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
@project.targets.first.name.should == 'Pods'
end 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 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 } describe "#add_target" do
@pod_target.file_accessors = [file_accessor]
@installer = Installer::PodsProjectGenerator::TargetInstaller.new(config.sandbox, @pod_target) before do
@project = Project.new(config.sandbox.project_path)
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 end
it "sets the ARCHS" do it "sets the ARCHS" do
@installer.send(:add_target) @sut.send(:add_target)
target = @project.targets.first target = @project.targets.first
target.build_settings('Debug')["ARCHS"].should == "$(ARCHS_STANDARD_32_BIT)" target.build_settings('Debug')["ARCHS"].should == "$(ARCHS_STANDARD_32_BIT)"
target.build_settings('AppStore')["ARCHS"].should == "$(ARCHS_STANDARD_32_BIT)"
target.build_settings('Debug')["ONLY_ACTIVE_ARCH"].should.be.nil target.build_settings('Debug')["ONLY_ACTIVE_ARCH"].should.be.nil
target.build_settings('AppStore')["ONLY_ACTIVE_ARCH"].should.be.nil
end end
it "sets ARCHS to 'armv6 armv7' for both configurations if the deployment target is less than 4.3 for iOS targets" do 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')) @sut.target.stubs(:platform).returns(Platform.new(:ios, '4.0'))
@installer.send(:add_target) @sut.send(:add_target)
target = @project.targets.first target = @project.targets.first
target.build_settings('Debug')["ARCHS"].should == "armv6 armv7" target.build_settings('Debug')["ARCHS"].should == "armv6 armv7"
target.build_settings('Release')["ARCHS"].should == "armv6 armv7" target.build_settings('Release')["ARCHS"].should == "armv6 armv7"
end 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
#-------------------------------------------------------------------------#
describe "In General" do
before do
project = Project.new(config.sandbox.project_path)
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
#-------------------------------------------------------------------------#
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