Commit ec3d6542 authored by Eloy Duran's avatar Eloy Duran

Merge branch 'dependency-targets'. Closes #11.

parents 99417d11 340bdb1e
...@@ -4,3 +4,11 @@ generate_bridge_support! ...@@ -4,3 +4,11 @@ generate_bridge_support!
dependency 'ASIHTTPRequest' dependency 'ASIHTTPRequest'
dependency 'SBJson' dependency 'SBJson'
target :debug do
dependency 'CocoaLumberjack'
end
target :test, :exclusive => true do
dependency 'Kiwi'
end
...@@ -330,7 +330,7 @@ ...@@ -330,7 +330,7 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "${SRCROOT}/Pods/PodsResources.sh"; shellScript = "${SRCROOT}/Pods/Pods-resources.sh";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
......
...@@ -15,11 +15,9 @@ module Pod ...@@ -15,11 +15,9 @@ module Pod
@headers.map { |header| "-I '#{header.dirname}'" }.uniq @headers.map { |header| "-I '#{header.dirname}'" }.uniq
end end
def create_in(root) def save_as(pathname)
puts "==> Generating BridgeSupport metadata file" unless config.silent? puts "==> Generating BridgeSupport metadata file" unless config.silent?
file = root + "Pods.bridgesupport" gen_bridge_metadata %{-c "#{search_paths.join(' ')}" -o '#{pathname}' '#{headers.join("' '")}'}
gen_bridge_metadata %{-c "#{search_paths.join(' ')}" -o '#{file}' '#{headers.join("' '")}'}
file
end end
end end
end end
module Pod module Pod
class Installer class Installer
include Config::Mixin module Shared
def initialize(specification)
@specification = specification
end
def dependent_specification_sets def dependent_specification_sets
@dependent_specification_sets ||= Resolver.new(@specification).resolve @dependent_specification_sets ||= Resolver.new(@podfile, @definition ? @definition.dependencies : nil).resolve
end end
def build_specification_sets def build_specification_sets
...@@ -17,6 +12,17 @@ module Pod ...@@ -17,6 +12,17 @@ module Pod
def build_specifications def build_specifications
build_specification_sets.map(&:specification) build_specification_sets.map(&:specification)
end end
end
class Target
include Config::Mixin
include Shared
attr_reader :target
def initialize(podfile, xcodeproj, definition)
@podfile, @xcodeproj, @definition = podfile, xcodeproj, definition
end
def xcconfig def xcconfig
@xcconfig ||= Xcode::Config.new({ @xcconfig ||= Xcode::Config.new({
...@@ -29,75 +35,167 @@ module Pod ...@@ -29,75 +35,167 @@ module Pod
}) })
end end
def template def xcconfig_filename
@template ||= ProjectTemplate.new(@specification.platform) "#{@definition.lib_name}.xcconfig"
end end
def xcodeproj def copy_resources_script
@xcodeproj ||= Xcode::Project.new(template.xcodeproj_path) @copy_resources_script ||= Xcode::CopyResourcesScript.new(build_specifications.map do |spec|
spec.expanded_resources
end.flatten)
end
def copy_resources_filename
"#{@definition.lib_name}-resources.sh"
end
def bridge_support_generator
BridgeSupportGenerator.new(build_specifications.map do |spec|
spec.header_files.map do |header|
config.project_pods_root + header
end
end.flatten)
end
def bridge_support_filename
"#{@definition.lib_name}.bridgesupport"
end
# TODO move out
def save_prefix_header_as(pathname)
pathname.open('w') do |header|
header.puts "#ifdef __OBJC__"
header.puts "#import #{@podfile.platform == :ios ? '<UIKit/UIKit.h>' : '<Cocoa/Cocoa.h>'}"
header.puts "#endif"
end
end
def prefix_header_filename
"#{@definition.lib_name}-prefix.pch"
end end
# TODO move xcconfig related code into the xcconfig method, like copy_resources_script and generate_bridge_support. # TODO move xcconfig related code into the xcconfig method, like copy_resources_script and generate_bridge_support.
def generate_project def install!
puts "==> Generating Xcode project and xcconfig" unless config.silent? # First add the target to the project
@target = @xcodeproj.targets.new_static_library(@definition.lib_name)
user_header_search_paths = [] user_header_search_paths = []
build_specifications.each do |spec| build_specifications.each do |spec|
xcconfig.merge!(spec.xcconfig) xcconfig.merge!(spec.xcconfig)
group = xcodeproj.add_pod_group(spec.name)
# Only add implementation files to the compile phase # Only add implementation files to the compile phase
spec.implementation_files.each do |file| spec.implementation_files.each do |file|
group.add_source_file(file, nil, spec.compiler_flags) @target.add_source_file(file, nil, spec.compiler_flags)
end end
# Add header files to a `copy header build phase` for each destination # Add header files to a `copy header build phase` for each destination
# directory in the pod's header directory. # directory in the pod's header directory.
spec.copy_header_mappings.each do |header_dir, files| spec.copy_header_mappings.each do |header_dir, files|
copy_phase = xcodeproj.add_copy_header_build_phase(spec.name, header_dir) copy_phase = @target.copy_files_build_phases.new_pod_dir(spec.name, header_dir)
files.each do |file| files.each do |file|
group.add_source_file(file, copy_phase) @target.add_source_file(file, copy_phase)
end end
end end
# Collect all header search paths # Collect all header search paths
user_header_search_paths.concat(spec.user_header_search_paths) user_header_search_paths.concat(spec.user_header_search_paths)
end end
xcconfig.merge!('USER_HEADER_SEARCH_PATHS' => user_header_search_paths.sort.uniq.join(" ")) xcconfig.merge!('USER_HEADER_SEARCH_PATHS' => user_header_search_paths.sort.uniq.join(" "))
# Add all the target related support files to the group, even the copy
# resources script although the project doesn't actually use them.
support_files_group = @xcodeproj.groups.find do |group|
group.name == "Targets Support Files"
end.groups.new("name" => @definition.lib_name)
support_files_group.files.new('path' => copy_resources_filename)
prefix_file = support_files_group.files.new('path' => prefix_header_filename)
xcconfig_file = support_files_group.files.new("path" => xcconfig_filename)
# Assign the xcconfig as the base config of each config.
@target.buildConfigurations.each do |config|
config.baseConfiguration = xcconfig_file
config.buildSettings['GCC_PREFIX_HEADER'] = prefix_header_filename
end
end end
def copy_resources_script def create_files_in(root)
@copy_resources_script ||= Xcode::CopyResourcesScript.new(build_specifications.map { |spec| spec.expanded_resources }.flatten) xcconfig.save_as(root + xcconfig_filename)
if @podfile.generate_bridge_support?
bridge_support_generator.save_as(root + bridge_support_filename)
copy_resources_script.resources << bridge_support_filename
end
save_prefix_header_as(root + prefix_header_filename)
copy_resources_script.save_as(root + copy_resources_filename)
end
end end
def bridge_support_generator include Config::Mixin
BridgeSupportGenerator.new(build_specifications.map do |spec| include Shared
spec.header_files.map do |header|
config.project_pods_root + header def initialize(podfile)
@podfile = podfile
end
def template
@template ||= ProjectTemplate.new(@podfile.platform)
end
def xcodeproj
unless @xcodeproj
@xcodeproj = Xcode::Project.new(template.xcodeproj_path)
# First we need to resolve dependencies across *all* targets, so that the
# same correct versions of pods are being used for all targets. This
# happens when we call `build_specifications'.
build_specifications.each do |spec|
# Add all source files to the project grouped by pod
group = xcodeproj.add_pod_group(spec.name)
spec.expanded_source_files.each do |path|
group.children.new('path' => path.to_s)
end
end
# Add a group to hold all the target support files
xcodeproj.main_group.groups.new('name' => 'Targets Support Files')
end
@xcodeproj
end
def targets
@targets ||= @podfile.targets.values.map do |target_definition|
Target.new(@podfile, xcodeproj, target_definition)
end end
end.flatten)
end end
def install! def install!
puts "Installing dependencies of: #{@specification.defined_in_file}" unless config.silent? puts "Installing dependencies of: #{@podfile.defined_in_file}" unless config.silent?
build_specifications.each(&:install!) build_specifications.each(&:install!)
generate_project
root = config.project_pods_root root = config.project_pods_root
puts " * Copying contents of template directory `#{template.path}' to `#{root}'" if config.verbose? puts " * Copying contents of template directory `#{template.path}' to `#{root}'" if config.verbose?
template.copy_to(root) template.copy_to(root)
puts "==> Generating Xcode project and xcconfig" unless config.silent?
targets.each do |target|
target.install!
target.create_files_in(root)
end
pbxproj = File.join(root, 'Pods.xcodeproj') pbxproj = File.join(root, 'Pods.xcodeproj')
puts " * Writing Xcode project file to `#{pbxproj}'" if config.verbose? puts " * Writing Xcode project file to `#{pbxproj}'" if config.verbose?
xcodeproj.save_as(pbxproj) xcodeproj.save_as(pbxproj)
xcconfig.create_in(root)
if @specification.generate_bridge_support?
path = bridge_support_generator.create_in(root)
copy_resources_script.resources << path.relative_path_from(config.project_pods_root)
end
copy_resources_script.create_in(root)
build_specifications.each(&:post_install) # Post install hooks run last!
targets.each do |target|
target.build_specifications.each { |spec| spec.post_install(target) }
end
end end
# For now this assumes just one pods target, i.e. only libPods.a.
# Not sure yet if we should try to be smart with apps that have multiple
# targets and try to map pod targets to those app targets.
#
# Possible options are:
# 1. Only cater to the most simple setup
# 2. Try to automagically figure it out by name. For example, a pod target
# called `:some_target' could map to an app target called `SomeTarget'.
# (A variation would be to not even camelize the target name, but simply
# let the user specify it with the proper case.)
# 3. Let the user specify the app target name as an extra argument, but this
# seems to be a less good version of the variation on #2.
def configure_project(projpath) def configure_project(projpath)
root = File.dirname(projpath) root = File.dirname(projpath)
xcworkspace = File.join(root, File.basename(projpath, '.xcodeproj') + '.xcworkspace') xcworkspace = File.join(root, File.basename(projpath, '.xcodeproj') + '.xcworkspace')
...@@ -118,8 +216,8 @@ module Pod ...@@ -118,8 +216,8 @@ module Pod
'lastKnownFileType' => 'text.xcconfig' 'lastKnownFileType' => 'text.xcconfig'
}) })
app_project.targets.each do |target| app_project.targets.each do |target|
target.buildConfigurationList.buildConfigurations.each do |config| target.buildConfigurations.each do |config|
config.baseConfigurationReference = configfile config.baseConfiguration = configfile
end end
end end
app_project.main_group << configfile app_project.main_group << configfile
...@@ -131,7 +229,7 @@ module Pod ...@@ -131,7 +229,7 @@ module Pod
'sourceTree' => 'BUILT_PRODUCTS_DIR' 'sourceTree' => 'BUILT_PRODUCTS_DIR'
}) })
app_project.objects.select_by_class(Xcode::Project::PBXFrameworksBuildPhase).each do |build_phase| app_project.objects.select_by_class(Xcode::Project::PBXFrameworksBuildPhase).each do |build_phase|
build_phase.files << libfile.build_file build_phase.files << libfile.buildFiles.new
end end
app_project.main_group << libfile app_project.main_group << libfile
...@@ -143,7 +241,7 @@ module Pod ...@@ -143,7 +241,7 @@ module Pod
'outputPaths' => [], 'outputPaths' => [],
'runOnlyForDeploymentPostprocessing' => '0', 'runOnlyForDeploymentPostprocessing' => '0',
'shellPath' => '/bin/sh', 'shellPath' => '/bin/sh',
'shellScript' => "${SRCROOT}/Pods/PodsResources.sh\n" 'shellScript' => "${SRCROOT}/Pods/Pods-resources.sh\n"
}) })
app_project.targets.each { |target| target.buildPhases << copy_resources } app_project.targets.each { |target| target.buildPhases << copy_resources }
......
module Pod module Pod
class Podfile class Podfile
class Target
attr_reader :name, :parent, :target_dependencies
def initialize(name, parent = nil)
@name, @parent, @target_dependencies = name, parent, []
end
def lib_name
name == :default ? "Pods" : "Pods-#{name}"
end
# Returns *all* dependencies of this target, not only the target specific
# ones in `target_dependencies`.
def dependencies
@target_dependencies + (@parent ? @parent.dependencies : [])
end
end
def self.from_file(path) def self.from_file(path)
podfile = Podfile.new do podfile = Podfile.new do
eval(path.read, nil, path.to_s) eval(path.read, nil, path.to_s)
...@@ -9,8 +27,10 @@ module Pod ...@@ -9,8 +27,10 @@ module Pod
podfile podfile
end end
include Config::Mixin
def initialize(&block) def initialize(&block)
@dependencies = [] @targets = { :default => (@target = Target.new(:default)) }
instance_eval(&block) instance_eval(&block)
end end
...@@ -58,10 +78,12 @@ module Pod ...@@ -58,10 +78,12 @@ module Pod
# * http://semver.org # * http://semver.org
# * http://docs.rubygems.org/read/chapter/7 # * http://docs.rubygems.org/read/chapter/7
def dependency(name, *version_requirements) def dependency(name, *version_requirements)
@dependencies << Dependency.new(name, *version_requirements) @target.target_dependencies << Dependency.new(name, *version_requirements)
end end
attr_reader :dependencies def dependencies
@targets.values.map(&:target_dependencies).flatten
end
# Specifies that a BridgeSupport metadata should be generated from the # Specifies that a BridgeSupport metadata should be generated from the
# headers of all installed Pods. # headers of all installed Pods.
...@@ -72,6 +94,42 @@ module Pod ...@@ -72,6 +94,42 @@ module Pod
@generate_bridge_support = true @generate_bridge_support = true
end end
attr_reader :targets
# Defines a new static library target and scopes dependencies defined from
# the given block. The target will by default include the dependencies
# defined outside of the block, unless the `:exclusive => true` option is
# given.
#
# Consider the following Podfile:
#
# dependency 'ASIHTTPRequest'
#
# target :debug do
# dependency 'SSZipArchive'
# end
#
# target :test, :exclusive => true do
# dependency 'JSONKit'
# end
#
# This Podfile defines three targets. The first one is the `:default` target,
# which produces the `libPods.a` file. The second and third are the `:debug`
# and `:test` ones, which produce the `libPods-debug.a` and `libPods-test.a`
# files.
#
# The `:default` target has only one dependency (ASIHTTPRequest), whereas the
# `:debug` target has two (ASIHTTPRequest, SSZipArchive). The `:test` target,
# however, is an exclusive target which means it will only have one
# dependency (JSONKit).
def target(name, options = {})
parent = @target
@targets[name] = @target = Target.new(name, options[:exclusive] ? nil : parent)
yield
ensure
@target = parent
end
# This is to be compatible with a Specification for use in the Installer and # This is to be compatible with a Specification for use in the Installer and
# Resolver. # Resolver.
...@@ -86,13 +144,13 @@ module Pod ...@@ -86,13 +144,13 @@ module Pod
end end
def dependency_by_name(name) def dependency_by_name(name)
@dependencies.find { |d| d.name == name } dependencies.find { |d| d.name == name }
end end
def validate! def validate!
lines = [] lines = []
lines << "* the `platform` attribute should be either `:osx` or `:ios`" unless [:osx, :ios].include?(@platform) lines << "* the `platform` attribute should be either `:osx` or `:ios`" unless [:osx, :ios].include?(@platform)
lines << "* no dependencies were specified, which is, well, kinda pointless" if @dependencies.empty? lines << "* no dependencies were specified, which is, well, kinda pointless" if dependencies.empty?
raise(Informative, (["The Podfile at `#{@defined_in_file}' is invalid:"] + lines).join("\n")) unless lines.empty? raise(Informative, (["The Podfile at `#{@defined_in_file}' is invalid:"] + lines).join("\n")) unless lines.empty?
end end
end end
......
module Pod module Pod
class Resolver class Resolver
def initialize(specification) def initialize(specification, dependencies = nil)
@specification = specification @specification, @dependencies = specification, dependencies || specification.dependencies
end end
def resolve def resolve
@sets = [] @sets = []
find_dependency_sets(@specification) find_dependency_sets(@specification, @dependencies)
@sets @sets
end end
def find_dependency_sets(specification) def find_dependency_sets(specification, dependencies = nil)
specification.dependencies.each do |dependency| (dependencies || specification.dependencies).each do |dependency|
set = find_dependency_set(dependency) set = find_dependency_set(dependency)
set.required_by(specification) set.required_by(specification)
unless @sets.include?(set) unless @sets.include?(set)
......
...@@ -325,17 +325,18 @@ module Pod ...@@ -325,17 +325,18 @@ module Pod
# This is a convenience method which gets called after all pods have been # This is a convenience method which gets called after all pods have been
# downloaded, installed, and the Xcode project and related files have been # downloaded, installed, and the Xcode project and related files have been
# generated. Override this to, for instance, add to the prefix header: # generated. (It receives the Pod::Installer::Target instance for the current
# target.) Override this to, for instance, add to the prefix header:
# #
# Pod::Spec.new do |s| # Pod::Spec.new do |s|
# def s.post_install # def s.post_install(target)
# prefix_header = config.project_pods_root + 'Pods-Prefix.pch' # prefix_header = config.project_pods_root + target.prefix_header_filename
# prefix_header.open('a') do |file| # prefix_header.open('a') do |file|
# file.puts(%{#ifdef __OBJC__\n#import "SSToolkitDefines.h"\n#endif}) # file.puts(%{#ifdef __OBJC__\n#import "SSToolkitDefines.h"\n#endif})
# end # end
# end # end
# end # end
def post_install def post_install(target)
end end
end end
......
...@@ -25,8 +25,8 @@ module Pod ...@@ -25,8 +25,8 @@ module Pod
@attributes.map { |key, value| "#{key} = #{value}" }.join("\n") @attributes.map { |key, value| "#{key} = #{value}" }.join("\n")
end end
def create_in(pods_root) def save_as(pathname)
(pods_root + 'Pods.xcconfig').open('w') { |file| file << to_s } pathname.open('w') { |file| file << to_s }
end end
end end
end end
......
module Pod module Pod
module Xcode module Xcode
class CopyResourcesScript class CopyResourcesScript
CONTENT = <<EOS
#!/bin/sh
install_resource()
{
echo "cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}
}
EOS
attr_reader :resources attr_reader :resources
# A list of files relative to the project pods root. # A list of files relative to the project pods root.
...@@ -8,13 +18,15 @@ module Pod ...@@ -8,13 +18,15 @@ module Pod
@resources = resources @resources = resources
end end
def create_in(root) def save_as(pathname)
return if @resources.empty? pathname.open('w') do |script|
(root + 'PodsResources.sh').open('a') do |script| script.puts CONTENT
@resources.each do |resource| @resources.each do |resource|
script.puts "install_resource '#{resource}'" script.puts "install_resource '#{resource}'"
end end
end end
# TODO use File api
system("chmod +x '#{pathname}'")
end end
end end
end end
......
...@@ -5,11 +5,88 @@ module Pod ...@@ -5,11 +5,88 @@ module Pod
module Xcode module Xcode
class Project class Project
class PBXObject class PBXObject
def self.attributes_accessor(*names) def self.attribute(attribute_name, accessor_name = nil)
names.each do |name| attribute_name = attribute_name.to_s
name = name.to_s name = (accessor_name || attribute_name).to_s
define_method(name) { @attributes[name] } define_method(name) { @attributes[attribute_name] }
define_method("#{name}=") { |value| @attributes[name] = value } define_method("#{name}=") { |value| @attributes[attribute_name] = value }
end
def self.attributes(*names)
names.each { |name| attribute(name) }
end
def self.has_many(plural_attr_name, options = {}, &block)
klass = options[:class] || PBXFileReference
singular_attr_name = options[:singular] || plural_attr_name.to_s[0..-2] # strip off 's'
if options[:fkey_on_target]
define_method(plural_attr_name) do
scoped = @project.objects.select_by_class(klass).select do |object|
object.send(options[:uuid]) == self.uuid
end
PBXObjectList.new(klass, @project, scoped) do |object|
object.send("#{options[:uuid]}=", self.uuid)
end
end
else
uuid_list_name = options[:uuid] || "#{singular_attr_name}References"
attribute(plural_attr_name, uuid_list_name)
define_method(plural_attr_name) do
uuids = send(uuid_list_name)
if block
list_by_class(uuids, klass) do |object|
instance_exec(object, &block)
end
else
list_by_class(uuids, klass)
end
end
define_method("#{plural_attr_name}=") do |objects|
send("#{uuid_list_name}=", objects.map(&:uuid))
end
end
end
def self.belongs_to(singular_attr_name, options = {})
if uuid_name = options[:uuids]
# part of another objects uuid list
klass = options[:class]
define_method(singular_attr_name) do
# Loop over all objects of the class and find the one that includes
# this object in the specified uuid list.
@project.objects.select_by_class(klass).find do |object|
object.send(uuid_name).include?(self.uuid)
end
end
define_method("#{singular_attr_name}=") do |object|
# Remove this object from the uuid list of the target
# that this object was associated to.
if previous = send(singular_attr_name)
previous.send(uuid_name).delete(self.uuid)
end
# Now assign this object to the new object
object.send(uuid_name) << self.uuid
end
else
uuid_name = options[:uuid] || "#{singular_attr_name}Reference"
attribute(options[:uuid] || singular_attr_name, uuid_name)
define_method(singular_attr_name) do
uuid = send(uuid_name)
@project.objects[uuid]
end
define_method("#{singular_attr_name}=") do |object|
send("#{uuid_name}=", object.uuid)
end
end
end
def self.has_one(singular_attr_name, options = {})
klass = options[:class]
uuid_name = options[:uuid] || "#{singular_attr_name}Reference"
define_method(singular_attr_name) do
@project.objects.select_by_class(klass).find do |object|
object.respond_to?(uuid_name) && object.send(uuid_name) == self.uuid
end
end end
end end
...@@ -18,13 +95,23 @@ module Pod ...@@ -18,13 +95,23 @@ module Pod
end end
attr_reader :uuid, :attributes attr_reader :uuid, :attributes
attributes_accessor :isa, :name attributes :isa, :name
def initialize(project, uuid, attributes) def initialize(project, uuid, attributes)
@project, @uuid, @attributes = project, uuid || generate_uuid, attributes @project, @attributes = project, attributes
unless uuid
# Add new objects to the main hash with a unique UUID
begin; uuid = generate_uuid; end while @project.objects_hash.has_key?(uuid)
@project.objects_hash[uuid] = @attributes
end
@uuid = uuid
self.isa ||= self.class.isa self.isa ||= self.class.isa
end end
def ==(other)
other.is_a?(PBXObject) && self.uuid == other.uuid
end
def inspect def inspect
"#<#{isa} UUID: `#{uuid}', name: `#{name}'>" "#<#{isa} UUID: `#{uuid}', name: `#{name}'>"
end end
...@@ -40,179 +127,263 @@ module Pod ...@@ -40,179 +127,263 @@ module Pod
uuid.gsub('-', '')[0..23] uuid.gsub('-', '')[0..23]
end end
def list_by_class(uuids, klass, scoped = nil) def list_by_class(uuids, klass, scoped = nil, &block)
unless scoped unless scoped
scoped = uuids.map { |uuid| @project.objects[uuid] }.select { |o| o.is_a?(klass) } scoped = uuids.map { |uuid| @project.objects[uuid] }.select { |o| o.is_a?(klass) }
end end
if block
PBXObjectList.new(klass, @project, scoped, &block)
else
PBXObjectList.new(klass, @project, scoped) do |object| PBXObjectList.new(klass, @project, scoped) do |object|
# Add the uuid of a newly created object to the uuids list # Add the uuid of a newly created object to the uuids list
uuids << object.uuid uuids << object.uuid
end end
end end
end end
end
class PBXGroup < PBXObject # Missing constants that begin with either `PBX' or `XC' are assumed to be
attributes_accessor :sourceTree, :children # valid classes in a Xcode project. A new PBXObject subclass is created
# for the constant and returned.
def self.const_missing(name)
if name =~ /^(PBX|XC)/
klass = Class.new(PBXObject)
const_set(name, klass)
klass
else
super
end
end
class PBXFileReference < PBXObject
attributes :path, :sourceTree, :explicitFileType, :includeInIndex
has_many :buildFiles, :uuid => :fileRef, :fkey_on_target => true, :class => Project::PBXBuildFile
belongs_to :group, :class => Project::PBXGroup, :uuids => :childReferences
def initialize(project, uuid, attributes) def initialize(project, uuid, attributes)
is_new = uuid.nil?
super super
self.sourceTree ||= '<group>' self.path = path if path # sets default name
self.children ||= [] self.sourceTree ||= 'SOURCE_ROOT'
if is_new
@project.main_group.children << self
end end
def files
list_by_class(children, PBXFileReference)
end end
def source_files alias_method :_path=, :path=
list_by_class(children, PBXFileReference, files.select { |file| !file.build_file.nil? }) def path=(path)
self._path = path
self.name ||= pathname.basename.to_s
path
end end
def groups def pathname
list_by_class(children, PBXGroup) Pathname.new(path)
end
end end
def add_source_file(path, copy_header_phase = nil, compiler_flags = nil) class PBXGroup < PBXObject
file = files.new('path' => path.to_s) attributes :sourceTree
build_file = file.build_file
if path.extname == '.h' has_many :children, :singular => :child do |object|
build_file.settings = { 'ATTRIBUTES' => ["Public"] } if object.is_a?(Pod::Xcode::Project::PBXFileReference)
# Working around a bug in Xcode 4.2 betas, remove this once the Xcode bug is fixed: # Associating the file to this group through the inverse
# https://github.com/alloy/cocoapods/issues/13 # association will also remove it from the group it was in.
#phase = copy_header_phase || @project.headers_build_phases.first object.group = self
phase = copy_header_phase || @project.copy_files_build_phases.first # TODO is this really needed?
phase.files << build_file
else else
build_file.settings = { 'COMPILER_FLAGS' => compiler_flags } if compiler_flags # TODO What objects can actually be in a group and don't they
@project.source_build_phase.files << build_file # all need the above treatment.
childReferences << object.uuid
end end
file
end end
def <<(child) def initialize(*)
children << child.uuid super
end self.sourceTree ||= '<group>'
self.childReferences ||= []
end end
class PBXFileReference < PBXObject def files
attributes_accessor :path, :sourceTree list_by_class(childReferences, Pod::Xcode::Project::PBXFileReference) do |file|
file.group = self
end
end
def initialize(project, uuid, attributes) def source_files
is_new = uuid.nil? files = self.files.reject { |file| file.buildFiles.empty? }
super list_by_class(childReferences, Pod::Xcode::Project::PBXFileReference, files) do |file|
self.name ||= pathname.basename.to_s file.group = self
self.sourceTree ||= 'SOURCE_ROOT'
if is_new
@project.build_files.new.file = self
end end
end end
def pathname def groups
Pathname.new(path) list_by_class(childReferences, Pod::Xcode::Project::PBXGroup)
end end
def build_file def <<(child)
@project.build_files.find { |o| o.fileRef == uuid } children << child
end end
end end
class PBXBuildFile < PBXObject class PBXBuildFile < PBXObject
attributes_accessor :fileRef, :settings attributes :settings
belongs_to :file, :uuid => :fileRef
# Takes a PBXFileReference instance and assigns its uuid to the fileRef attribute.
def file=(file)
self.fileRef = file.uuid
end end
# Returns a PBXFileReference instance corresponding to the uuid in the fileRef attribute. class PBXBuildPhase < PBXObject
def file # TODO rename this to buildFiles and add a files :through => :buildFiles shortcut
@project.objects[fileRef] has_many :files, :class => PBXBuildFile
attributes :buildActionMask, :runOnlyForDeploymentPostprocessing
def initialize(*)
super
self.fileReferences ||= []
# These are always the same, no idea what they are.
self.buildActionMask ||= "2147483647"
self.runOnlyForDeploymentPostprocessing ||= "0"
end end
end end
class PBXBuildPhase < PBXObject class PBXCopyFilesBuildPhase < PBXBuildPhase
attributes_accessor :files attributes :dstPath, :dstSubfolderSpec
alias_method :file_uuids, :files
alias_method :file_uuids=, :files=
def initialize(project, uuid, attributes) def self.new_pod_dir(project, pod_name, path)
super new(project, nil, {
self.file_uuids ||= [] "dstPath" => "$(PUBLIC_HEADERS_FOLDER_PATH)/#{path}",
"name" => "Copy #{pod_name} Public Headers",
})
end end
def files def initialize(*)
list_by_class(file_uuids, PBXBuildFile) super
self.dstSubfolderSpec ||= "16"
end end
end end
class PBXSourcesBuildPhase < PBXBuildPhase; end class PBXSourcesBuildPhase < PBXBuildPhase; end
class PBXCopyFilesBuildPhase < PBXBuildPhase; end
class PBXFrameworksBuildPhase < PBXBuildPhase; end class PBXFrameworksBuildPhase < PBXBuildPhase; end
class PBXShellScriptBuildPhase < PBXBuildPhase class PBXShellScriptBuildPhase < PBXBuildPhase
attributes_accessor :shellScript attribute :shellScript
end end
class PBXNativeTarget < PBXObject class PBXNativeTarget < PBXObject
attributes_accessor :buildPhases, :buildConfigurationList STATIC_LIBRARY = 'com.apple.product-type.library.static'
alias_method :build_phase_uuids, :buildPhases
alias_method :build_phase_uuids=, :buildPhases=
alias_method :build_configuration_list_uuid, :buildConfigurationList
alias_method :build_configuration_list_uuid=, :buildConfigurationList=
def buildPhases attributes :productName, :productType
list_by_class(build_phase_uuids, PBXBuildPhase)
end
def buildConfigurationList has_many :buildPhases, :class => PBXBuildPhase
@project.objects[build_configuration_list_uuid] has_many :dependencies, :singular => :dependency # TODO :class => ?
end has_many :buildRules # TODO :class => ?
belongs_to :buildConfigurationList
belongs_to :product, :uuid => :productReference
def self.new_static_library(project, productName)
# TODO should probably switch the uuid and attributes argument
target = new(project, nil, 'productType' => STATIC_LIBRARY, 'productName' => productName)
target.product.path = "lib#{productName}.a"
target.product.includeInIndex = "0" # no idea what this is
target.product.explicitFileType = "archive.ar"
target.buildPhases.add(PBXSourcesBuildPhase)
def buildConfigurationList=(config_list) buildPhase = target.buildPhases.add(PBXFrameworksBuildPhase)
self.build_configuration_list_uuid = config_list.uuid project.groups.find { |g| g.name == 'Frameworks' }.files.each do |framework|
buildPhase.files << framework.buildFiles.new
end end
target.buildPhases.add(PBXCopyFilesBuildPhase, 'dstPath' => '$(PUBLIC_HEADERS_FOLDER_PATH)')
target
end end
class XCBuildConfiguration < PBXObject def initialize(project, *)
attributes_accessor :baseConfigurationReference super
alias_method :base_configuration_reference_uuid, :baseConfigurationReference self.name ||= productName
alias_method :base_configuration_reference_uuid=, :baseConfigurationReference= self.buildRuleReferences ||= []
self.dependencyReferences ||= []
self.buildPhaseReferences ||= []
def baseConfigurationReference unless buildConfigurationList
@project.objects[base_configuration_reference_uuid] self.buildConfigurationList = project.objects.add(XCConfigurationList)
# TODO or should this happen in buildConfigurationList?
buildConfigurationList.buildConfigurations.new('name' => 'Debug')
buildConfigurationList.buildConfigurations.new('name' => 'Release')
end end
def baseConfigurationReference=(config) unless product
self.base_configuration_reference_uuid = config.uuid self.product = project.files.new('sourceTree' => 'BUILT_PRODUCTS_DIR')
product.group = project.products
end end
end end
class XCConfigurationList < PBXObject
attributes_accessor :buildConfigurations
alias_method :build_configuration_uuids, :buildConfigurations
alias_method :build_configuration_uuids=, :buildConfigurations=
def buildConfigurations def buildConfigurations
list_by_class(build_configuration_uuids, XCBuildConfiguration) buildConfigurationList.buildConfigurations
end end
def buildConfigurations=(configs) def source_build_phases
self.build_configuration_uuids = configs.map(&:uuid) buildPhases.select_by_class(PBXSourcesBuildPhase)
end end
def copy_files_build_phases
buildPhases.select_by_class(PBXCopyFilesBuildPhase)
end end
# Missing constants that begin with either `PBX' or `XC' are assumed to be def frameworks_build_phases
# valid classes in a Xcode project. A new PBXObject subclass is created buildPhases.select_by_class(PBXFrameworksBuildPhase)
# for the constant and returned. end
def self.const_missing(name)
if name =~ /^(PBX|XC)/ # Finds an existing file reference or creates a new one.
klass = Class.new(PBXObject) def add_source_file(path, copy_header_phase = nil, compiler_flags = nil)
const_set(name, klass) file = @project.files.find { |file| file.path == path.to_s } || @project.files.new('path' => path.to_s)
klass buildFile = file.buildFiles.new
if path.extname == '.h'
buildFile.settings = { 'ATTRIBUTES' => ["Public"] }
# Working around a bug in Xcode 4.2 betas, remove this once the Xcode bug is fixed:
# https://github.com/alloy/cocoapods/issues/13
#phase = copy_header_phase || headers_build_phases.first
phase = copy_header_phase || copy_files_build_phases.first
phase.files << buildFile
else else
buildFile.settings = { 'COMPILER_FLAGS' => compiler_flags } if compiler_flags
source_build_phases.first.files << buildFile
end
file
end
end
class XCBuildConfiguration < PBXObject
attribute :buildSettings
belongs_to :baseConfiguration, :uuid => :baseConfigurationReference
def initialize(*)
super super
# TODO These are from an iOS static library, need to check if it works for any product type
self.buildSettings = {
'DSTROOT' => '/tmp/Pods.dst',
'GCC_PRECOMPILE_PREFIX_HEADER' => 'YES',
'GCC_VERSION' => 'com.apple.compilers.llvm.clang.1_0',
# The OTHER_LDFLAGS option *has* to be overriden so that it does not
# use those from the xcconfig (for CocoaPods specifically).
'OTHER_LDFLAGS' => '',
'PRODUCT_NAME' => '$(TARGET_NAME)',
'SKIP_INSTALL' => 'YES',
}.merge(buildSettings || {})
end end
end end
class XCConfigurationList < PBXObject
has_many :buildConfigurations, :class => XCBuildConfiguration
def initialize(*)
super
self.buildConfigurationReferences ||= []
end
end
class PBXProject < PBXObject
has_many :targets, :class => PBXNativeTarget
belongs_to :products, :uuid => :productRefGroup, :class => PBXGroup
end
class PBXObjectList class PBXObjectList
include Enumerable include Enumerable
...@@ -223,6 +394,10 @@ module Pod ...@@ -223,6 +394,10 @@ module Pod
@callback = new_object_callback @callback = new_object_callback
end end
def empty?
@scoped_hash.empty?
end
def [](uuid) def [](uuid)
if hash = @scoped_hash[uuid] if hash = @scoped_hash[uuid]
Project.const_get(hash['isa']).new(@project, uuid, hash) Project.const_get(hash['isa']).new(@project, uuid, hash)
...@@ -231,14 +406,12 @@ module Pod ...@@ -231,14 +406,12 @@ module Pod
def add(klass, hash = {}) def add(klass, hash = {})
object = klass.new(@project, nil, hash) object = klass.new(@project, nil, hash)
@project.objects_hash[object.uuid] = object.attributes @callback.call(object) if @callback
object object
end end
def new(hash = {}) def new(hash = {})
object = add(@represented_class, hash) add(@represented_class, hash)
@callback.call(object) if @callback
object
end end
def <<(object) def <<(object)
...@@ -251,14 +424,42 @@ module Pod ...@@ -251,14 +424,42 @@ module Pod
end end
end end
def ==(other)
self.to_a == other.to_a
end
def first
to_a.first
end
def last
to_a.last
end
def inspect def inspect
"<PBXObjectList: #{map(&:inspect)}>" "<PBXObjectList: #{map(&:inspect)}>"
end end
# Only makes sense on the list that has the full objects_hash as its scoped hash. # Only makes sense on lists that contain mixed classes.
def select_by_class(klass) def select_by_class(klass)
scoped = @project.objects_hash.select { |_, attr| attr['isa'] == klass.isa } scoped = @scoped_hash.select { |_, attr| attr['isa'] == klass.isa }
PBXObjectList.new(klass, @project, scoped) PBXObjectList.new(klass, @project, scoped) do |object|
# Objects added to the subselection should still use the same
# callback as this list.
self << object
end
end
def method_missing(name, *args, &block)
if @represented_class.respond_to?(name)
object = @represented_class.send(name, @project, *args)
# The callbacks are only for PBXObject instances instantiated
# from the class method that we forwarded the message to.
@callback.call(object) if object.is_a?(PBXObject)
object
else
super
end
end end
end end
...@@ -279,13 +480,17 @@ module Pod ...@@ -279,13 +480,17 @@ module Pod
@objects ||= PBXObjectList.new(PBXObject, self, objects_hash) @objects ||= PBXObjectList.new(PBXObject, self, objects_hash)
end end
# TODO This should probably be the actual Project class (PBXProject).
def project_object
objects[@plist['rootObject']]
end
def groups def groups
objects.select_by_class(PBXGroup) objects.select_by_class(PBXGroup)
end end
def main_group def main_group
project = objects[@plist['rootObject']] objects[project_object.attributes['mainGroup']]
objects[project.attributes['mainGroup']]
end end
# Shortcut access to the `Pods' PBXGroup. # Shortcut access to the `Pods' PBXGroup.
...@@ -306,16 +511,14 @@ module Pod ...@@ -306,16 +511,14 @@ module Pod
objects.select_by_class(PBXBuildFile) objects.select_by_class(PBXBuildFile)
end end
def source_build_phase def targets
objects.find { |o| o.is_a?(PBXSourcesBuildPhase) } # Better to check the project object for targets to ensure they are
end # actually there so the project will work
project_object.targets
def copy_files_build_phases
objects.select_by_class(PBXCopyFilesBuildPhase)
end end
def targets def products
objects.select_by_class(PBXNativeTarget) project_object.products
end end
IGNORE_GROUPS = ['Pods', 'Frameworks', 'Products', 'Supporting Files'] IGNORE_GROUPS = ['Pods', 'Frameworks', 'Products', 'Supporting Files']
...@@ -333,24 +536,6 @@ module Pod ...@@ -333,24 +536,6 @@ module Pod
FileUtils.mkdir_p(projpath) FileUtils.mkdir_p(projpath)
@plist.writeToFile(File.join(projpath, 'project.pbxproj'), atomically:true) @plist.writeToFile(File.join(projpath, 'project.pbxproj'), atomically:true)
end end
# TODO add comments, or even constants, describing what these magic numbers are.
def add_copy_header_build_phase(name, path)
phase = copy_files_build_phases.new({
"buildActionMask" => "2147483647",
"dstPath" => "$(PUBLIC_HEADERS_FOLDER_PATH)/#{path}",
"dstSubfolderSpec" => "16",
"name" => "Copy #{name} Public Headers",
"runOnlyForDeploymentPostprocessing" => "0",
})
targets.first.buildPhases << phase
phase
end
# A silly hack to pretty print the objects hash from MacRuby.
def pretty_print
puts `ruby -r pp -e 'pp(#{@template.inspect})'`
end
end end
end end
end end
...@@ -38,8 +38,6 @@ else ...@@ -38,8 +38,6 @@ else
config.silent = true config.silent = true
config.repos_dir = fixture('spec-repos') config.repos_dir = fixture('spec-repos')
config.project_pods_root = temporary_directory + 'Pods' config.project_pods_root = temporary_directory + 'Pods'
def config.ios?; true; end
def config.osx?; false; end
FileUtils.cp_r(fixture('integration/.'), config.project_pods_root) FileUtils.cp_r(fixture('integration/.'), config.project_pods_root)
end end
...@@ -51,6 +49,9 @@ else ...@@ -51,6 +49,9 @@ else
# TODO add a simple source file which uses the compiled lib to check that it really really works # TODO add a simple source file which uses the compiled lib to check that it really really works
it "should activate required pods and create a working static library xcode project" do it "should activate required pods and create a working static library xcode project" do
spec = Pod::Podfile.new do spec = Pod::Podfile.new do
# first ensure that the correct info is available to the specs when they load
config.rootspec = self
self.platform platform self.platform platform
dependency 'ASIWebPageRequest', '>= 1.8.1' dependency 'ASIWebPageRequest', '>= 1.8.1'
dependency 'JSONKit', '>= 1.0' dependency 'JSONKit', '>= 1.0'
...@@ -61,26 +62,29 @@ else ...@@ -61,26 +62,29 @@ else
installer.install! installer.install!
root = config.project_pods_root root = config.project_pods_root
(root + 'Reachability.podspec').should.exist (root + 'Reachability.podspec').should.exist if platform == :ios
(root + 'ASIHTTPRequest.podspec').should.exist (root + 'ASIHTTPRequest.podspec').should.exist
(root + 'ASIWebPageRequest.podspec').should.exist (root + 'ASIWebPageRequest.podspec').should.exist
(root + 'JSONKit.podspec').should.exist (root + 'JSONKit.podspec').should.exist
(root + 'SSZipArchive.podspec').should.exist (root + 'SSZipArchive.podspec').should.exist
(root + 'Pods.xcconfig').read.should == installer.xcconfig.to_s (root + 'Pods.xcconfig').read.should == installer.targets.first.xcconfig.to_s
project_file = (root + 'Pods.xcodeproj/project.pbxproj').to_s project_file = (root + 'Pods.xcodeproj/project.pbxproj').to_s
NSDictionary.dictionaryWithContentsOfFile(project_file).should == installer.xcodeproj.to_hash NSDictionary.dictionaryWithContentsOfFile(project_file).should == installer.xcodeproj.to_hash
#puts "\n[!] Compiling static library..." puts "\n[!] Compiling static library..."
#Dir.chdir(config.project_pods_root) do Dir.chdir(config.project_pods_root) do
#system("xcodebuild > /dev/null 2>&1").should == true system("xcodebuild > /dev/null 2>&1").should == true
#system("xcodebuild").should == true #system("xcodebuild").should == true
#end end
end end
it "does not activate pods that are only part of other pods" do it "does not activate pods that are only part of other pods" do
spec = Pod::Podfile.new do spec = Pod::Podfile.new do
# first ensure that the correct info is available to the specs when they load
config.rootspec = self
self.platform platform self.platform platform
dependency 'Reachability' dependency 'Reachability'
end end
...@@ -94,16 +98,18 @@ else ...@@ -94,16 +98,18 @@ else
it "adds resources to the xcode copy script" do it "adds resources to the xcode copy script" do
spec = Pod::Podfile.new do spec = Pod::Podfile.new do
# first ensure that the correct info is available to the specs when they load
config.rootspec = self
self.platform platform self.platform platform
dependency 'SSZipArchive' dependency 'SSZipArchive'
end end
installer = SpecHelper::Installer.new(spec) installer = SpecHelper::Installer.new(spec)
dependency_spec = installer.build_specifications.first installer.targets.first.build_specifications.first.resources = 'LICEN*', 'Readme.*'
dependency_spec.resources = 'LICEN*', 'Readme.*'
installer.install! installer.install!
contents = (config.project_pods_root + 'PodsResources.sh').read contents = (config.project_pods_root + 'Pods-resources.sh').read
contents.should.include "install_resource 'SSZipArchive/LICENSE'\n" \ contents.should.include "install_resource 'SSZipArchive/LICENSE'\n" \
"install_resource 'SSZipArchive/Readme.markdown'" "install_resource 'SSZipArchive/Readme.markdown'"
end end
...@@ -111,6 +117,9 @@ else ...@@ -111,6 +117,9 @@ else
# TODO we need to do more cleaning and/or add a --prune task # TODO we need to do more cleaning and/or add a --prune task
it "overwrites an existing project.pbxproj file" do it "overwrites an existing project.pbxproj file" do
spec = Pod::Podfile.new do spec = Pod::Podfile.new do
# first ensure that the correct info is available to the specs when they load
config.rootspec = self
self.platform platform self.platform platform
dependency 'JSONKit' dependency 'JSONKit'
end end
...@@ -120,18 +129,60 @@ else ...@@ -120,18 +129,60 @@ else
Pod::Source.reset! Pod::Source.reset!
Pod::Spec::Set.reset! Pod::Spec::Set.reset!
spec = Pod::Podfile.new do spec = Pod::Podfile.new do
# first ensure that the correct info is available to the specs when they load
config.rootspec = self
self.platform platform self.platform platform
dependency 'SSZipArchive' dependency 'SSZipArchive'
end end
installer = SpecHelper::Installer.new(spec) installer = SpecHelper::Installer.new(spec)
installer.install! installer.install!
installer = Pod::Installer.new(spec)
installer.generate_project
project = Pod::Xcode::Project.new(config.project_pods_root + 'Pods.xcodeproj') project = Pod::Xcode::Project.new(config.project_pods_root + 'Pods.xcodeproj')
project.source_files.should == installer.xcodeproj.source_files project.source_files.should == installer.xcodeproj.source_files
end end
it "creates a project with multiple targets" do
Pod::Source.reset!
Pod::Spec::Set.reset!
podfile = Pod::Podfile.new do
# first ensure that the correct info is available to the specs when they load
config.rootspec = self
self.platform platform
target(:debug) { dependency 'SSZipArchive' }
target(:test, :exclusive => true) { dependency 'JSONKit' }
dependency 'ASIHTTPRequest'
end
installer = Pod::Installer.new(podfile)
installer.install!
#project = Pod::Xcode::Project.new(config.project_pods_root + 'Pods.xcodeproj')
#p project
#project.targets.each do |target|
#target.source_build_phases.
#end
root = config.project_pods_root
(root + 'Pods.xcconfig').should.exist
(root + 'Pods-debug.xcconfig').should.exist
(root + 'Pods-test.xcconfig').should.exist
(root + 'Pods-resources.sh').should.exist
(root + 'Pods-debug-resources.sh').should.exist
(root + 'Pods-test-resources.sh').should.exist
Dir.chdir(config.project_pods_root) do
puts "\n[!] Compiling static library `Pods'..."
#system("xcodebuild -target Pods").should == true
system("xcodebuild -target Pods > /dev/null 2>&1").should == true
puts "\n[!] Compiling static library `Pods-debug'..."
system("xcodebuild -target Pods-debug > /dev/null 2>&1").should == true
puts "\n[!] Compiling static library `Pods-test'..."
system("xcodebuild -target Pods-test > /dev/null 2>&1").should == true
end
end
it "sets up an existing project with pods" do it "sets up an existing project with pods" do
basename = platform == :ios ? 'iPhone' : 'Mac' basename = platform == :ios ? 'iPhone' : 'Mac'
projpath = temporary_directory + 'ASIHTTPRequest.xcodeproj' projpath = temporary_directory + 'ASIHTTPRequest.xcodeproj'
...@@ -143,27 +194,26 @@ else ...@@ -143,27 +194,26 @@ else
installer = SpecHelper::Installer.new(spec) installer = SpecHelper::Installer.new(spec)
installer.install! installer.install!
installer.configure_project(projpath) installer.configure_project(projpath)
xcworkspace = temporary_directory + 'ASIHTTPRequest.xcworkspace' xcworkspace = temporary_directory + 'ASIHTTPRequest.xcworkspace'
workspace = Pod::Xcode::Workspace.new_from_xcworkspace(xcworkspace) workspace = Pod::Xcode::Workspace.new_from_xcworkspace(xcworkspace)
workspace.projpaths.sort.should == ['ASIHTTPRequest.xcodeproj', 'Pods/Pods.xcodeproj'] workspace.projpaths.sort.should == ['ASIHTTPRequest.xcodeproj', 'Pods/Pods.xcodeproj']
project = Pod::Xcode::Project.new(projpath) project = Pod::Xcode::Project.new(projpath)
config = project.files.find { |f| f.path =~ /Pods.xcconfig$/ } libPods = project.files.find { |f| f.name == 'libPods.a' }
config.should.not.equal nil
copy_resources = project.objects.select_by_class(Pod::Xcode::Project::PBXShellScriptBuildPhase).find do |ss|
ss.shellScript['PodsResources.sh']
end
copy_resources.should.not.equal nil
project.targets.each do |target| project.targets.each do |target|
bases = target.buildConfigurationList.buildConfigurations.map(&:baseConfigurationReference) target.buildConfigurations.each do |config|
bases.uniq[0].uuid.should == config.uuid config.baseConfiguration.path.should == 'Pods/Pods.xcconfig'
target.buildPhases.map(&:uuid).should.include copy_resources.uuid
end end
lib = project.files.find { |f| f.path =~ /libPods.a$/ }
lib.should.not.equal nil phase = target.frameworks_build_phases.first
project.objects.select_by_class(Pod::Xcode::Project::PBXFrameworksBuildPhase).each do |build_phase| phase.files.map { |buildFile| buildFile.file }.should.include libPods
build_phase.files.map(&:uuid).should.include lib.build_file.uuid
# should be the last phase
target.buildPhases.last.shellScript.should == "${SRCROOT}/Pods/Pods-resources.sh\n"
end end
end end
end end
end end
end end
...@@ -7,8 +7,8 @@ describe "Pod::BridgeSupportGenerator" do ...@@ -7,8 +7,8 @@ describe "Pod::BridgeSupportGenerator" do
def generator.gen_bridge_metadata(command) def generator.gen_bridge_metadata(command)
@command = command @command = command
end end
generator.create_in(Pathname.new("/path/to/Pods")) generator.save_as(Pathname.new("/path/to/Pods.bridgesupport"))
generator.instance_variable_get(:@command).should == generator.instance_variable_get(:@command).should ==
%{-c "-I '/some/dir' -I '/some/other/dir'" -o '/path/to/Pods/Pods.bridgesupport' '#{headers.join("' '")}'} %{-c "-I '/some/dir' -I '/some/other/dir'" -o '/path/to/Pods.bridgesupport' '#{headers.join("' '")}'}
end end
end end
...@@ -3,7 +3,7 @@ require File.expand_path('../../spec_helper', __FILE__) ...@@ -3,7 +3,7 @@ require File.expand_path('../../spec_helper', __FILE__)
describe "Pod::Installer" do describe "Pod::Installer" do
describe ", by default," do describe ", by default," do
before do before do
@xcconfig = Pod::Installer.new(Pod::Spec.new).xcconfig.to_hash @xcconfig = Pod::Installer.new(Pod::Podfile.new { platform :ios }).targets.first.xcconfig.to_hash
end end
it "sets the header search paths where installed Pod headers can be found" do it "sets the header search paths where installed Pod headers can be found" do
...@@ -33,9 +33,9 @@ describe "Pod::Installer" do ...@@ -33,9 +33,9 @@ describe "Pod::Installer" do
end end
it "generates a BridgeSupport metadata file from all the pod headers" do it "generates a BridgeSupport metadata file from all the pod headers" do
spec = Pod::Spec.new do |s| spec = Pod::Podfile.new do
s.platform = :osx platform :osx
s.dependency 'ASIHTTPRequest' dependency 'ASIHTTPRequest'
end end
expected = [] expected = []
installer = Pod::Installer.new(spec) installer = Pod::Installer.new(spec)
...@@ -44,71 +44,6 @@ describe "Pod::Installer" do ...@@ -44,71 +44,6 @@ describe "Pod::Installer" do
expected << config.project_pods_root + header expected << config.project_pods_root + header
end end
end end
installer.bridge_support_generator.headers.should == expected installer.targets.first.bridge_support_generator.headers.should == expected
end
it "adds all source files that should be included in the library to the xcode project" do
[
[
'ASIHTTPRequest',
['Classes'],
{ 'ASIHTTPRequest' => "Classes/*.{h,m}", 'Reachability' => "External/Reachability/*.{h,m}" },
{
"USER_HEADER_SEARCH_PATHS" => '"$(BUILT_PRODUCTS_DIR)/Pods" ' \
'"$(BUILT_PRODUCTS_DIR)/Pods/ASIHTTPRequest" ' \
'"$(BUILT_PRODUCTS_DIR)/Pods/Reachability"',
"ALWAYS_SEARCH_USER_PATHS" => "YES",
"OTHER_LDFLAGS" => "-ObjC -all_load " \
"-framework SystemConfiguration -framework MobileCoreServices " \
"-framework CFNetwork -lz.1"
}
],
[
'Reachability',
["External/Reachability/*.h", "External/Reachability/*.m"],
{ 'Reachability' => "External/Reachability/*.{h,m}", },
{
"USER_HEADER_SEARCH_PATHS" => '"$(BUILT_PRODUCTS_DIR)/Pods" ' \
'"$(BUILT_PRODUCTS_DIR)/Pods/Reachability"',
"ALWAYS_SEARCH_USER_PATHS" => "YES",
"OTHER_LDFLAGS" => "-ObjC -all_load"
}
],
[
'ASIWebPageRequest',
['**/ASIWebPageRequest.*'],
{ 'ASIHTTPRequest' => "Classes/*.{h,m}", 'ASIWebPageRequest' => "Classes/ASIWebPageRequest/*.{h,m}", 'Reachability' => "External/Reachability/*.{h,m}" },
{
"USER_HEADER_SEARCH_PATHS" => '"$(BUILT_PRODUCTS_DIR)/Pods" ' \
'"$(BUILT_PRODUCTS_DIR)/Pods/ASIHTTPRequest" ' \
'"$(BUILT_PRODUCTS_DIR)/Pods/Reachability"',
"ALWAYS_SEARCH_USER_PATHS" => "YES",
"HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2",
"OTHER_LDFLAGS" => "-ObjC -all_load " \
"-lxml2.2.7.3 -framework SystemConfiguration " \
"-framework MobileCoreServices -framework CFNetwork -lz.1"
}
],
].each do |name, patterns, expected_patterns, xcconfig|
Pod::Source.reset!
Pod::Spec::Set.reset!
installer = Pod::Installer.new(Pod::Spec.new do |s|
s.platform = :ios
s.dependency(name)
s.source_files = *patterns
end)
installer.generate_project
expected_patterns.each do |name, pattern|
pattern = config.project_pods_root + 'ASIHTTPRequest' + pattern
expected = pattern.glob.map do |file|
file.relative_path_from(config.project_pods_root)
end
installer.xcodeproj.source_files[name].size.should == expected.size
installer.xcodeproj.source_files[name].sort.should == expected.sort
end
installer.xcconfig.to_hash.should == xcconfig
end
end end
end end
...@@ -23,6 +23,47 @@ describe "Pod::Podfile" do ...@@ -23,6 +23,47 @@ describe "Pod::Podfile" do
podfile.generate_bridge_support?.should == true podfile.generate_bridge_support?.should == true
end end
describe "concerning targets (dependency groups)" do
before do
@podfile = Pod::Podfile.new do
target :debug do
dependency 'SSZipArchive'
end
target :test, :exclusive => true do
dependency 'JSONKit'
end
dependency 'ASIHTTPRequest'
end
end
it "returns all dependencies of all targets combined, which is used during resolving to enusre compatible dependencies" do
@podfile.dependencies.map(&:name).sort.should == %w{ ASIHTTPRequest JSONKit SSZipArchive }
end
it "adds dependencies outside of any explicit target block to the default target" do
target = @podfile.targets[:default]
target.lib_name.should == 'Pods'
target.dependencies.should == [Pod::Dependency.new('ASIHTTPRequest')]
end
it "adds dependencies of the outer target to non-exclusive targets" do
target = @podfile.targets[:debug]
target.lib_name.should == 'Pods-debug'
target.dependencies.sort_by(&:name).should == [
Pod::Dependency.new('ASIHTTPRequest'),
Pod::Dependency.new('SSZipArchive')
]
end
it "does not add dependencies of the outer target to exclusive targets" do
target = @podfile.targets[:test]
target.lib_name.should == 'Pods-test'
target.dependencies.should == [Pod::Dependency.new('JSONKit')]
end
end
describe "concerning validations" do describe "concerning validations" do
it "raises if no platform is specified" do it "raises if no platform is specified" do
exception = lambda { exception = lambda {
......
...@@ -25,7 +25,7 @@ describe "Pod::Xcode::Config" do ...@@ -25,7 +25,7 @@ describe "Pod::Xcode::Config" do
it "creates the config file" do it "creates the config file" do
@config.merge!('HEADER_SEARCH_PATHS' => '/some/path') @config.merge!('HEADER_SEARCH_PATHS' => '/some/path')
@config.merge!('OTHER_LD_FLAGS' => '-l xml2.2.7.3') @config.merge!('OTHER_LD_FLAGS' => '-l xml2.2.7.3')
@config.create_in(temporary_directory) @config.save_as(temporary_directory + 'Pods.xcconfig')
(temporary_directory + 'Pods.xcconfig').read.split("\n").sort.should == [ (temporary_directory + 'Pods.xcconfig').read.split("\n").sort.should == [
"OTHER_LD_FLAGS = -framework Foundation -l xml2.2.7.3", "OTHER_LD_FLAGS = -framework Foundation -l xml2.2.7.3",
"HEADER_SEARCH_PATHS = /some/path" "HEADER_SEARCH_PATHS = /some/path"
......
...@@ -23,13 +23,17 @@ describe "Pod::Xcode::Project" do ...@@ -23,13 +23,17 @@ describe "Pod::Xcode::Project" do
@project.to_hash.should == NSDictionary.dictionaryWithContentsOfFile(template_file) @project.to_hash.should == NSDictionary.dictionaryWithContentsOfFile(template_file)
end end
before do
@target = @project.targets.new_static_library('Pods')
end
it "returns the objects hash" do it "returns the objects hash" do
@project.objects_hash.should == @project.to_hash['objects'] @project.objects_hash.should == @project.to_hash['objects']
end end
describe "PBXObject" do describe "PBXObject" do
before do before do
@object = Pod::Xcode::Project::PBXObject.new(@project.objects, nil, 'name' => 'AnObject') @object = Pod::Xcode::Project::PBXObject.new(@project, nil, 'name' => 'AnObject')
end end
it "merges the class name into the attributes" do it "merges the class name into the attributes" do
...@@ -48,6 +52,172 @@ describe "Pod::Xcode::Project" do ...@@ -48,6 +52,172 @@ describe "Pod::Xcode::Project" do
@object.uuid.size.should == 24 @object.uuid.size.should == 24
@object.uuid.should == @object.uuid @object.uuid.should == @object.uuid
end end
it "adds the object to the objects hash" do
@project.objects_hash[@object.uuid].should == @object.attributes
end
end
describe "a PBXFileReference" do
before do
@file = @project.files.new('path' => 'some/file.m')
end
it "is automatically added to the main group" do
@file.group.should == @project.main_group
end
it "is removed from the original group when added to another group" do
@project.pods.children << @file
@file.group.should == @project.pods
@project.main_group.children.should.not.include @file
end
end
describe "a new PBXBuildPhase" do
before do
@phase = @project.objects.add(Pod::Xcode::Project::PBXBuildPhase)
end
it "has an empty list of files" do
@phase.files.to_a.should == []
end
it "always returns the same buildActionMask (no idea what it is)" do
@phase.buildActionMask.should == "2147483647"
end
it "always returns zero for runOnlyForDeploymentPostprocessing (no idea what it is)" do
@phase.runOnlyForDeploymentPostprocessing.should == "0"
end
end
describe "a new PBXCopyFilesBuildPhase" do
before do
@phase = @project.objects.add(Pod::Xcode::Project::PBXCopyFilesBuildPhase, 'dstPath' => 'some/path')
end
it "is a PBXBuildPhase" do
@phase.should.be.kind_of Pod::Xcode::Project::PBXBuildPhase
end
it "returns the dstPath" do
@phase.dstPath.should == 'some/path'
end
it "returns the dstSubfolderSpec (no idea what it is yet, but it's not always the same)" do
@phase.dstSubfolderSpec.should == "16"
end
end
describe "a new PBXSourcesBuildPhase" do
before do
@phase = @project.objects.add(Pod::Xcode::Project::PBXSourcesBuildPhase)
end
it "is a PBXBuildPhase" do
@phase.should.be.kind_of Pod::Xcode::Project::PBXBuildPhase
end
end
describe "a new PBXFrameworksBuildPhase" do
before do
@phase = @project.objects.add(Pod::Xcode::Project::PBXFrameworksBuildPhase)
end
it "is a PBXBuildPhase" do
@phase.should.be.kind_of Pod::Xcode::Project::PBXBuildPhase
end
end
describe "a new XCBuildConfiguration" do
before do
@configuration = @project.objects.add(Pod::Xcode::Project::XCBuildConfiguration)
end
it "returns the xcconfig that this configuration is based on (baseConfigurationReference)" do
xcconfig = @project.objects.new
@configuration.baseConfiguration = xcconfig
@configuration.baseConfigurationReference.should == xcconfig.uuid
end
end
describe "a new XCConfigurationList" do
before do
@list = @project.objects.add(Pod::Xcode::Project::XCConfigurationList)
end
it "returns the configurations" do
configuration = @project.objects.add(Pod::Xcode::Project::XCBuildConfiguration)
@list.buildConfigurations.to_a.should == []
@list.buildConfigurations = [configuration]
@list.buildConfigurationReferences.should == [configuration.uuid]
end
end
describe "a new PBXNativeTarget" do
it "returns the product name, which is the name of the binary (minus prefix/suffix)" do
@target.name.should == "Pods"
@target.productName.should == "Pods"
end
it "returns the product" do
product = @target.product
product.uuid.should == @target.productReference
product.should.be.instance_of Pod::Xcode::Project::PBXFileReference
product.path.should == "libPods.a"
product.name.should == "libPods.a"
product.group.name.should == "Products"
product.sourceTree.should == "BUILT_PRODUCTS_DIR"
product.explicitFileType.should == "archive.ar"
product.includeInIndex.should == "0"
end
it "returns that product type is a static library" do
@target.productType.should == "com.apple.product-type.library.static"
end
it "returns the buildConfigurationList" do
list = @target.buildConfigurationList
list.should.be.instance_of Pod::Xcode::Project::XCConfigurationList
list.buildConfigurations.each do |configuration|
configuration.buildSettings.should == {
'DSTROOT' => '/tmp/Pods.dst',
'GCC_PRECOMPILE_PREFIX_HEADER' => 'YES',
# TODO do we need a default?
#'GCC_PREFIX_HEADER' => 'Pods-Prefix.pch',
'OTHER_LDFLAGS' => '',
'GCC_VERSION' => 'com.apple.compilers.llvm.clang.1_0',
'PRODUCT_NAME' => '$(TARGET_NAME)',
'SKIP_INSTALL' => 'YES',
}
end
end
it "returns an empty list of dependencies and buildRules (not sure yet which classes those are yet)" do
@target.dependencies.to_a.should == []
@target.buildRules.to_a.should == []
end
describe "concerning its build phases" do
extend SpecHelper::TemporaryDirectory
it "returns an empty sources build phase" do
phase = @target.buildPhases.select_by_class(Pod::Xcode::Project::PBXSourcesBuildPhase).first
phase.files.to_a.should == []
end
it "returns a libraries/frameworks build phase, which by default only contains `Foundation.framework'" do
phase = @target.buildPhases.select_by_class(Pod::Xcode::Project::PBXFrameworksBuildPhase).first
phase.files.map { |buildFile| buildFile.file.name }.should == ['Foundation.framework']
end
it "returns an empty 'copy headers' phase" do
phase = @target.buildPhases.select_by_class(Pod::Xcode::Project::PBXCopyFilesBuildPhase).first
phase.dstPath.should == "$(PUBLIC_HEADERS_FOLDER_PATH)"
phase.files.to_a.should == []
end
end
end end
it "returns the objects as PBXObject instances" do it "returns the objects as PBXObject instances" do
...@@ -80,7 +250,7 @@ describe "Pod::Xcode::Project" do ...@@ -80,7 +250,7 @@ describe "Pod::Xcode::Project" do
it "adds a new PBXBuildFile to the objects hash when a new PBXFileReference is created" do it "adds a new PBXBuildFile to the objects hash when a new PBXFileReference is created" do
file = @project.files.new('name' => '/some/source/file.h') file = @project.files.new('name' => '/some/source/file.h')
build_file = file.build_file build_file = file.buildFiles.new
build_file.file = file build_file.file = file
build_file.fileRef.should == file.uuid build_file.fileRef.should == file.uuid
build_file.isa.should == 'PBXBuildFile' build_file.isa.should == 'PBXBuildFile'
...@@ -89,7 +259,7 @@ describe "Pod::Xcode::Project" do ...@@ -89,7 +259,7 @@ describe "Pod::Xcode::Project" do
it "adds a group to the `Pods' group" do it "adds a group to the `Pods' group" do
group = @project.add_pod_group('JSONKit') group = @project.add_pod_group('JSONKit')
@project.pods.children.should.include group.uuid @project.pods.childReferences.should.include group.uuid
find_object({ find_object({
'isa' => 'PBXGroup', 'isa' => 'PBXGroup',
'name' => 'JSONKit', 'name' => 'JSONKit',
...@@ -98,35 +268,18 @@ describe "Pod::Xcode::Project" do ...@@ -98,35 +268,18 @@ describe "Pod::Xcode::Project" do
}).should.not == nil }).should.not == nil
end end
it "adds an `m' or `c' file as a build file, adds it to the specified group, and adds it to the `sources build' phase list" do it "adds an `m' or `c' file to the `sources build' phase list" do
file_ref_uuids, build_file_uuids = [], []
group = @project.add_pod_group('SomeGroup')
%w{ m mm c cpp }.each do |ext| %w{ m mm c cpp }.each do |ext|
path = Pathname.new("path/to/file.#{ext}") path = Pathname.new("path/to/file.#{ext}")
file = group.add_source_file(path) file = @target.add_source_file(path)
# ensure that it was added to all objects
file = @project.objects[file.uuid]
@project.objects_hash[file.uuid].should == { phase = @target.buildPhases.find { |phase| phase.is_a?(Pod::Xcode::Project::PBXSourcesBuildPhase) }
'name' => path.basename.to_s, phase.files.map { |buildFile| buildFile.file }.should.include file
'isa' => 'PBXFileReference',
'sourceTree' => 'SOURCE_ROOT',
'path' => path.to_s
}
file_ref_uuids << file.uuid
build_file_uuid, _ = find_object({
'isa' => 'PBXBuildFile',
'fileRef' => file.uuid
})
build_file_uuids << build_file_uuid
group.children.should == file_ref_uuids phase = @target.buildPhases.find { |phase| phase.is_a?(Pod::Xcode::Project::PBXCopyFilesBuildPhase) }
phase.files.map { |buildFile| buildFile.file }.should.not.include file
_, object = find_object('isa' => 'PBXSourcesBuildPhase')
object['files'].should == build_file_uuids
_, object = find_object('isa' => 'PBXHeadersBuildPhase')
object['files'].should.not.include build_file_uuid
end end
end end
...@@ -134,7 +287,7 @@ describe "Pod::Xcode::Project" do ...@@ -134,7 +287,7 @@ describe "Pod::Xcode::Project" do
build_file_uuids = [] build_file_uuids = []
%w{ m mm c cpp }.each do |ext| %w{ m mm c cpp }.each do |ext|
path = Pathname.new("path/to/file.#{ext}") path = Pathname.new("path/to/file.#{ext}")
file = @project.pods.add_source_file(path, nil, '-fno-obj-arc') file = @project.targets.first.add_source_file(path, nil, '-fno-obj-arc')
find_object({ find_object({
'isa' => 'PBXBuildFile', 'isa' => 'PBXBuildFile',
'fileRef' => file.uuid, 'fileRef' => file.uuid,
...@@ -144,44 +297,33 @@ describe "Pod::Xcode::Project" do ...@@ -144,44 +297,33 @@ describe "Pod::Xcode::Project" do
end end
it "creates a copy build header phase which will copy headers to a specified path" do it "creates a copy build header phase which will copy headers to a specified path" do
phase = @project.add_copy_header_build_phase("SomePod", "Path/To/Source") phase = @project.targets.first.copy_files_build_phases.new_pod_dir("SomePod", "Path/To/Source")
find_object({ find_object({
'isa' => 'PBXCopyFilesBuildPhase', 'isa' => 'PBXCopyFilesBuildPhase',
'dstPath' => '$(PUBLIC_HEADERS_FOLDER_PATH)/Path/To/Source', 'dstPath' => '$(PUBLIC_HEADERS_FOLDER_PATH)/Path/To/Source',
'name' => 'Copy SomePod Public Headers' 'name' => 'Copy SomePod Public Headers'
}).should.not == nil }).should.not == nil
target = @project.targets.first @project.targets.first.buildPhases.should.include phase
target.attributes['buildPhases'].should.include phase.uuid
end end
it "adds a `h' file as a build file and adds it to the `headers build' phase list" do # TODO add test for the optional copy_header_phase
group = @project.groups.new('name' => 'SomeGroup') #it "adds a `h' file as a build file and adds it to the `headers build' phase list" do
it "adds a `h' file as a build file and adds it to the `copy header files' build phase list" do
path = Pathname.new("path/to/file.h") path = Pathname.new("path/to/file.h")
file = group.add_source_file(path) file = @target.add_source_file(path)
@project.objects_hash[file.uuid].should == { # ensure that it was added to all objects
'name' => path.basename.to_s, file = @project.objects[file.uuid]
'isa' => 'PBXFileReference',
'sourceTree' => 'SOURCE_ROOT',
'path' => path.to_s
}
build_file_uuid, _ = find_object({
'isa' => 'PBXBuildFile',
'fileRef' => file.uuid
})
#_, object = find_object('isa' => 'PBXHeadersBuildPhase') phase = @target.buildPhases.find { |phase| phase.is_a?(Pod::Xcode::Project::PBXSourcesBuildPhase) }
_, object = find_object('isa' => 'PBXCopyFilesBuildPhase') phase.files.map { |buildFile| buildFile.file }.should.not.include file
object['files'].should == [build_file_uuid]
_, object = find_object('isa' => 'PBXSourcesBuildPhase') phase = @target.buildPhases.find { |phase| phase.is_a?(Pod::Xcode::Project::PBXCopyFilesBuildPhase) }
object['files'].should.not.include build_file_uuid phase.files.map { |buildFile| buildFile.file }.should.include file
end end
it "saves the template with the adjusted project" do it "saves the template with the adjusted project" do
@template.copy_to(temporary_directory) @template.copy_to(temporary_directory)
@project.save_as(temporary_directory + 'Pods.xcodeproj') @project.save_as(temporary_directory + 'Pods.xcodeproj')
(temporary_directory + 'Pods-Prefix.pch').should.exist
(temporary_directory + 'Pods.xcconfig').should.exist
project_file = (temporary_directory + 'Pods.xcodeproj/project.pbxproj') project_file = (temporary_directory + 'Pods.xcodeproj/project.pbxproj')
NSDictionary.dictionaryWithContentsOfFile(project_file.to_s).should == @project.to_hash NSDictionary.dictionaryWithContentsOfFile(project_file.to_s).should == @project.to_hash
end end
...@@ -189,7 +331,7 @@ describe "Pod::Xcode::Project" do ...@@ -189,7 +331,7 @@ describe "Pod::Xcode::Project" do
it "returns all source files" do it "returns all source files" do
group = @project.groups.new('name' => 'SomeGroup') group = @project.groups.new('name' => 'SomeGroup')
files = [Pathname.new('/some/file.h'), Pathname.new('/some/file.m')] files = [Pathname.new('/some/file.h'), Pathname.new('/some/file.m')]
files.each { |file| group.add_source_file(file) } files.each { |file| group << @target.add_source_file(file) }
group.source_files.map(&:pathname).sort.should == files.sort group.source_files.map(&:pathname).sort.should == files.sort
end end
end end
//
// Prefix header for all source files of the 'Pods' target in the 'Pods' project
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif
...@@ -6,33 +6,14 @@ ...@@ -6,33 +6,14 @@
objectVersion = 46; objectVersion = 46;
objects = { objects = {
/* Begin PBXBuildFile section */
518ACD3F1446050200F6BE80 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 518ACD3E1446050200F6BE80 /* Cocoa.framework */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
518ACD3B1446050200F6BE80 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
518ACD3E1446050200F6BE80 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 518ACD3E1446050200F6BE80 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
518ACD461446050200F6BE80 /* Pods-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Pods-Prefix.pch"; sourceTree = "<group>"; };
518ACD53144605B400F6BE80 /* Pods.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Pods.xcconfig; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
518ACD381446050200F6BE80 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
518ACD3F1446050200F6BE80 /* Cocoa.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
518ACD301446050100F6BE80 = { 518ACD301446050100F6BE80 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
518ACD53144605B400F6BE80 /* Pods.xcconfig */,
518ACD5B1446449B00F6BE80 /* Pods */, 518ACD5B1446449B00F6BE80 /* Pods */,
518ACD3D1446050200F6BE80 /* Frameworks */, 518ACD3D1446050200F6BE80 /* Frameworks */,
518ACD3C1446050200F6BE80 /* Products */, 518ACD3C1446050200F6BE80 /* Products */,
...@@ -42,7 +23,6 @@ ...@@ -42,7 +23,6 @@
518ACD3C1446050200F6BE80 /* Products */ = { 518ACD3C1446050200F6BE80 /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
518ACD3B1446050200F6BE80 /* libPods.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -55,55 +35,15 @@ ...@@ -55,55 +35,15 @@
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
518ACD451446050200F6BE80 /* Supporting Files */ = {
isa = PBXGroup;
children = (
518ACD461446050200F6BE80 /* Pods-Prefix.pch */,
);
name = "Supporting Files";
path = Pods;
sourceTree = "<group>";
};
518ACD5B1446449B00F6BE80 /* Pods */ = { 518ACD5B1446449B00F6BE80 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
518ACD451446050200F6BE80 /* Supporting Files */,
); );
name = Pods; name = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
518ACD391446050200F6BE80 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
518ACD3A1446050200F6BE80 /* Pods */ = {
isa = PBXNativeTarget;
buildConfigurationList = 518ACD4C1446050200F6BE80 /* Build configuration list for PBXNativeTarget "Pods" */;
buildPhases = (
518ACD371446050200F6BE80 /* Sources */,
518ACD381446050200F6BE80 /* Frameworks */,
518ACD391446050200F6BE80 /* Headers */,
);
buildRules = (
);
dependencies = (
);
name = Pods;
productName = Pods;
productReference = 518ACD3B1446050200F6BE80 /* libPods.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */ /* Begin PBXProject section */
518ACD321446050100F6BE80 /* Project object */ = { 518ACD321446050100F6BE80 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
...@@ -122,21 +62,10 @@ ...@@ -122,21 +62,10 @@
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
targets = ( targets = (
518ACD3A1446050200F6BE80 /* Pods */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
518ACD371446050200F6BE80 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
518ACD4A1446050200F6BE80 /* Debug */ = { 518ACD4A1446050200F6BE80 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
...@@ -185,30 +114,6 @@ ...@@ -185,30 +114,6 @@
}; };
name = Release; name = Release;
}; };
518ACD4D1446050200F6BE80 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 518ACD53144605B400F6BE80 /* Pods.xcconfig */;
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Pods-Prefix.pch";
OTHER_LDFLAGS = (
);
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
518ACD4E1446050200F6BE80 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 518ACD53144605B400F6BE80 /* Pods.xcconfig */;
buildSettings = {
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Pods-Prefix.pch";
OTHER_LDFLAGS = (
);
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
...@@ -221,15 +126,6 @@ ...@@ -221,15 +126,6 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
518ACD4C1446050200F6BE80 /* Build configuration list for PBXNativeTarget "Pods" */ = {
isa = XCConfigurationList;
buildConfigurations = (
518ACD4D1446050200F6BE80 /* Debug */,
518ACD4E1446050200F6BE80 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */ /* End XCConfigurationList section */
}; };
rootObject = 518ACD321446050100F6BE80 /* Project object */; rootObject = 518ACD321446050100F6BE80 /* Project object */;
......
#!/bin/sh
install_resource()
{
echo "cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}
}
//
// Prefix header for all source files of the 'Pods' target in the 'Pods' project
//
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
...@@ -6,46 +6,14 @@ ...@@ -6,46 +6,14 @@
objectVersion = 46; objectVersion = 46;
objects = { objects = {
/* Begin PBXBuildFile section */
515B0FB9141D52E0001DC3E6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 515B0FB8141D52E0001DC3E6 /* Foundation.framework */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
82A8B61C142F7EC7006897C9 /* Copy Public Headers */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)";
dstSubfolderSpec = 16;
files = (
);
name = "Copy Public Headers";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
515160D0141EC5D100EBB823 /* Pods.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Pods.xcconfig; sourceTree = "<group>"; };
515B0FB5141D52E0001DC3E6 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
515B0FB8141D52E0001DC3E6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 515B0FB8141D52E0001DC3E6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
515B0FBC141D52E0001DC3E6 /* Pods-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Pods-Prefix.pch"; sourceTree = SOURCE_ROOT; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
515B0FB2141D52E0001DC3E6 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
515B0FB9141D52E0001DC3E6 /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */ /* Begin PBXGroup section */
515B0FAA141D52E0001DC3E6 = { 515B0FAA141D52E0001DC3E6 = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
515160D0141EC5D100EBB823 /* Pods.xcconfig */,
515B0FC9141D5FBE001DC3E6 /* Pods */, 515B0FC9141D5FBE001DC3E6 /* Pods */,
515B0FB7141D52E0001DC3E6 /* Frameworks */, 515B0FB7141D52E0001DC3E6 /* Frameworks */,
515B0FB6141D52E0001DC3E6 /* Products */, 515B0FB6141D52E0001DC3E6 /* Products */,
...@@ -55,7 +23,6 @@ ...@@ -55,7 +23,6 @@
515B0FB6141D52E0001DC3E6 /* Products */ = { 515B0FB6141D52E0001DC3E6 /* Products */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
515B0FB5141D52E0001DC3E6 /* libPods.a */,
); );
name = Products; name = Products;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -68,59 +35,21 @@ ...@@ -68,59 +35,21 @@
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
515B0FBB141D52E0001DC3E6 /* Supporting Files */ = {
isa = PBXGroup;
children = (
515B0FBC141D52E0001DC3E6 /* Pods-Prefix.pch */,
);
name = "Supporting Files";
path = Pods;
sourceTree = "<group>";
};
515B0FC9141D5FBE001DC3E6 /* Pods */ = { 515B0FC9141D5FBE001DC3E6 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
515B0FBB141D52E0001DC3E6 /* Supporting Files */,
); );
name = Pods; name = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
515B0FB3141D52E0001DC3E6 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
515B0FB4141D52E0001DC3E6 /* Pods */ = {
isa = PBXNativeTarget;
buildConfigurationList = 515B0FC2141D52E0001DC3E6 /* Build configuration list for PBXNativeTarget "Pods" */;
buildPhases = (
515B0FB1141D52E0001DC3E6 /* Sources */,
515B0FB2141D52E0001DC3E6 /* Frameworks */,
515B0FB3141D52E0001DC3E6 /* Headers */,
82A8B61C142F7EC7006897C9 /* Copy Public Headers */,
);
buildRules = (
);
dependencies = (
);
name = Pods;
productName = Pods;
productReference = 515B0FB5141D52E0001DC3E6 /* libPods.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */ /* Begin PBXProject section */
515B0FAC141D52E0001DC3E6 /* Project object */ = { 515B0FAC141D52E0001DC3E6 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = {
LastUpgradeCheck = 0420;
};
buildConfigurationList = 515B0FAF141D52E0001DC3E6 /* Build configuration list for PBXProject "Pods" */; buildConfigurationList = 515B0FAF141D52E0001DC3E6 /* Build configuration list for PBXProject "Pods" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
developmentRegion = English; developmentRegion = English;
...@@ -133,21 +62,10 @@ ...@@ -133,21 +62,10 @@
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
targets = ( targets = (
515B0FB4141D52E0001DC3E6 /* Pods */,
); );
}; };
/* End PBXProject section */ /* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
515B0FB1141D52E0001DC3E6 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */ /* Begin XCBuildConfiguration section */
515B0FC0141D52E0001DC3E6 /* Debug */ = { 515B0FC0141D52E0001DC3E6 /* Debug */ = {
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
...@@ -193,34 +111,6 @@ ...@@ -193,34 +111,6 @@
}; };
name = Release; name = Release;
}; };
515B0FC3141D52E0001DC3E6 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 515160D0141EC5D100EBB823 /* Pods.xcconfig */;
buildSettings = {
DSTROOT = /tmp/Pods.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Pods-Prefix.pch";
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
515B0FC4141D52E0001DC3E6 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 515160D0141EC5D100EBB823 /* Pods.xcconfig */;
buildSettings = {
DSTROOT = /tmp/Pods.dst;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Pods-Prefix.pch";
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */ /* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */ /* Begin XCConfigurationList section */
...@@ -233,15 +123,6 @@ ...@@ -233,15 +123,6 @@
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
515B0FC2141D52E0001DC3E6 /* Build configuration list for PBXNativeTarget "Pods" */ = {
isa = XCConfigurationList;
buildConfigurations = (
515B0FC3141D52E0001DC3E6 /* Debug */,
515B0FC4141D52E0001DC3E6 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */ /* End XCConfigurationList section */
}; };
rootObject = 515B0FAC141D52E0001DC3E6 /* Project object */; rootObject = 515B0FAC141D52E0001DC3E6 /* Project object */;
......
#!/bin/sh
install_resource()
{
echo "cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment