Commit c5d13de4 authored by Fabio Pelosin's avatar Fabio Pelosin

Completed support for Xcodeproj refactor.

parent 4fb9ca0a
......@@ -72,14 +72,16 @@ module Pod
#
def generate_xcconfig(pods, sandbox)
xcconfig = Xcodeproj::Config.new({
'PODS_ROOT' => @target_definition.relative_pods_root,
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_PUBLIC_HEADERS_SEARCH_PATHS}',
'ALWAYS_SEARCH_USER_PATHS' => 'YES', # needed to make EmbedReader build
'OTHER_LDFLAGS' => default_ld_flags
'ALWAYS_SEARCH_USER_PATHS' => 'YES', # needed to make EmbedReader build
'OTHER_LDFLAGS' => default_ld_flags,
'HEADER_SEARCH_PATHS' => '${PODS_HEADERS_SEARCH_PATHS}',
# CocoaPods global keys
'PODS_ROOT' => @target_definition.relative_pods_root,
'PODS_BUILD_HEADERS_SEARCH_PATHS' => quoted(sandbox.build_headers.search_paths).join(" "),
'PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quoted(sandbox.public_headers.search_paths).join(" "),
# Pods project specific keys
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_PUBLIC_HEADERS_SEARCH_PATHS}'
})
xcconfig.merge!('HEADER_SEARCH_PATHS' => '${PODS_HEADERS_SEARCH_PATHS}')
xcconfig.merge!('PODS_BUILD_HEADERS_SEARCH_PATHS' => quoted(sandbox.build_headers.search_paths).join(" "))
xcconfig.merge!('PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quoted(sandbox.public_headers.search_paths).join(" "))
pods.each { |pod| xcconfig.merge!(pod.xcconfig) }
@xcconfig = xcconfig
end
......
......@@ -387,8 +387,14 @@ module Pod
result
end
# @!group Project integration
# @!group Xcodeproj integration
# Adds the file references, to the given `Pods.xcodeproj` project, for the
# source files of the pod. The file references are grouped by specification
# and stored in {#file_references_by_spec}.
#
# @note If the pod is locally sourced the file references are stored in the
# `Local Pods` group otherwise they are stored in the `Pods` group.
#
# @return [void]
#
......@@ -406,13 +412,24 @@ module Pod
end
end
#
# @return [Hash{Specification => Array<PBXFileReference>}] The file
# references of the pod in the `Pods.xcodeproj` project.
#
attr_reader :file_references_by_spec
# Adds a build file for each file reference to a given target taking into
# account the compiler flags of the corresponding specification.
#
# @raise If the {#add_file_references_to_project} was not called before of
# calling this method.
#
# @return [void]
#
def add_build_files_to_target(target)
unless file_references_by_spec
raise Informative, "Local Pod needs to add the file references to the " \
"project before adding the build files to the target."
end
file_references_by_spec.each do |spec, file_reference|
target.add_file_references(file_reference, spec.compiler_flags.strip)
end
......@@ -543,15 +560,27 @@ module Pod
"\t Options: #{options.inspect}"
end
patterns = [ patterns ] if patterns.is_a? String
patterns.map do |pattern|
pattern = root + pattern
return [] if patterns.empty?
patterns = [ patterns ] if patterns.is_a?(String)
file_lists = patterns.select { |p| p.is_a?(FileList) }
glob_patterns = patterns - file_lists
result = []
result << file_lists.map do |file_list|
file_list.prepend_patterns(root)
file_list.glob
end
result << glob_patterns.map do |pattern|
pattern = root + pattern
if pattern.directory? && options[:glob]
pattern += options[:glob]
end
Pathname.glob(pattern, File::FNM_CASEFOLD)
end.flatten
result.flatten.compact.uniq
end
# A {LocalSourcedPod} is a {LocalPod} that interacts with the files of
......
require 'xcodeproj/project'
require 'xcodeproj/project/object/build_phase'
Xcodeproj::Project::Object::PBXCopyFilesBuildPhase.instance_eval do
def self.new_pod_dir(project, pod_name, path)
new(project, nil, {
"dstPath" => "Pods/#{path}",
"name" => "Copy #{pod_name} Public Headers",
})
end
end
# Xcodeproj::Project::Object::PBXCopyFilesBuildPhase.instance_eval do
# def self.new_pod_dir(project, pod_name, path)
# new(project, nil, {
# "dstPath" => "Pods/#{path}",
# "name" => "Copy #{pod_name} Public Headers",
# })
# end
# end
module Pod
class Project < Xcodeproj::Project
......@@ -65,6 +64,7 @@ module Pod
end
if platform == :ios && platform.deployment_target
# TODO: add for osx as well
settings['IPHONEOS_DEPLOYMENT_TARGET'] = platform.deployment_target.to_s
end
......
......@@ -438,11 +438,12 @@ module Pod
# this to, for instance, to run any build script:
#
# Pod::Spec.new do |s|
# def pre_install(pod, target_definition)
# def s.pre_install(pod, target_definition)
# Dir.chdir(pod.root){ `sh make.sh` }
# end
# end
def pre_install(pod, target_definition)
FALSE
end
# This is a convenience method which gets called after all pods have been
......@@ -460,6 +461,7 @@ module Pod
# end
# end
def post_install(target_installer)
FALSE
end
def podfile?
......
......@@ -32,21 +32,13 @@ describe Pod::Installer::UserProjectIntegrator do
@sample_project = Xcodeproj::Project.new(@sample_project_path)
end
it 'adds references to the Pods static libraries to the root of the project if the Frameworks group does not exist' do
@sample_project.group('Frameworks').destroy
@sample_project.save_as(@sample_project_path)
integrate!
@sample_project.main_group.files.where(:name => "libPods.a").should.not == nil
@sample_project.main_group.files.where(:name => "libPods-test_runner.a").should.not == nil
end
before do
integrate!
end
it 'adds references to the Pods static libraries to the Frameworks group' do
@sample_project.group('Frameworks').files.where(:name => "libPods.a").should.not == nil
@sample_project.group('Frameworks').files.where(:name => "libPods-test_runner.a").should.not == nil
@sample_project["Frameworks/libPods.a"].should.not == nil
@sample_project["Frameworks/libPods-test_runner.a"].should.not == nil
end
it 'creates a workspace with a name matching the project' do
......@@ -66,26 +58,25 @@ describe Pod::Installer::UserProjectIntegrator do
it 'sets the Pods xcconfig as the base config for each build configuration' do
@podfile.target_definitions.each do |_, definition|
target = @sample_project.targets.where(:name => definition.link_with.first)
xcconfig_file = @sample_project.files.where(:path => "Pods/#{definition.xcconfig_name}")
target = @sample_project.targets.find { |t| t.name == definition.link_with.first }
xcconfig_file = @sample_project.files.find { |f| f.path == "Pods/#{definition.xcconfig_name}" }
target.build_configurations.each do |config|
config.base_configuration.should == xcconfig_file
config.base_configuration_reference.should == xcconfig_file
end
end
end
it 'adds the libPods static library to the "Link binary with libraries" build phase of each target' do
@podfile.target_definitions.each do |_, definition|
target = @sample_project.targets.where(:name => definition.link_with.first)
framework_build_phase = target.frameworks_build_phases.first
framework_build_phase.files.where(:name => definition.lib_name).should.not == nil
target = @sample_project.targets.find { |t| t.name == definition.link_with.first }
target.frameworks_build_phase.files.find { |f| f.file_ref.name == definition.lib_name}.should.not == nil
end
end
it 'adds a Copy Pods Resources build phase to each target' do
@podfile.target_definitions.each do |_, definition|
target = @sample_project.targets.where(:name => definition.link_with.first)
phase = target.shell_script_build_phases.where(:name => "Copy Pods Resources")
target = @sample_project.targets.find { |t| t.name == definition.link_with.first }
phase = target.shell_script_build_phases.find { |bp| bp.name == "Copy Pods Resources" }
phase.shell_script.strip.should == "\"${SRCROOT}/Pods/#{definition.copy_resources_script_name}\""
end
end
......@@ -101,8 +92,8 @@ describe Pod::Installer::UserProjectIntegrator do
# Remove libPods.a from the app target. But don't do it through TargetIntegrator#targets,
# as it will return only those that still need integration.
app_target = app_integrator.user_project.targets.where(:name => 'SampleProject')
app_target.frameworks_build_phases.first.build_files.last.destroy
app_target = app_integrator.user_project.targets.find { |t| t.name == 'SampleProject' }
app_target.frameworks_build_phase.files.last.remove_from_project
app_integrator.expects(:add_pods_library)
test_runner_integrator.expects(:add_pods_library).never
......
......@@ -389,7 +389,9 @@ else
installer.install!
project = Pod::Project.new(config.project_pods_root + 'Pods.xcodeproj')
project.source_files.should == installer.project.source_files
disk_source_files = project.files.sort.reject { |f| f.build_files.empty? }
installer_source_files = installer.project.files.sort.reject { |f| f.build_files.empty? }
disk_source_files.should == installer_source_files
end
it "creates a project with multiple targets" do
......@@ -409,7 +411,7 @@ else
project = Xcodeproj::Project.new(config.project_pods_root + 'Pods.xcodeproj')
project.targets.each do |target|
phase = target.build_phases.find { |phase| phase.is_a?(Xcodeproj::Project::Object::PBXSourcesBuildPhase) }
files = phase.files.map(&:name)
files = phase.files.map { |bf| bf.file_ref.name }
case target.product_name
when 'Pods'
files.should.include "ASIHTTPRequest.m"
......@@ -466,9 +468,9 @@ else
target = project.targets.first
target.build_configurations.each do |config|
config.base_configuration.path.should == 'Pods/Pods.xcconfig'
config.base_configuration_reference.path.should == 'Pods/Pods.xcconfig'
end
target.frameworks_build_phases.first.files.should.include libPods
target.frameworks_build_phase.files.should.include libPods.build_files.first
# should be the last phase
target.build_phases.last.shell_script.should == %{"${SRCROOT}/Pods/Pods-resources.sh"\n}
end
......
......@@ -13,7 +13,7 @@ describe Pod::Installer::TargetInstaller do
@target_definition = @podfile.target_definitions[:default]
@project = Pod::Project.new
@project.main_group.groups.new('name' => 'Targets Support Files')
@project.new_group('Targets Support Files')
@installer = Pod::Installer::TargetInstaller.new(@podfile, @project, @target_definition)
......@@ -24,6 +24,7 @@ describe Pod::Installer::TargetInstaller do
end
def do_install!
@pods.each { |pod| pod.add_file_references_to_project(@project) }
@installer.install!(@pods, @sandbox)
end
......@@ -40,14 +41,15 @@ describe Pod::Installer::TargetInstaller do
end
it 'adds each pod to the static library target' do
@pods[0].expects(:source_file_descriptions).returns([])
@pods[0].expects(:add_build_files_to_target)
do_install!
end
it 'tells each pod to link its headers' do
@pods[0].expects(:link_headers)
do_install!
end
# TODO: move to project
# it 'tells each pod to link its headers' do
# @pods[0].expects(:link_headers)
# do_install!
# end
it 'adds the sandbox header search paths to the xcconfig, with quotes' do
do_install!
......@@ -62,7 +64,7 @@ describe Pod::Installer::TargetInstaller do
it 'adds the -fobjc-arc to OTHER_LDFLAGS if any pods require arc (to support non-ARC projects on iOS 4.0)' do
@podfile.stubs(:set_arc_compatibility_flag? => true)
@specification.stubs(:requires_arc).returns(true)
@installer.install!(@pods, @sandbox)
do_install!
@installer.xcconfig.to_hash['OTHER_LDFLAGS'].split(" ").should.include("-fobjc-arc")
end
......
......@@ -17,7 +17,9 @@ module Pod
sandbox = Sandbox.new(fixture('integration'))
resolver = Resolver.new(podfile, nil, sandbox)
@xcconfig = Installer.new(resolver).target_installers.first.xcconfig.to_hash
target_installer = Installer.new(resolver).target_installers.first
target_installer.generate_xcconfig([], sandbox)
@xcconfig = target_installer.xcconfig.to_hash
end
it "sets the header search paths where installed Pod headers can be found" do
......@@ -127,7 +129,7 @@ module Pod
it "adds the files of the pod to the Pods project only once" do
@installer.install!
group = @installer.project.pods.groups.where(:name => 'Reachability')
group = @installer.project.pods.groups.find { |g| g.name == 'Reachability' }
group.files.map(&:name).should == ["Reachability.h", "Reachability.m"]
end
......@@ -155,13 +157,13 @@ module Pod
it "namespaces local pods" do
@installer.install!
group = @installer.project.groups.where(:name => 'Local Pods')
group = @installer.project['Local Pods']
group.groups.map(&:name).sort.should == %w| Chameleon |
end
it "namespaces subspecs" do
@installer.install!
group = @installer.project.groups.where(:name => 'Chameleon')
group = @installer.project['Local Pods/Chameleon']
group.groups.map(&:name).sort.should == %w| AVFoundation AssetsLibrary MediaPlayer MessageUI StoreKit UIKit |
end
end
......
......@@ -38,7 +38,7 @@ describe Pod::LocalPod do
].sort
end
it "returns the source files groupped by specification" do
it "returns the source files grouped by specification" do
files = @pod.source_files_by_spec[@pod.specifications.first].sort
files.should == [
@pod.root + "Classes/Banana.m",
......@@ -83,18 +83,26 @@ describe Pod::LocalPod do
end
it "can add it's source files to an Xcode project target" do
@pod.source_file_descriptions.should == [
Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(Pathname.new("BananaLib/Classes/Banana.h"), "", nil),
Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(Pathname.new("BananaLib/Classes/Banana.m"), "", nil)
]
project = Pod::Project.new
@pod.add_file_references_to_project(project)
project['Pods/BananaLib/Banana.h'].path.should == "BananaLib/Classes/Banana.h"
project['Pods/BananaLib/Banana.m'].path.should == "BananaLib/Classes/Banana.m"
end
it "can add it's source files to a target with any specially configured compiler flags" do
project = Pod::Project.new
target = project.new_target(:static, 'Pods', :ios)
@pod.top_specification.compiler_flags = '-d some_flag'
@pod.source_file_descriptions.should == [
Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(Pathname.new("BananaLib/Classes/Banana.h"), '-d some_flag', nil),
Xcodeproj::Project::PBXNativeTarget::SourceFileDescription.new(Pathname.new("BananaLib/Classes/Banana.m"), '-d some_flag', nil)
]
@pod.add_file_references_to_project(project)
@pod.add_build_files_to_target(target)
h_build_file = target.headers_build_phase.files.first
h_build_file.file_ref.path.should == "BananaLib/Classes/Banana.h"
h_build_file.settings.should == {"ATTRIBUTES"=>["Public"]}
m_build_file = target.source_build_phase.files.first
m_build_file.file_ref.path.should == "BananaLib/Classes/Banana.m"
m_build_file.settings.should == {"COMPILER_FLAGS"=>"-d some_flag"}
end
it "returns the platform" do
......
......@@ -5,44 +5,32 @@ describe 'Pod::Project' do
@project = Pod::Project.new
end
def find_object(conditions)
@project.objects_hash.select do |_, object|
(conditions.keys - object.keys).empty? && object.values_at(*conditions.keys) == conditions.values
end.first
end
it "adds a group to the `Pods' group" do
group = @project.add_spec_group('JSONKit', @project.pods)
@project.pods.child_references.should.include group.uuid
find_object({
'isa' => 'PBXGroup',
'name' => 'JSONKit',
'sourceTree' => '<group>',
'children' => []
}).should.not == nil
@project.pods.children.should.include?(group)
g = @project['Pods/JSONKit']
g.name.should == 'JSONKit'
g.children.should.be.empty?
end
it "namespaces subspecs in groups" do
group = @project.add_spec_group('JSONKit/Subspec', @project.pods)
@project.pods.groups.find { |g| g.name == 'JSONKit' }.child_references.should.include group.uuid
find_object({
'isa' => 'PBXGroup',
'name' => 'Subspec',
'sourceTree' => '<group>',
'children' => []
}).should.not == nil
@project.pods.groups.find { |g| g.name == 'JSONKit' }.children.should.include?(group)
g = @project['Pods/JSONKit/Subspec']
g.name.should == 'Subspec'
g.children.should.be.empty?
end
it "creates a copy build header phase which will copy headers to a specified path" do
@project.targets.new
phase = @project.targets.first.copy_files_build_phases.new_pod_dir("SomePod", "Path/To/Source")
find_object({
'isa' => 'PBXCopyFilesBuildPhase',
'dstPath' => 'Pods/Path/To/Source',
'name' => 'Copy SomePod Public Headers'
}).should.not == nil
@project.targets.first.build_phases.should.include phase
end
# it "creates a copy build header phase which will copy headers to a specified path" do
# @project.targets.new
# phase = @project.targets.first.copy_files_build_phases.new_pod_dir("SomePod", "Path/To/Source")
# find_object({
# 'isa' => 'PBXCopyFilesBuildPhase',
# 'dstPath' => 'Pods/Path/To/Source',
# 'name' => 'Copy SomePod Public Headers'
# }).should.not == nil
# @project.targets.first.build_phases.should.include phase
# end
it "adds build configurations named after every configuration across all of the user's projects" do
@project.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'Test' => :debug, 'AppStore' => :release }
......
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