Commit 70578126 authored by Fabio Pelosin's avatar Fabio Pelosin

[TargetInstaller] Refactor, merge logic of aggregate and pod targets

parent 12b5bedc
...@@ -17,7 +17,7 @@ GIT ...@@ -17,7 +17,7 @@ GIT
GIT GIT
remote: https://github.com/CocoaPods/Xcodeproj.git remote: https://github.com/CocoaPods/Xcodeproj.git
revision: 41644f62741f5fb71d776b08bfb1e55c017f75e7 revision: 2c25c6712b9ac2472f3e8fd34d0744166af8f7ff
branch: master branch: master
specs: specs:
xcodeproj (0.10.1) xcodeproj (0.10.1)
......
...@@ -19,6 +19,9 @@ module Pod ...@@ -19,6 +19,9 @@ module Pod
# To tame the complexity of the incremental editing, the generator relies # To tame the complexity of the incremental editing, the generator relies
# on the following assumptions: # on the following assumptions:
# #
# - Unrecognized targets and groups are removed early so the rest of the
# generation can focus on adding references if missing. In this way the
# same code path can be shared with the generation from scratch.
# - The file references of the Pods are all stored in a dedicated group. # - The file references of the Pods are all stored in a dedicated group.
# - The support files for a Pod are stored in a group which in turn is # - The support files for a Pod are stored in a group which in turn is
# namespaced per aggregate target. # namespaced per aggregate target.
...@@ -63,20 +66,18 @@ module Pod ...@@ -63,20 +66,18 @@ module Pod
# recompilation of the project. # recompilation of the project.
# #
# #
# TODO: Fix the CocoaPods compatibility version.
# TODO: Resource bundle targets are currently removed as they are not # TODO: Resource bundle targets are currently removed as they are not
# unrecognized. # recognized.
# TODO: Rebuild from scratch if the version of CocoaPods is not compatible.
# TODO: The paths of frameworks might not match in different systems.
# TODO: The recreation of the prefix header of the Pods targets forces a # TODO: The recreation of the prefix header of the Pods targets forces a
# recompilation. # recompilation.
# TODO: The headers search paths of the Pods xcconfigs should not include # TODO: The headers search paths of the Pods xcconfigs should not include
# all the headers. # all the headers.
# TODO: Clean system frameworks & libraries not referenced anymore.
# #
class PodsProjectGenerator class PodsProjectGenerator
autoload :AggregateTargetInstaller, 'cocoapods/installer/pods_project_generator/target_installer/aggregate_target_installer'
autoload :FileReferencesInstaller, 'cocoapods/installer/pods_project_generator/file_references_installer' autoload :FileReferencesInstaller, 'cocoapods/installer/pods_project_generator/file_references_installer'
autoload :PodTargetInstaller, 'cocoapods/installer/pods_project_generator/target_installer/pod_target_installer'
autoload :SupportFilesGenerator, 'cocoapods/installer/pods_project_generator/support_files_generator' autoload :SupportFilesGenerator, 'cocoapods/installer/pods_project_generator/support_files_generator'
autoload :TargetInstaller, 'cocoapods/installer/pods_project_generator/target_installer' autoload :TargetInstaller, 'cocoapods/installer/pods_project_generator/target_installer'
...@@ -117,6 +118,7 @@ module Pod ...@@ -117,6 +118,7 @@ module Pod
sync_support_files sync_support_files
add_missing_aggregate_targets_libraries add_missing_aggregate_targets_libraries
add_missing_target_dependencies add_missing_target_dependencies
post_installation_cleaning
end end
# Writes the Pods project to the disk. # Writes the Pods project to the disk.
...@@ -184,7 +186,7 @@ module Pod ...@@ -184,7 +186,7 @@ module Pod
end end
aggregate_targets_to_install.each do |target| aggregate_targets_to_install.each do |target|
UI.message"- Installing `#{target.label}`" do UI.message"- Installing `#{target}`" do
add_aggregate_target(target) add_aggregate_target(target)
end end
end end
...@@ -199,7 +201,7 @@ module Pod ...@@ -199,7 +201,7 @@ module Pod
targets = all_pod_targets + aggregate_targets targets = all_pod_targets + aggregate_targets
targets.reject!(&:skip_installation?) targets.reject!(&:skip_installation?)
targets.each do |target| targets.each do |target|
UI.message"- Generating support files for target `#{target.label}`" do UI.message"- Generating support files for target `#{target}`" do
gen = SupportFilesGenerator.new(target, sandbox.project) gen = SupportFilesGenerator.new(target, sandbox.project)
gen.generate! gen.generate!
end end
...@@ -214,9 +216,9 @@ module Pod ...@@ -214,9 +216,9 @@ module Pod
def add_missing_aggregate_targets_libraries def add_missing_aggregate_targets_libraries
UI.message"- Populating aggregate targets" do UI.message"- Populating aggregate targets" do
aggregate_targets.each do |aggregate_target| aggregate_targets.each do |aggregate_target|
native_target = aggregate_target.target native_target = aggregate_target.native_target
aggregate_target.pod_targets.each do |pod_target| aggregate_target.pod_targets.each do |pod_target|
product = pod_target.target.product_reference product = pod_target.native_target.product_reference
unless native_target.frameworks_build_phase.files_references.include?(product) unless native_target.frameworks_build_phase.files_references.include?(product)
native_target.frameworks_build_phase.add_file_reference(product) native_target.frameworks_build_phase.add_file_reference(product)
end end
...@@ -233,14 +235,14 @@ module Pod ...@@ -233,14 +235,14 @@ module Pod
UI.message"- Setting-up target dependencies" do UI.message"- Setting-up target dependencies" do
aggregate_targets.each do |aggregate_target| aggregate_targets.each do |aggregate_target|
aggregate_target.pod_targets.each do |dep| aggregate_target.pod_targets.each do |dep|
aggregate_target.target.add_dependency(dep.target) aggregate_target.native_target.add_dependency(dep.target)
end end
aggregate_targets.each do |aggregate_target| aggregate_targets.each do |aggregate_target|
aggregate_target.pod_targets.each do |pod_target| aggregate_target.pod_targets.each do |pod_target|
dependencies = pod_target.dependencies.map { |dep_name| aggregate_target.pod_targets.find { |target| target.pod_name == dep_name } } dependencies = pod_target.dependencies.map { |dep_name| aggregate_target.pod_targets.find { |target| target.pod_name == dep_name } }
dependencies.each do |dep| dependencies.each do |dep|
pod_target.target.add_dependency(dep.target) pod_target.native_target.add_dependency(dep.target)
end end
end end
end end
...@@ -248,6 +250,19 @@ module Pod ...@@ -248,6 +250,19 @@ module Pod
end end
end end
# Removes any system framework not referenced by any target.
#
# @return [void]
#
def post_installation_cleaning
project.frameworks_group.files.each do |file|
only_refered_by_group = file.referrers.count == 1
if only_refered_by_group
file.remove_from_project
end
end
end
private private
...@@ -266,7 +281,7 @@ module Pod ...@@ -266,7 +281,7 @@ module Pod
cp_targets.each do |pod_target| cp_targets.each do |pod_target|
native_targets = native_targets_by_name[pod_target.label] native_targets = native_targets_by_name[pod_target.label]
if native_targets if native_targets
pod_target.target = native_targets.first pod_target.native_target = native_targets.first
@unrecognized_targets.delete(pod_target.label) @unrecognized_targets.delete(pod_target.label)
end end
end end
...@@ -314,7 +329,8 @@ module Pod ...@@ -314,7 +329,8 @@ module Pod
# @!group Private Helpers # @!group Private Helpers
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
# # @return [Bool] Whether a new project should be created from scratch or
# the installation can be performed incrementally.
# #
def should_create_new_project? def should_create_new_project?
# TODO version # TODO version
...@@ -341,7 +357,7 @@ module Pod ...@@ -341,7 +357,7 @@ module Pod
all_pod_targets.map(&:pod_name).uniq.sort all_pod_targets.map(&:pod_name).uniq.sort
else else
# TODO: Add missing groups # TODO: Add missing groups
missing_target = all_pod_targets.select { |pod_target| pod_target.target.nil? }.map(&:pod_name).uniq missing_target = all_pod_targets.select { |pod_target| pod_target.native_target.nil? }.map(&:pod_name).uniq
@pods_to_install ||= (sandbox.state.added | sandbox.state.changed | missing_target).uniq.sort @pods_to_install ||= (sandbox.state.added | sandbox.state.changed | missing_target).uniq.sort
end end
end end
...@@ -350,7 +366,7 @@ module Pod ...@@ -350,7 +366,7 @@ module Pod
# #
def aggregate_targets_to_install def aggregate_targets_to_install
aggregate_targets.sort_by(&:name).select do |target| aggregate_targets.sort_by(&:name).select do |target|
target.target.nil? && !target.skip_installation? target.native_target.nil? && !target.skip_installation?
end end
end end
...@@ -403,7 +419,7 @@ module Pod ...@@ -403,7 +419,7 @@ module Pod
# @return [void] # @return [void]
# #
def remove_target(target) def remove_target(target)
UI.message"- Removing `#{target.display_name}` target" do UI.message"- Removing `#{target}` target" do
target.referrers.each do |ref| target.referrers.each do |ref|
if ref.isa == 'PBXTargetDependency' if ref.isa == 'PBXTargetDependency'
ref.remove_from_project ref.remove_from_project
...@@ -437,11 +453,9 @@ module Pod ...@@ -437,11 +453,9 @@ module Pod
FileReferencesInstaller.new(sandbox, pod_targets).install! FileReferencesInstaller.new(sandbox, pod_targets).install!
end end
pod_targets.each do |pod_target| pod_targets.each do |target|
remove_target(pod_target.target) if pod_target.target remove_target(target.native_target) if target.native_target
UI.message "- Installing target `#{pod_target.name}` #{pod_target.platform}" do add_aggregate_target(target)
PodTargetInstaller.new(sandbox, pod_target).install!
end
end end
end end
...@@ -450,7 +464,9 @@ module Pod ...@@ -450,7 +464,9 @@ module Pod
# @return [void] # @return [void]
# #
def add_aggregate_target(target) def add_aggregate_target(target)
AggregateTargetInstaller.new(sandbox, target).install! UI.message "- Installing target `#{target}`" do
TargetInstaller.new(project, target).install!
end
end end
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
......
...@@ -3,28 +3,46 @@ module Pod ...@@ -3,28 +3,46 @@ module Pod
class PodsProjectGenerator class PodsProjectGenerator
# Controller class responsible of creating and configuring the static # Controller class responsible of creating and configuring the static
# target target in Pods project. It also creates the support file needed # target.native_target in Pods project. It also creates the support file needed
# by the target. # by the target.
# #
# Creates the target for the Pods libraries in the Pods project and the
# relative support files.
#
#
class TargetInstaller class TargetInstaller
# @return [Sandbox] sandbox the sandbox where the support files should # @return [Project] The project where the target should be installed.
# be generated.
# #
attr_reader :sandbox attr_reader :project
# @return [target] The target whose target needs to be generated. # @return [Target] The target whose native target needs to be
# generated.
# #
attr_reader :target attr_reader :target
# @param [Project] project @see project # @param [Project] project @see project
# @param [target] target @see target # @param [Target] target @see target
# #
def initialize(sandbox, target) def initialize(project, target)
@sandbox = sandbox @project = project
@target = target @target = target
end end
# Creates the target in the Pods project and the relative support
# files.
#
# @return [void]
#
def install!
add_target
unless target.is_a?(AggregateTarget)
add_files_to_build_phases
add_resources_bundle_targets
link_to_system_frameworks
end
end
private private
...@@ -56,31 +74,130 @@ module Pod ...@@ -56,31 +74,130 @@ module Pod
@native_target.add_build_configuration(bc_name, type) @native_target.add_build_configuration(bc_name, type)
end end
target.target = @native_target target.native_target = @native_target
end
# Adds the build files of the pods to the target and adds a reference to
# the frameworks of the Pods.
#
# @note The Frameworks are used only for presentation purposes as the
# xcconfig is the authoritative source about their information.
#
# @return [void]
#
def add_files_to_build_phases
target.file_accessors.each do |file_accessor|
consumer = file_accessor.spec_consumer
flags = compiler_flags_for_consumer(consumer, target.inhibits_warnings?)
source_files = file_accessor.source_files
file_refs = source_files.map { |sf| project.reference_for_path(sf) }
target.native_target.add_file_references(file_refs, flags)
end
end
# Adds the resources of the Pods to the Pods project.
#
# @note The source files are grouped by Pod and in turn by subspec
# (recursively) in the resources group.
#
# @return [void]
#
def add_resources_bundle_targets
# TODO: Move to a dedicated installer
target.file_accessors.each do |file_accessor|
file_accessor.resource_bundles.each do |bundle_name, paths|
file_references = paths.map { |sf| project.reference_for_path(sf) }
bundle_target = project.new_resources_bundle(bundle_name, file_accessor.spec_consumer.platform_name)
bundle_target.add_resources(file_references)
target.user_build_configurations.each do |bc_name, type|
bundle_target.add_build_configuration(bc_name, type)
end
target.add_dependency(bundle_target)
end
end
end end
# @return [PBXNativeTarget] the target generated by the installation # Add a file reference to the system frameworks if needed and links the
# process. # target to them.
# #
# @note Generated by the {#add_target} step. # This is done only for informative purposes as the xcconfigs are the
# authoritative source of the build settings.
# #
# TODO Remove # @return [void]
# #
attr_reader :native_target def link_to_system_frameworks
target.native_target.add_system_frameworks(target.frameworks)
target.native_target.add_system_libraries(target.libraries)
end
private private
# @!group Private helpers. # @!group Private helpers
#---------------------------------------------------------------------# #---------------------------------------------------------------------#
# @return [Project] the Pods project of the sandbox. # The minimum deployment targets where the `OS_OBJECT_USE_OBJC` flag
# should be used per platform name.
#
ENABLE_OBJECT_USE_OBJC_FROM = {
:ios => Version.new('6'),
:osx => Version.new('10.8')
}
# Returns the compiler flags for the source files of the given specification.
#
# The following behavior is regarding the `OS_OBJECT_USE_OBJC` flag. When
# set to `0`, it will allow code to use `dispatch_release()` on >= iOS 6.0
# and OS X 10.8.
#
# * New libraries that do *not* require ARC don’t need to care about this
# issue at all.
#
# * New libraries that *do* require ARC _and_ have a deployment target of
# >= iOS 6.0 or OS X 10.8:
#
# These no longer use `dispatch_release()` and should *not* have the
# `OS_OBJECT_USE_OBJC` flag set to `0`.
# #
def project # **Note:** this means that these libraries *have* to specify the
sandbox.project # deployment target in order to function well.
#
# * New libraries that *do* require ARC, but have a deployment target of
# < iOS 6.0 or OS X 10.8:
#
# These contain `dispatch_release()` calls and as such need the
# `OS_OBJECT_USE_OBJC` flag set to `1`.
#
# **Note:** libraries that do *not* specify a platform version are
# assumed to have a deployment target of < iOS 6.0 or OS X 10.8.
#
# For more information, see: http://opensource.apple.com/source/libdispatch/libdispatch-228.18/os/object.h
#
# @param [Specification::Consumer] consumer
# The consumer for the specification for which the compiler flags
# are needed.
#
# @return [String] The compiler flags.
#
def compiler_flags_for_consumer(consumer, inhibits_warnings = false)
flags = consumer.compiler_flags.dup
if consumer.requires_arc
flags << '-fobjc-arc'
platform_name = consumer.platform_name
spec_deployment_target = consumer.spec.deployment_target(platform_name)
if spec_deployment_target.nil? || Version.new(spec_deployment_target) < ENABLE_OBJECT_USE_OBJC_FROM[platform_name]
flags << '-DOS_OBJECT_USE_OBJC=0'
end
end
if inhibits_warnings
flags << '-w -Xanalyzer -analyzer-disable-checker'
end
flags.join(" ")
end end
#-----------------------------------------------------------------------# #---------------------------------------------------------------------#
end end
end end
......
module Pod
class Installer
class PodsProjectGenerator
# Creates the targets which aggregate the Pods libraries in the Pods
# project and the relative support files.
#
class AggregateTargetInstaller < TargetInstaller
# Creates the target in the Pods project and the relative support files.
#
# @return [void]
#
def install!
UI.message "- Installing target `#{target.name}` #{target.platform}" do
add_target
end
end
end
end
end
end
module Pod
class Installer
class PodsProjectGenerator
# Creates the target for the Pods libraries in the Pods project and the
# relative support files.
#
class PodTargetInstaller < TargetInstaller
# Creates the target in the Pods project and the relative support files.
#
# @return [void]
#
def install!
add_target
add_files_to_build_phases
add_resources_bundle_targets
link_to_system_frameworks
end
private
#-----------------------------------------------------------------------#
# Adds the build files of the pods to the target and adds a reference to
# the frameworks of the Pods.
#
# @note The Frameworks are used only for presentation purposes as the
# xcconfig is the authoritative source about their information.
#
# @return [void]
#
def add_files_to_build_phases
target.file_accessors.each do |file_accessor|
consumer = file_accessor.spec_consumer
flags = compiler_flags_for_consumer(consumer)
source_files = file_accessor.source_files
file_refs = source_files.map { |sf| project.reference_for_path(sf) }
target.target.add_file_references(file_refs, flags)
end
end
# Adds the resources of the Pods to the Pods project.
#
# @note The source files are grouped by Pod and in turn by subspec
# (recursively) in the resources group.
#
# @return [void]
#
def add_resources_bundle_targets
target.file_accessors.each do |file_accessor|
file_accessor.resource_bundles.each do |bundle_name, paths|
file_references = paths.map { |sf| project.reference_for_path(sf) }
bundle_target = project.new_resources_bundle(bundle_name, file_accessor.spec_consumer.platform_name)
bundle_target.add_resources(file_references)
target.user_build_configurations.each do |bc_name, type|
bundle_target.add_build_configuration(bc_name, type)
end
target.add_dependency(bundle_target)
end
end
end
# Add a file reference to the system frameworks if needed and links the
# target to them.
#
# This is done only for informative purposes as the xcconfigs are the
# authoritative source of the build settings.
#
# @return [void]
#
def link_to_system_frameworks
target.specs.each do |spec|
spec.consumer(target.platform).frameworks.each do |framework|
project.add_system_framework(framework, target.target)
end
end
end
# TODO
#
ENABLE_OBJECT_USE_OBJC_FROM = {
:ios => Version.new('6'),
:osx => Version.new('10.8')
}
# Returns the compiler flags for the source files of the given specification.
#
# The following behavior is regarding the `OS_OBJECT_USE_OBJC` flag. When
# set to `0`, it will allow code to use `dispatch_release()` on >= iOS 6.0
# and OS X 10.8.
#
# * New libraries that do *not* require ARC don’t need to care about this
# issue at all.
#
# * New libraries that *do* require ARC _and_ have a deployment target of
# >= iOS 6.0 or OS X 10.8:
#
# These no longer use `dispatch_release()` and should *not* have the
# `OS_OBJECT_USE_OBJC` flag set to `0`.
#
# **Note:** this means that these libraries *have* to specify the
# deployment target in order to function well.
#
# * New libraries that *do* require ARC, but have a deployment target of
# < iOS 6.0 or OS X 10.8:
#
# These contain `dispatch_release()` calls and as such need the
# `OS_OBJECT_USE_OBJC` flag set to `1`.
#
# **Note:** libraries that do *not* specify a platform version are
# assumed to have a deployment target of < iOS 6.0 or OS X 10.8.
#
# For more information, see: http://opensource.apple.com/source/libdispatch/libdispatch-228.18/os/object.h
#
# @param [Specification::Consumer] consumer
# The consumer for the specification for which the compiler flags
# are needed.
#
# @return [String] The compiler flags.
#
def compiler_flags_for_consumer(consumer)
flags = consumer.compiler_flags.dup
if consumer.requires_arc
flags << '-fobjc-arc'
platform_name = consumer.platform_name
spec_deployment_target = consumer.spec.deployment_target(platform_name)
if spec_deployment_target.nil? || Version.new(spec_deployment_target) < ENABLE_OBJECT_USE_OBJC_FROM[platform_name]
flags << '-DOS_OBJECT_USE_OBJC=0'
end
end
if target.target_definition.inhibits_warnings_for_pod?(consumer.spec.root.name)
flags << '-w -Xanalyzer -analyzer-disable-checker'
end
flags * " "
end
#-----------------------------------------------------------------------#
end
end
end
end
...@@ -44,7 +44,10 @@ module Pod ...@@ -44,7 +44,10 @@ module Pod
def inspect def inspect
"<#{self.class} name=#{name}>" "<#{self.class} name=#{name}>"
end end
alias :to_s :inspect
def to_s
"#{name} #{platform}"
end
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
...@@ -60,6 +63,8 @@ module Pod ...@@ -60,6 +63,8 @@ module Pod
# this library. # this library.
# #
attr_accessor :target attr_accessor :target
alias :native_target :target
alias :native_target= :target=
# @return [Platform] the platform for this library. # @return [Platform] the platform for this library.
# #
......
...@@ -13,6 +13,7 @@ module Pod ...@@ -13,6 +13,7 @@ module Pod
@sandbox = sandbox @sandbox = sandbox
@pod_targets = [] @pod_targets = []
@file_accessors = [] @file_accessors = []
@user_build_configurations = {}
end end
def skip_installation? def skip_installation?
......
...@@ -23,6 +23,7 @@ module Pod ...@@ -23,6 +23,7 @@ module Pod
@sandbox = sandbox @sandbox = sandbox
@build_headers = Sandbox::HeadersStore.new(sandbox, "BuildHeaders") @build_headers = Sandbox::HeadersStore.new(sandbox, "BuildHeaders")
@file_accessors = [] @file_accessors = []
@user_build_configurations = {}
end end
# @return [String] the label for the target. # @return [String] the label for the target.
...@@ -64,5 +65,17 @@ module Pod ...@@ -64,5 +65,17 @@ module Pod
end.flatten.reject { |dep| dep == pod_name } end.flatten.reject { |dep| dep == pod_name }
end end
def inhibits_warnings?
@inhibits_warnings ||= target_definition.inhibits_warnings_for_pod?(pod_name)
end
def frameworks
spec_consumers.map(&:frameworks).flatten.uniq
end
def libraries
spec_consumers.map(&:libraries).flatten.uniq
end
end end
end end
Subproject commit 684084445b742eb4c9e080d1b2a6a8ea66d23375 Subproject commit 47c921f09fe5c1f0079922c6e10be0de21513a4a
require File.expand_path('../../../../../spec_helper', __FILE__)
module Pod
describe Installer::PodsProjectGenerator::AggregateTargetInstaller do
describe "In General" do
before do
config.sandbox.project = Project.new(config.sandbox.project_path)
@target = AggregateTarget.new(@target_definition, config.sandbox)
@target.stubs(:label).returns('Pods')
@target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@target.user_build_configurations = { 'AppStore' => :release, 'Test' => :debug }
@sut = Installer::PodsProjectGenerator::AggregateTargetInstaller.new(config.sandbox, @target)
end
#-----------------------------------------------------------------------#
it 'adds the target for the static target to the project' do
@sut.install!
config.sandbox.project.targets.count.should == 1
config.sandbox.project.targets.first.name.should == 'Pods'
end
it "adds the user build configurations to the target" do
@sut.install!
target = config.sandbox.project.targets.first
target.build_settings('Test')["VALIDATE_PRODUCT"].should == nil
target.build_settings('AppStore')["VALIDATE_PRODUCT"].should == "YES"
end
it "sets VALIDATE_PRODUCT to YES for the Release configuration for iOS targets" do
@sut.install!
target = config.sandbox.project.targets.first
target.build_settings('Release')["VALIDATE_PRODUCT"].should == "YES"
end
it "sets the platform and the deployment target for iOS targets" do
@sut.install!
target = config.sandbox.project.targets.first
target.platform_name.should == :ios
target.deployment_target.should == "6.0"
target.build_settings('Debug')["IPHONEOS_DEPLOYMENT_TARGET"].should == "6.0"
target.build_settings('AppStore')["IPHONEOS_DEPLOYMENT_TARGET"].should == "6.0"
end
it "sets the platform and the deployment target for OS X targets" do
@target.stubs(:platform).returns(Platform.new(:osx, '10.8'))
@sut.install!
target = config.sandbox.project.targets.first
target.platform_name.should == :osx
target.deployment_target.should == "10.8"
target.build_settings('Debug')["MACOSX_DEPLOYMENT_TARGET"].should == "10.8"
target.build_settings('AppStore')["MACOSX_DEPLOYMENT_TARGET"].should == "10.8"
end
it "adds the user's build configurations to the target" do
@sut.install!
config.sandbox.project.targets.first.build_configurations.map(&:name).sort.should == %w{ AppStore Debug Release Test }
end
it "it creates different hash instances for the build settings of various build configurations" do
@sut.install!
build_settings = config.sandbox.project.targets.first.build_configurations.map(&:build_settings)
build_settings.map(&:object_id).uniq.count.should == 4
end
it "does not enable the GCC_WARN_INHIBIT_ALL_WARNINGS flag by default" do
@sut.install!
@sut.target.target.build_configurations.each do |config|
config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'].should.be.nil
end
end
#-----------------------------------------------------------------------#
end
end
end
require File.expand_path('../../../../../spec_helper', __FILE__)
module Pod
describe Installer::PodsProjectGenerator::PodTargetInstaller do
describe "In General" do
before do
@podfile = Podfile.new do
platform :ios
xcodeproj 'dummy'
end
@target_definition = @podfile.target_definitions['Pods']
@project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project
path_list = Sandbox::PathList.new(fixture('banana-lib'))
@spec = fixture_spec('banana-lib/BananaLib.podspec')
file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios))
@project.add_pod_group('BananaLib', fixture('banana-lib'))
group = @project.group_for_spec('BananaLib', :source_files)
file_accessor.source_files.each do |file|
@project.add_file_reference(file, group)
end
@pod_target = PodTarget.new([@spec], @target_definition, config.sandbox)
@pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@pod_target.file_accessors = [file_accessor]
@pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release }
@installer = Installer::PodsProjectGenerator::PodTargetInstaller.new(config.sandbox, @pod_target)
@spec.prefix_header_contents = '#import "BlocksKit.h"'
end
#--------------------------------------#
it 'adds the target for the static target to the project' do
@installer.install!
@project.targets.count.should == 1
@project.targets.first.name.should == 'Pods-BananaLib'
end
it "sets VALIDATE_PRODUCT to YES for the Release configuration for iOS targets" do
@installer.install!
target = @project.targets.first
target.build_settings('Release')["VALIDATE_PRODUCT"].should == "YES"
end
it "sets the platform and the deployment target for iOS targets" do
@installer.install!
target = @project.targets.first
target.platform_name.should == :ios
target.deployment_target.should == "6.0"
target.build_settings('Debug')["IPHONEOS_DEPLOYMENT_TARGET"].should == "6.0"
end
it "sets the platform and the deployment target for OS X targets" do
@pod_target.stubs(:platform).returns(Platform.new(:osx, '10.8'))
@installer.install!
target = @project.targets.first
target.platform_name.should == :osx
target.deployment_target.should == "10.8"
target.build_settings('Debug')["MACOSX_DEPLOYMENT_TARGET"].should == "10.8"
end
it "adds the user's build configurations to the target" do
@pod_target.user_build_configurations.merge!({ 'AppStore' => :release, 'Test' => :debug })
@installer.install!
@project.targets.first.build_configurations.map(&:name).sort.should == %w{ AppStore Debug Release Test }
end
it "it creates different hash instances for the build settings of various build configurations" do
@installer.install!
build_settings = @project.targets.first.build_configurations.map(&:build_settings)
build_settings.map(&:object_id).uniq.count.should == 2
end
it "does not enable the GCC_WARN_INHIBIT_ALL_WARNINGS flag by default" do
@installer.install!
@installer.target.target.build_configurations.each do |config|
config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'].should.be.nil
end
end
#--------------------------------------#
it 'adds the source files of each pod to the target of the Pod target' do
@installer.install!
names = @installer.target.target.source_build_phase.files.map { |bf| bf.file_ref.display_name }
names.should.include("Banana.m")
end
#--------------------------------------#
xit 'adds the resource bundle targets' do
end
xit 'adds the build configurations to the resources bundle targets' do
end
#--------------------------------------#
xit 'links to system frameworks' do
end
#--------------------------------------------------------------------------------#
describe "concerning ARC before and after iOS 6.0 and OS X 10.8" do
before do
@spec = Pod::Spec.new
end
it "does not do anything if ARC is *not* required" do
@spec.requires_arc = false
@spec.ios.deployment_target = '5'
@spec.osx.deployment_target = '10.6'
ios_flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
osx_flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:osx))
ios_flags.should.not.include '-DOS_OBJECT_USE_OBJC'
osx_flags.should.not.include '-DOS_OBJECT_USE_OBJC'
end
it "does *not* disable the `OS_OBJECT_USE_OBJC` flag if ARC is required and has a deployment target of >= iOS 6.0 or OS X 10.8" do
@spec.requires_arc = false
@spec.ios.deployment_target = '6'
@spec.osx.deployment_target = '10.8'
ios_flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
osx_flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:osx))
ios_flags.should.not.include '-DOS_OBJECT_USE_OBJC'
osx_flags.should.not.include '-DOS_OBJECT_USE_OBJC'
end
it "*does* disable the `OS_OBJECT_USE_OBJC` flag if ARC is required but has a deployment target < iOS 6.0 or OS X 10.8" do
@spec.requires_arc = true
@spec.ios.deployment_target = '5.1'
@spec.osx.deployment_target = '10.7.2'
ios_flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
osx_flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:osx))
ios_flags.should.include '-DOS_OBJECT_USE_OBJC'
osx_flags.should.include '-DOS_OBJECT_USE_OBJC'
end
it "*does* disable the `OS_OBJECT_USE_OBJC` flag if ARC is required and *no* deployment target is specified" do
@spec.requires_arc = true
ios_flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
osx_flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:osx))
ios_flags.should.include '-DOS_OBJECT_USE_OBJC'
osx_flags.should.include '-DOS_OBJECT_USE_OBJC'
end
it "adds -w per pod if target definition inhibits warnings for that pod" do
@installer.target.target_definition.stubs(:inhibits_warnings_for_pod?).returns(true)
flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
flags.should.include?('-w')
end
it "doesn't inhibit warnings by default" do
flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
flags.should.not.include?('-w')
end
it "adds -Xanalyzer -analyzer-disable-checker per pod" do
@installer.target.target_definition.stubs(:inhibits_warnings_for_pod?).returns(true)
flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
flags.should.include?('-Xanalyzer -analyzer-disable-checker')
end
it "doesn't inhibit analyzer warnings by default" do
flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
flags.should.not.include?('-Xanalyzer -analyzer-disable-checker')
end
end
end
end
end
...@@ -3,48 +3,232 @@ require File.expand_path('../../../../spec_helper', __FILE__) ...@@ -3,48 +3,232 @@ require File.expand_path('../../../../spec_helper', __FILE__)
module Pod module Pod
describe Installer::PodsProjectGenerator::TargetInstaller do describe Installer::PodsProjectGenerator::TargetInstaller do
before do describe "#install!" do
@podfile = Podfile.new do xit 'adds the target for the static target to the project' do
platform :ios @sut.send(:add_target)
xcodeproj 'dummy' @project.targets.count.should == 1
end @project.targets.first.name.should == 'Pods'
@target_definition = @podfile.target_definitions['Pods'] end
@project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project
path_list = Sandbox::PathList.new(fixture('banana-lib'))
@spec = fixture_spec('banana-lib/BananaLib.podspec')
file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios))
@project.add_pod_group('BananaLib', fixture('banana-lib'))
group = @project.group_for_spec('BananaLib', :source_files)
file_accessor.source_files.each do |file|
@project.add_file_reference(file, group)
end
@pod_target = PodTarget.new([@spec], @target_definition, config.sandbox)
@pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug }
@pod_target.file_accessors = [file_accessor]
@installer = Installer::PodsProjectGenerator::TargetInstaller.new(config.sandbox, @pod_target)
end end
it "sets the ARCHS" do #-------------------------------------------------------------------------#
@installer.send(:add_target)
target = @project.targets.first describe "#add_target" do
target.build_settings('Debug')["ARCHS"].should == "$(ARCHS_STANDARD_32_BIT)"
target.build_settings('AppStore')["ARCHS"].should == "$(ARCHS_STANDARD_32_BIT)" before do
target.build_settings('Debug')["ONLY_ACTIVE_ARCH"].should.be.nil @project = Project.new(config.sandbox.project_path)
target.build_settings('AppStore')["ONLY_ACTIVE_ARCH"].should.be.nil target = AggregateTarget.new(nil, config.sandbox)
target.stubs(:label).returns('Pods')
target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@sut = Installer::PodsProjectGenerator::TargetInstaller.new(@project, target)
end
it 'adds the target for the static target to the project' do
@sut.send(:add_target)
@project.targets.count.should == 1
@project.targets.first.name.should == 'Pods'
end
it "sets the ARCHS" do
@sut.send(:add_target)
target = @project.targets.first
target.build_settings('Debug')["ARCHS"].should == "$(ARCHS_STANDARD_32_BIT)"
target.build_settings('Debug')["ONLY_ACTIVE_ARCH"].should.be.nil
end
it "sets ARCHS to 'armv6 armv7' for both configurations if the deployment target is less than 4.3 for iOS targets" do
@sut.target.stubs(:platform).returns(Platform.new(:ios, '4.0'))
@sut.send(:add_target)
target = @project.targets.first
target.build_settings('Debug')["ARCHS"].should == "armv6 armv7"
target.build_settings('Release')["ARCHS"].should == "armv6 armv7"
end
it "sets VALIDATE_PRODUCT to YES for the Release configuration for iOS targets" do
@sut.send(:add_target)
target = @project.targets.first
target.build_settings('Release')["VALIDATE_PRODUCT"].should == "YES"
end
it "sets the platform and the deployment target for iOS targets" do
@sut.install!
target = @project.targets.first
target.platform_name.should == :ios
target.deployment_target.should == "6.0"
target.build_settings('Debug')["IPHONEOS_DEPLOYMENT_TARGET"].should == "6.0"
end
it "sets the platform and the deployment target for OS X targets" do
@sut.target.stubs(:platform).returns(Platform.new(:osx, '10.8'))
@sut.install!
target = @project.targets.first
target.platform_name.should == :osx
target.deployment_target.should == "10.8"
target.build_settings('Debug')["MACOSX_DEPLOYMENT_TARGET"].should == "10.8"
end
it "adds the user's build configurations to the target" do
@sut.target.user_build_configurations = { 'AppStore' => :release, 'Test' => :debug }
@sut.send(:add_target)
@project.targets.first.build_configurations.map(&:name).sort.should == %w{ AppStore Debug Release Test }
end
it "it creates different hash instances for the build settings of various build configurations" do
@sut.send(:add_target)
build_settings = @project.targets.first.build_configurations.map(&:build_settings)
build_settings.map(&:object_id).uniq.count.should == 2
end
it "does not enable the GCC_WARN_INHIBIT_ALL_WARNINGS flag by default" do
@sut.send(:add_target)
@sut.target.native_target.build_configurations.each do |config|
config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'].should.be.nil
end
end
end end
it "sets ARCHS to 'armv6 armv7' for both configurations if the deployment target is less than 4.3 for iOS targets" do #-------------------------------------------------------------------------#
@pod_target.stubs(:platform).returns(Platform.new(:ios, '4.0'))
@installer.send(:add_target) describe "In General" do
target = @project.targets.first before do
target.build_settings('Debug')["ARCHS"].should == "armv6 armv7" project = Project.new(config.sandbox.project_path)
target.build_settings('Release')["ARCHS"].should == "armv6 armv7" spec = fixture_spec('banana-lib/BananaLib.podspec')
file_accessor = fixture_file_accessor('banana-lib/BananaLib.podspec')
project.add_pod_group('BananaLib', fixture('banana-lib'))
group = project.group_for_spec('BananaLib', :source_files)
file_accessor.source_files.each do |file|
project.add_file_reference(file, group)
end
target = PodTarget.new([spec], nil, config.sandbox)
target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
target.file_accessors = [file_accessor]
target.stubs(:inhibits_warnings?).returns(false)
target.stubs(:label).returns('Pods-BananaLib')
@sut = Installer::PodsProjectGenerator::TargetInstaller.new(project, target)
@sut.send(:add_target)
end
it 'adds the source files of each pod to the target of the Pod target' do
@sut.send(:add_files_to_build_phases)
source_files = @sut.target.native_target.source_build_phase.files_references
source_files.map { |ref| ref.display_name }.should == ['Banana.m']
end
it 'sets the compiler flags of the source files' do
compiler_flag = '-flag'
Specification::Consumer.any_instance.stubs(:compiler_flags).returns([compiler_flag])
@sut.send(:add_files_to_build_phases)
build_files = @sut.target.native_target.source_build_phase.files
build_files.first.settings.should == { 'COMPILER_FLAGS' => compiler_flag }
end
end end
#-------------------------------------------------------------------------#
describe "#add_resources_bundle_targets" do
xit 'adds the resource bundle targets' do
end
xit 'adds the build configurations to the resources bundle targets' do
end
end
#-------------------------------------------------------------------------#
describe "#link_to_system_frameworks" do
before do
project = Project.new(config.sandbox.project_path)
target = PodTarget.new([], nil, config.sandbox)
target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
target.stubs(:label).returns('Pods-BananaLib')
@sut = Installer::PodsProjectGenerator::TargetInstaller.new(project, target)
@sut.send(:add_target)
end
it 'links to system frameworks' do
@sut.target.stubs(:frameworks).returns(['QuartzCore', 'QuartzCore'])
@sut.send(:link_to_system_frameworks)
build_files = @sut.target.native_target.frameworks_build_phase.files
build_files = @sut.target.native_target.frameworks_build_phase.file_display_names
build_files.should == ["Foundation.framework", "QuartzCore.framework"]
end
it 'links to system libraries' do
@sut.target.stubs(:libraries).returns(['z', 'xml2'])
@sut.send(:link_to_system_frameworks)
build_files = @sut.target.native_target.frameworks_build_phase.file_display_names
build_files.should == ["Foundation.framework", "libz.dylib", "libxml2.dylib"]
end
end
#-----------------------------------------------------------------------#
describe "#compiler_flags_for_consumer" do
before do
@spec = Pod::Spec.new
@sut = Installer::PodsProjectGenerator::TargetInstaller.new(nil, nil)
end
it "does not do anything if ARC is *not* required" do
@spec.requires_arc = false
@spec.ios.deployment_target = '5'
@spec.osx.deployment_target = '10.6'
ios_flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
osx_flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:osx))
ios_flags.should.not.include '-DOS_OBJECT_USE_OBJC'
osx_flags.should.not.include '-DOS_OBJECT_USE_OBJC'
end
it "does *not* disable the `OS_OBJECT_USE_OBJC` flag if ARC is required and has a deployment target of >= iOS 6.0 or OS X 10.8" do
@spec.requires_arc = false
@spec.ios.deployment_target = '6'
@spec.osx.deployment_target = '10.8'
ios_flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
osx_flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:osx))
ios_flags.should.not.include '-DOS_OBJECT_USE_OBJC'
osx_flags.should.not.include '-DOS_OBJECT_USE_OBJC'
end
it "*does* disable the `OS_OBJECT_USE_OBJC` flag if ARC is required but has a deployment target < iOS 6.0 or OS X 10.8" do
@spec.requires_arc = true
@spec.ios.deployment_target = '5.1'
@spec.osx.deployment_target = '10.7.2'
ios_flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
osx_flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:osx))
ios_flags.should.include '-DOS_OBJECT_USE_OBJC'
osx_flags.should.include '-DOS_OBJECT_USE_OBJC'
end
it "*does* disable the `OS_OBJECT_USE_OBJC` flag if ARC is required and *no* deployment target is specified" do
@spec.requires_arc = true
ios_flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:ios))
osx_flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:osx))
ios_flags.should.include '-DOS_OBJECT_USE_OBJC'
osx_flags.should.include '-DOS_OBJECT_USE_OBJC'
end
it "adds -w per pod if target definition inhibits warnings for that pod" do
flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:ios), true)
flags.should.include?('-w')
flags.should.include?('-Xanalyzer -analyzer-disable-checker')
end
it "doesn't inhibit warnings by default" do
flags = @sut.send(:compiler_flags_for_consumer, @spec.consumer(:ios), false)
flags.should.not.include?('-w')
flags.should.not.include?('-Xanalyzer -analyzer-disable-checker')
end
end
#-----------------------------------------------------------------------#
end end
end end
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