Remove all PBX state from targets, improve project generation performance

parent 1c6dedd1
...@@ -8,6 +8,10 @@ To install release candidates run `[sudo] gem install cocoapods --pre` ...@@ -8,6 +8,10 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
##### Enhancements ##### Enhancements
* Remove all PBX state from targets, improve project generation performance
[Dimitris Koutsogiorgas](https://github.com/dnkoutso)
[#7610](https://github.com/CocoaPods/CocoaPods/pull/7610)
* Improve performance of the dependency resolver by removing duplicates for dependency nodes. * Improve performance of the dependency resolver by removing duplicates for dependency nodes.
[Jacek Suliga](https://github.com/jmkk) [Jacek Suliga](https://github.com/jmkk)
......
...@@ -173,14 +173,14 @@ module Pod ...@@ -173,14 +173,14 @@ module Pod
private private
def create_generator def create_generator
Xcode::PodsProjectGenerator.new(aggregate_targets, sandbox, pod_targets, analysis_result, installation_options, config) Xcode::PodsProjectGenerator.new(sandbox, aggregate_targets, pod_targets, analysis_result, installation_options, config)
end end
# Generate the 'Pods/Pods.xcodeproj' project. # Generate the 'Pods/Pods.xcodeproj' project.
# #
def generate_pods_project(generator = create_generator) def generate_pods_project(generator = create_generator)
UI.section 'Generating Pods project' do UI.section 'Generating Pods project' do
generator.generate! @target_installation_results = generator.generate!
@pods_project = generator.project @pods_project = generator.project
run_podfile_post_install_hooks run_podfile_post_install_hooks
generator.write generator.write
...@@ -200,6 +200,11 @@ module Pod ...@@ -200,6 +200,11 @@ module Pod
# #
attr_reader :analysis_result attr_reader :analysis_result
# @return [Array<Hash{String, TargetInstallationResult}>] the installation results produced by the pods project
# generator
#
attr_reader :target_installation_results
# @return [Pod::Project] the `Pods/Pods.xcodeproj` project. # @return [Pod::Project] the `Pods/Pods.xcodeproj` project.
# #
attr_reader :pods_project attr_reader :pods_project
......
...@@ -8,21 +8,21 @@ module Pod ...@@ -8,21 +8,21 @@ module Pod
class AggregateTargetInstaller < TargetInstaller class AggregateTargetInstaller < TargetInstaller
# Creates the target in the Pods project and the relative support files. # Creates the target in the Pods project and the relative support files.
# #
# @return [void] # @return [TargetInstallationResult] the result of the installation of this target.
# #
def install! def install!
UI.message "- Installing target `#{target.name}` #{target.platform}" do UI.message "- Installing target `#{target.name}` #{target.platform}" do
add_target native_target = add_target
create_support_files_dir create_support_files_dir
create_support_files_group create_support_files_group
create_xcconfig_file create_xcconfig_file(native_target)
if target.requires_frameworks? if target.requires_frameworks?
create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform) create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform)
create_module_map create_module_map(native_target)
create_umbrella_header create_umbrella_header(native_target)
elsif target.uses_swift? elsif target.uses_swift?
create_module_map create_module_map(native_target)
create_umbrella_header create_umbrella_header(native_target)
end end
# Because embedded targets live in their host target, CocoaPods # Because embedded targets live in their host target, CocoaPods
# copies all of the embedded target's pod_targets to its host # copies all of the embedded target's pod_targets to its host
...@@ -31,10 +31,11 @@ module Pod ...@@ -31,10 +31,11 @@ module Pod
# embedded in embedded targets. # embedded in embedded targets.
# #
create_embed_frameworks_script unless target.requires_host_target? create_embed_frameworks_script unless target.requires_host_target?
create_bridge_support_file create_bridge_support_file(native_target)
create_copy_resources_script create_copy_resources_script
create_acknowledgements create_acknowledgements
create_dummy_source create_dummy_source(native_target)
TargetInstallationResult.new(target, native_target)
end end
end end
...@@ -87,9 +88,12 @@ module Pod ...@@ -87,9 +88,12 @@ module Pod
# Generates the contents of the xcconfig file and saves it to disk. # Generates the contents of the xcconfig file and saves it to disk.
# #
# @param [PBXNativeTarget] native_target
# the native target to link the module map file into.
#
# @return [void] # @return [void]
# #
def create_xcconfig_file def create_xcconfig_file(native_target)
native_target.build_configurations.each do |configuration| native_target.build_configurations.each do |configuration|
path = target.xcconfig_path(configuration.name) path = target.xcconfig_path(configuration.name)
gen = Generator::XCConfig::AggregateXCConfig.new(target, configuration.name) gen = Generator::XCConfig::AggregateXCConfig.new(target, configuration.name)
...@@ -106,9 +110,12 @@ module Pod ...@@ -106,9 +110,12 @@ module Pod
# target because it is needed for environments interpreted at # target because it is needed for environments interpreted at
# runtime. # runtime.
# #
# @param [PBXNativeTarget] native_target
# the native target to add the bridge support file into.
#
# @return [void] # @return [void]
# #
def create_bridge_support_file def create_bridge_support_file(native_target)
if target.podfile.generate_bridge_support? if target.podfile.generate_bridge_support?
path = target.bridge_support_path path = target.bridge_support_path
headers = native_target.headers_build_phase.files.map { |bf| sandbox.root + bf.file_ref.path } headers = native_target.headers_build_phase.files.map { |bf| sandbox.root + bf.file_ref.path }
......
...@@ -6,16 +6,16 @@ module Pod ...@@ -6,16 +6,16 @@ module Pod
# the test targets included by each pod target. # the test targets included by each pod target.
# #
class PodTargetIntegrator class PodTargetIntegrator
# @return [PodTarget] the target that should be integrated. # @return [TargetInstallationResult] the installation result of the target that should be integrated.
# #
attr_reader :target attr_reader :target_installation_result
# Init a new PodTargetIntegrator. # Initialize a new instance
# #
# @param [PodTarget] target @see #target # @param [TargetInstallationResult] target_installation_result @see #target_installation_result
# #
def initialize(target) def initialize(target_installation_result)
@target = target @target_installation_result = target_installation_result
end end
# Integrates the pod target. # Integrates the pod target.
...@@ -24,13 +24,13 @@ module Pod ...@@ -24,13 +24,13 @@ module Pod
# #
def integrate! def integrate!
UI.section(integration_message) do UI.section(integration_message) do
target.test_specs_by_native_target.each do |native_target, test_specs| target_installation_result.test_specs_by_native_target.each do |test_native_target, test_specs|
add_embed_frameworks_script_phase(native_target) add_embed_frameworks_script_phase(test_native_target)
add_copy_resources_script_phase(native_target) add_copy_resources_script_phase(test_native_target)
UserProjectIntegrator::TargetIntegrator.create_or_update_user_script_phases(script_phases_for_specs(test_specs), native_target) UserProjectIntegrator::TargetIntegrator.create_or_update_user_script_phases(script_phases_for_specs(test_specs), test_native_target)
end end
specs = target.non_test_specs specs = target.non_test_specs
UserProjectIntegrator::TargetIntegrator.create_or_update_user_script_phases(script_phases_for_specs(specs), target.native_target) UserProjectIntegrator::TargetIntegrator.create_or_update_user_script_phases(script_phases_for_specs(specs), target_installation_result.native_target)
end end
end end
...@@ -89,6 +89,12 @@ module Pod ...@@ -89,6 +89,12 @@ module Pod
"Integrating target `#{target.name}`" "Integrating target `#{target.name}`"
end end
# @return [PodTarget] the target part of the installation result.
#
def target
target_installation_result.target
end
# @param [Array<Specification] specs # @param [Array<Specification] specs
# the specs to return script phrases from. # the specs to return script phrases from.
# #
......
module Pod
class Installer
class Xcode
class PodsProjectGenerator
# A simple container produced after a target installation is completed.
#
class TargetInstallationResult
# @return [Target] target
# The target this installation result is for.
#
attr_reader :target
# @return [PBXNativeTarget] native_target
# The native target that was produced for this target.
#
attr_reader :native_target
# @return [Array<PBXNativeTarget>] resource_bundle_targets
# The resource bundle targets that were produced for this target. Can be empty if the target had
# no resource bundles.
#
attr_reader :resource_bundle_targets
# @return [Array<PBXNativeTarget>] test_native_targets
# The test native targets that were produced for this target. Can be empty if there were no test
# native targets created (e.g. no test specs present).
#
attr_reader :test_native_targets
# @return [Array<PBXNativeTarget>] test_resource_bundle_targets
# The test resource bundle targets that were produced for this target. Can be empty if the target had
# no resource bundles for any tests.
#
attr_reader :test_resource_bundle_targets
# @return [Array<PBXNativeTarget>] test_app_host_targets
# The test app host native targets that were produced for this target. Can be empty.
#
attr_reader :test_app_host_targets
# Initialize a new instance
#
# @param [Target] target @see #target
# @param [PBXNativeTarget] native_target @see #native_target
# @param [Array<PBXNativeTarget>] resource_bundle_targets @see #resource_bundle_targets
# @param [Array<PBXNativeTarget>] test_native_targets @see #test_native_targets
# @param [Array<PBXNativeTarget>] test_resource_bundle_targets @see #test_resource_bundle_targets
# @param [Array<PBXNativeTarget>] test_app_host_targets @see #test_app_host_targets
#
def initialize(target, native_target, resource_bundle_targets = [], test_native_targets = [],
test_resource_bundle_targets = [], test_app_host_targets = [])
@target = target
@native_target = native_target
@resource_bundle_targets = resource_bundle_targets
@test_native_targets = test_native_targets
@test_resource_bundle_targets = test_resource_bundle_targets
@test_app_host_targets = test_app_host_targets
end
# Returns the corresponding native target to use based on the provided specification.
#
# @param [Specification] spec
# The specification to base from in order to find the native target.
#
# @return [PBXNativeTarget] the native target to use or `nil` if none is found.
#
def native_target_for_spec(spec)
return native_target unless spec.test_specification?
test_native_target_from_spec(spec)
end
# @return [Hash{Array => Specification}] a hash where the keys are the test native targets and the value
# an array of all the test specs associated with this native target.
#
def test_specs_by_native_target
target.test_specs.group_by do |test_spec|
test_native_target_from_spec(test_spec)
end
end
private
def test_native_target_from_spec(spec)
test_native_targets.find do |test_native_target|
test_native_target.symbol_type == target.product_type_for_test_type(spec.test_type)
end
end
end
end
end
end
end
...@@ -45,28 +45,28 @@ module Pod ...@@ -45,28 +45,28 @@ module Pod
# #
# @note The `PODS_HEADERS_SEARCH_PATHS` overrides the xcconfig. # @note The `PODS_HEADERS_SEARCH_PATHS` overrides the xcconfig.
# #
# @return [void] # @return [PBXNativeTarget] the native target that was added.
# #
def add_target def add_target
product_type = target.product_type product_type = target.product_type
name = target.label name = target.label
platform = target.platform.name platform = target.platform.name
language = target.uses_swift? ? :swift : :objc language = target.uses_swift? ? :swift : :objc
@native_target = project.new_target(product_type, name, platform, deployment_target, nil, language) native_target = project.new_target(product_type, name, platform, deployment_target, nil, language)
product_name = target.product_name product_name = target.product_name
product = @native_target.product_reference product = native_target.product_reference
product.name = product_name product.name = product_name
target.user_build_configurations.each do |bc_name, type| target.user_build_configurations.each do |bc_name, type|
@native_target.add_build_configuration(bc_name, type) native_target.add_build_configuration(bc_name, type)
end end
@native_target.build_configurations.each do |configuration| native_target.build_configurations.each do |configuration|
configuration.build_settings.merge!(custom_build_settings) configuration.build_settings.merge!(custom_build_settings)
end end
target.native_target = @native_target native_target
end end
# @return [String] The deployment target. # @return [String] The deployment target.
...@@ -175,9 +175,12 @@ module Pod ...@@ -175,9 +175,12 @@ module Pod
# Creates the module map file which ensures that the umbrella header is # Creates the module map file which ensures that the umbrella header is
# recognized with a customized path # recognized with a customized path
# #
# @param [PBXNativeTarget] native_target
# the native target to link the module map file into.
#
# @return [void] # @return [void]
# #
def create_module_map def create_module_map(native_target)
path = target.module_map_path path = target.module_map_path
UI.message "- Generating module map file at #{UI.path(path)}" do UI.message "- Generating module map file at #{UI.path(path)}" do
generator = Generator::ModuleMap.new(target) generator = Generator::ModuleMap.new(target)
...@@ -195,10 +198,15 @@ module Pod ...@@ -195,10 +198,15 @@ module Pod
# Generates a header which ensures that all header files are exported # Generates a header which ensures that all header files are exported
# in the module map # in the module map
# #
# @param [PBXNativeTarget] native_target
# the native target to link the umbrella header file into.
#
# @yield_param [Generator::UmbrellaHeader] # @yield_param [Generator::UmbrellaHeader]
# yielded once to configure the imports # yielded once to configure the imports
# #
def create_umbrella_header # @return [void]
#
def create_umbrella_header(native_target)
path = target.umbrella_header_path path = target.umbrella_header_path
UI.message "- Generating umbrella header at #{UI.path(path)}" do UI.message "- Generating umbrella header at #{UI.path(path)}" do
generator = Generator::UmbrellaHeader.new(target) generator = Generator::UmbrellaHeader.new(target)
...@@ -220,9 +228,12 @@ module Pod ...@@ -220,9 +228,12 @@ module Pod
# Generates a dummy source file for each target so libraries that contain # Generates a dummy source file for each target so libraries that contain
# only categories build. # only categories build.
# #
# @param [PBXNativeTarget] native_target
# the native target to link the dummy source file into.
#
# @return [void] # @return [void]
# #
def create_dummy_source def create_dummy_source(native_target)
path = target.dummy_source_path path = target.dummy_source_path
generator = Generator::DummySource.new(target.label) generator = Generator::DummySource.new(target.label)
update_changed_file(generator, path) update_changed_file(generator, path)
...@@ -230,13 +241,6 @@ module Pod ...@@ -230,13 +241,6 @@ module Pod
native_target.source_build_phase.add_file_reference(file_reference) native_target.source_build_phase.add_file_reference(file_reference)
end end
# @return [PBXNativeTarget] the target generated by the installation
# process.
#
# @note Generated by the {#add_target} step.
#
attr_reader :native_target
private private
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
......
...@@ -142,6 +142,8 @@ module Pod ...@@ -142,6 +142,8 @@ module Pod
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# @!group Framework support
# @return [Boolean] whether the generated target needs to be implemented # @return [Boolean] whether the generated target needs to be implemented
# as a framework # as a framework
# #
...@@ -151,13 +153,6 @@ module Pod ...@@ -151,13 +153,6 @@ module Pod
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# @return [PBXNativeTarget] the target generated in the Pods project for
# this library.
#
attr_accessor :native_target
#-------------------------------------------------------------------------#
# @!group Support files # @!group Support files
# @return [Pathname] the folder where to store the support files of this # @return [Pathname] the folder where to store the support files of this
......
...@@ -63,7 +63,8 @@ module Pod ...@@ -63,7 +63,8 @@ module Pod
# @param [Array<String>] user_target_uuids @see #user_target_uuids # @param [Array<String>] user_target_uuids @see #user_target_uuids
# @param [Array<PodTarget>] pod_targets @see #pod_targets # @param [Array<PodTarget>] pod_targets @see #pod_targets
# #
def initialize(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, target_definition, client_root, user_project, user_target_uuids, pod_targets) def initialize(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, target_definition,
client_root, user_project, user_target_uuids, pod_targets)
super(sandbox, host_requires_frameworks, user_build_configurations, archs, platform) super(sandbox, host_requires_frameworks, user_build_configurations, archs, platform)
raise "Can't initialize an AggregateTarget without a TargetDefinition!" if target_definition.nil? raise "Can't initialize an AggregateTarget without a TargetDefinition!" if target_definition.nil?
raise "Can't initialize an AggregateTarget with an abstract TargetDefinition!" if target_definition.abstract? raise "Can't initialize an AggregateTarget with an abstract TargetDefinition!" if target_definition.abstract?
......
...@@ -48,21 +48,6 @@ module Pod ...@@ -48,21 +48,6 @@ module Pod
# #
attr_accessor :test_dependent_targets attr_accessor :test_dependent_targets
# return [Array<PBXNativeTarget>] the test target generated in the Pods project for
# this library or `nil` if there is no test target created.
#
attr_accessor :test_native_targets
# @return [Array<PBXNativeTarget>] the resource bundle targets belonging
# to this target.
#
attr_reader :resource_bundle_targets
# @return [Array<PBXNativeTarget>] the resource bundle test targets belonging
# to this target.
#
attr_reader :test_resource_bundle_targets
# Initialize a new instance # Initialize a new instance
# #
# @param [Sandbox] sandbox @see Target#sandbox # @param [Sandbox] sandbox @see Target#sandbox
...@@ -74,7 +59,8 @@ module Pod ...@@ -74,7 +59,8 @@ module Pod
# @param [Array<Sandbox::FileAccessor>] file_accessors @see #file_accessors # @param [Array<Sandbox::FileAccessor>] file_accessors @see #file_accessors
# @param [String] scope_suffix @see #scope_suffix # @param [String] scope_suffix @see #scope_suffix
# #
def initialize(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs, target_definitions, file_accessors = [], scope_suffix = nil) def initialize(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs,
target_definitions, file_accessors = [], scope_suffix = nil)
super(sandbox, host_requires_frameworks, user_build_configurations, archs, platform) super(sandbox, host_requires_frameworks, user_build_configurations, archs, platform)
raise "Can't initialize a PodTarget without specs!" if specs.nil? || specs.empty? raise "Can't initialize a PodTarget without specs!" if specs.nil? || specs.empty?
raise "Can't initialize a PodTarget without TargetDefinition!" if target_definitions.nil? || target_definitions.empty? raise "Can't initialize a PodTarget without TargetDefinition!" if target_definitions.nil? || target_definitions.empty?
...@@ -86,9 +72,6 @@ module Pod ...@@ -86,9 +72,6 @@ module Pod
@scope_suffix = scope_suffix @scope_suffix = scope_suffix
@test_specs, @non_test_specs = @specs.partition(&:test_specification?) @test_specs, @non_test_specs = @specs.partition(&:test_specification?)
@build_headers = Sandbox::HeadersStore.new(sandbox, 'Private', :private) @build_headers = Sandbox::HeadersStore.new(sandbox, 'Private', :private)
@resource_bundle_targets = []
@test_resource_bundle_targets = []
@test_native_targets = []
@dependent_targets = [] @dependent_targets = []
@test_dependent_targets = [] @test_dependent_targets = []
@build_config_cache = {} @build_config_cache = {}
...@@ -108,7 +91,6 @@ module Pod ...@@ -108,7 +91,6 @@ module Pod
cache[cache_key] cache[cache_key]
else else
target = PodTarget.new(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs, [target_definition], file_accessors, target_definition.label) target = PodTarget.new(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs, [target_definition], file_accessors, target_definition.label)
target.native_target = native_target
target.dependent_targets = dependent_targets.flat_map { |pt| pt.scoped(cache) }.select { |pt| pt.target_definitions == [target_definition] } target.dependent_targets = dependent_targets.flat_map { |pt| pt.scoped(cache) }.select { |pt| pt.target_definitions == [target_definition] }
target.test_dependent_targets = test_dependent_targets.flat_map { |pt| pt.scoped(cache) }.select { |pt| pt.target_definitions == [target_definition] } target.test_dependent_targets = test_dependent_targets.flat_map { |pt| pt.scoped(cache) }.select { |pt| pt.target_definitions == [target_definition] }
cache[cache_key] = target cache[cache_key] = target
...@@ -218,13 +200,6 @@ module Pod ...@@ -218,13 +200,6 @@ module Pod
!script_phases.empty? !script_phases.empty?
end end
# @return [Hash{Array => Specification}] a hash where the keys are the test native targets and the value
# an array of all the test specs associated with this native target.
#
def test_specs_by_native_target
test_specs.group_by { |test_spec| native_target_for_spec(test_spec) }
end
# @return [Boolean] Whether the target has any tests specifications. # @return [Boolean] Whether the target has any tests specifications.
# #
def contains_test_specifications? def contains_test_specifications?
...@@ -304,22 +279,6 @@ module Pod ...@@ -304,22 +279,6 @@ module Pod
end end
end end
# Returns the corresponding native target to use based on the provided specification.
# This is used to figure out whether to add a source file into the library native target or any of the
# test native targets.
#
# @param [Specification] spec
# The specification to base from in order to find the native target.
#
# @return [PBXNativeTarget] the native target to use or `nil` if none is found.
#
def native_target_for_spec(spec)
return native_target unless spec.test_specification?
test_native_targets.find do |native_target|
native_target.symbol_type == product_type_for_test_type(spec.test_type)
end
end
# Returns the corresponding native product type to use given the test type. # Returns the corresponding native product type to use given the test type.
# This is primarily used when creating the native targets in order to produce the correct test bundle target # This is primarily used when creating the native targets in order to produce the correct test bundle target
# based on the type of tests included. # based on the type of tests included.
......
...@@ -501,43 +501,33 @@ module Pod ...@@ -501,43 +501,33 @@ module Pod
perform_post_install_actions).each { |m| @installer.send(m) } perform_post_install_actions).each { |m| @installer.send(m) }
deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name) deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name)
configure_pod_targets(@installer.aggregate_targets, deployment_target) configure_pod_targets(@installer.aggregate_targets, @installer.target_installation_results, deployment_target)
@installer.pods_project.save @installer.pods_project.save
end end
def configure_pod_targets(targets, deployment_target) def configure_pod_targets(targets, target_installation_results, deployment_target)
test_only_pod_targets = @installer.pod_targets - targets.flat_map(&:pod_targets) target_installation_results.first.values.each do |pod_target_installation_result|
targets.each do |target| pod_target = pod_target_installation_result.target
target.pod_targets.each do |pod_target| native_target = pod_target_installation_result.native_target
update_pod_target_build_settings(pod_target) native_target.build_configuration_list.build_configurations.each do |build_configuration|
if pod_target.uses_swift? (build_configuration.build_settings['OTHER_CFLAGS'] ||= '$(inherited)') << ' -Wincomplete-umbrella'
pod_target.test_native_targets.each do |test_native_target| build_configuration.build_settings['SWIFT_VERSION'] = (pod_target.swift_version || swift_version) if pod_target.uses_swift?
test_native_target.build_configuration_list.build_configurations.each do |build_configuration| end
build_configuration.build_settings['SWIFT_VERSION'] = swift_version if pod_target.uses_swift?
end pod_target_installation_result.test_native_targets.each do |test_native_target|
test_native_target.build_configuration_list.build_configurations.each do |build_configuration|
build_configuration.build_settings['SWIFT_VERSION'] = swift_version
end end
end end
end end
end
targets.each do |target|
if target.pod_targets.any?(&:uses_swift?) && consumer.platform_name == :ios && if target.pod_targets.any?(&:uses_swift?) && consumer.platform_name == :ios &&
(deployment_target.nil? || Version.new(deployment_target).major < 8) (deployment_target.nil? || Version.new(deployment_target).major < 8)
uses_xctest = target.spec_consumers.any? { |c| (c.frameworks + c.weak_frameworks).include? 'XCTest' } uses_xctest = target.spec_consumers.any? { |c| (c.frameworks + c.weak_frameworks).include? 'XCTest' }
error('swift', 'Swift support uses dynamic frameworks and is therefore only supported on iOS > 8.') unless uses_xctest error('swift', 'Swift support uses dynamic frameworks and is therefore only supported on iOS > 8.') unless uses_xctest
end end
end end
# Wire up Swift version to pod targets used only by tests.
test_only_pod_targets.each do |test_pod_target|
update_pod_target_build_settings(test_pod_target)
end
end
def update_pod_target_build_settings(pod_target)
native_target = pod_target.native_target
unless native_target.nil?
native_target.build_configuration_list.build_configurations.each do |build_configuration|
(build_configuration.build_settings['OTHER_CFLAGS'] ||= '$(inherited)') << ' -Wincomplete-umbrella'
build_configuration.build_settings['SWIFT_VERSION'] = (pod_target.swift_version || swift_version) if pod_target.uses_swift?
end
end
end end
def validate_vendored_dynamic_frameworks def validate_vendored_dynamic_frameworks
...@@ -597,7 +587,7 @@ module Pod ...@@ -597,7 +587,7 @@ module Pod
UI.message "\nTesting with `xcodebuild`.\n".yellow do UI.message "\nTesting with `xcodebuild`.\n".yellow do
pod_target = @installer.pod_targets.find { |pt| pt.pod_name == spec.root.name } pod_target = @installer.pod_targets.find { |pt| pt.pod_name == spec.root.name }
consumer.spec.test_specs.each do |test_spec| consumer.spec.test_specs.each do |test_spec|
scheme = pod_target.native_target_for_spec(test_spec) scheme = @installer.target_installation_results.first[pod_target.name].native_target_for_spec(test_spec)
output = xcodebuild('test', scheme, 'Debug') output = xcodebuild('test', scheme, 'Debug')
parsed_output = parse_xcodebuild_output(output) parsed_output = parse_xcodebuild_output(output)
translate_output_to_linter_messages(parsed_output) translate_output_to_linter_messages(parsed_output)
......
Subproject commit 2ede36e05798057b7d21e6bd953497c52fad71bb Subproject commit 55202559c1b06409113d2a19b15fb065c3742115
...@@ -146,9 +146,10 @@ def fixture_pod_target_with_specs(specs, host_requires_frameworks = false, user_ ...@@ -146,9 +146,10 @@ def fixture_pod_target_with_specs(specs, host_requires_frameworks = false, user_
target_definitions, file_accessors, scope_suffix) target_definitions, file_accessors, scope_suffix)
end end
def fixture_aggregate_target(pod_targets = [], platform = Pod::Platform.new(:ios, '6.0'), target_definition = nil) def fixture_aggregate_target(pod_targets = [], host_requires_frameworks = false, user_build_configurations = {},
archs = [], platform = Pod::Platform.new(:ios, '6.0'), target_definition = nil)
target_definition ||= pod_targets.flat_map(&:target_definitions).first || fixture_target_definition target_definition ||= pod_targets.flat_map(&:target_definitions).first || fixture_target_definition
Pod::AggregateTarget.new(config.sandbox, false, {}, [], platform, Pod::AggregateTarget.new(config.sandbox, host_requires_frameworks, user_build_configurations, archs, platform,
target_definition, config.sandbox.root.dirname, nil, nil, pod_targets) target_definition, config.sandbox.root.dirname, nil, nil, pod_targets)
end end
......
...@@ -18,7 +18,7 @@ module Pod ...@@ -18,7 +18,7 @@ module Pod
@specs.first.user_target_xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' } unless @specs.empty? @specs.first.user_target_xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' } unless @specs.empty?
@specs.first.pod_target_xcconfig = { 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11' } unless @specs.empty? @specs.first.pod_target_xcconfig = { 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11' } unless @specs.empty?
@pod_targets = @specs.map { |spec| pod_target(spec, @target_definition) } @pod_targets = @specs.map { |spec| pod_target(spec, @target_definition) }
@target = fixture_aggregate_target(@pod_targets, Platform.new(:ios, '6.0'), @target_definition) @target = fixture_aggregate_target(@pod_targets, false, {}, [], Platform.new(:ios, '6.0'), @target_definition)
unless @specs.empty? unless @specs.empty?
@target.target_definition.whitelist_pod_for_configuration(@specs.first.name, 'Release') @target.target_definition.whitelist_pod_for_configuration(@specs.first.name, 'Release')
end end
......
...@@ -607,7 +607,7 @@ module Pod ...@@ -607,7 +607,7 @@ module Pod
describe 'for proper other ld flags' do describe 'for proper other ld flags' do
def stub_aggregate_target(pod_targets, target_definition = nil, search_paths_aggregate_targets: []) def stub_aggregate_target(pod_targets, target_definition = nil, search_paths_aggregate_targets: [])
target_definition.stubs(:abstract? => false) unless target_definition.respond_to?(:abstract?) target_definition.stubs(:abstract? => false) unless target_definition.respond_to?(:abstract?)
fixture_aggregate_target(pod_targets, Platform.ios, target_definition).tap do |aggregate_target| fixture_aggregate_target(pod_targets, false, {}, [], Platform.ios, target_definition).tap do |aggregate_target|
aggregate_target.search_paths_aggregate_targets.concat(search_paths_aggregate_targets).freeze aggregate_target.search_paths_aggregate_targets.concat(search_paths_aggregate_targets).freeze
end end
end end
......
...@@ -88,29 +88,25 @@ module Pod ...@@ -88,29 +88,25 @@ module Pod
end end
it 'does not enable the GCC_WARN_INHIBIT_ALL_WARNINGS flag by default' do it 'does not enable the GCC_WARN_INHIBIT_ALL_WARNINGS flag by default' do
@installer.install! @installer.install!.native_target.build_configurations.each do |config|
@installer.target.native_target.build_configurations.each do |config|
config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'].should.be.nil config.build_settings['GCC_WARN_INHIBIT_ALL_WARNINGS'].should.be.nil
end end
end end
it 'will be built as static library' do it 'will be built as static library' do
@installer.install! @installer.install!.native_target.build_configurations.each do |config|
@installer.target.native_target.build_configurations.each do |config|
config.build_settings['MACH_O_TYPE'].should == 'staticlib' config.build_settings['MACH_O_TYPE'].should == 'staticlib'
end end
end end
it 'will be skipped when installing' do it 'will be skipped when installing' do
@installer.install! @installer.install!.native_target.build_configurations.each do |config|
@installer.target.native_target.build_configurations.each do |config|
config.build_settings['SKIP_INSTALL'].should == 'YES' config.build_settings['SKIP_INSTALL'].should == 'YES'
end end
end end
it 'has a PRODUCT_BUNDLE_IDENTIFIER set' do it 'has a PRODUCT_BUNDLE_IDENTIFIER set' do
@installer.install! @installer.install!.native_target.build_configurations.each do |config|
@installer.target.native_target.build_configurations.each do |config|
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}' config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}'
end end
end end
...@@ -219,8 +215,7 @@ module Pod ...@@ -219,8 +215,7 @@ module Pod
end end
it 'creates a dummy source to ensure the creation of a single base library' do it 'creates a dummy source to ensure the creation of a single base library' do
@installer.install! build_files = @installer.install!.native_target.source_build_phase.files
build_files = @installer.target.native_target.source_build_phase.files
build_file = build_files.find { |bf| bf.file_ref.path.include?('Pods-SampleProject-dummy.m') } build_file = build_files.find { |bf| bf.file_ref.path.include?('Pods-SampleProject-dummy.m') }
build_file.should.be.not.nil build_file.should.be.not.nil
build_file.file_ref.path.should == 'Pods-SampleProject-dummy.m' build_file.file_ref.path.should == 'Pods-SampleProject-dummy.m'
...@@ -251,9 +246,7 @@ module Pod ...@@ -251,9 +246,7 @@ module Pod
it 'installs umbrella headers for swift static libraries' do it 'installs umbrella headers for swift static libraries' do
@pod_target.stubs(:uses_swift? => true) @pod_target.stubs(:uses_swift? => true)
@target.stubs(:uses_swift? => true) @target.stubs(:uses_swift? => true)
@installer.install! build_files = @installer.install!.native_target.headers_build_phase.files
build_files = @installer.target.native_target.headers_build_phase.files
build_file = build_files.find { |bf| bf.file_ref.path.include?('Pods-SampleProject-umbrella.h') } build_file = build_files.find { |bf| bf.file_ref.path.include?('Pods-SampleProject-umbrella.h') }
build_file.should.not.be.nil build_file.should.not.be.nil
build_file.settings.should == { 'ATTRIBUTES' => ['Project'] } build_file.settings.should == { 'ATTRIBUTES' => ['Project'] }
...@@ -262,9 +255,7 @@ module Pod ...@@ -262,9 +255,7 @@ module Pod
it 'installs umbrella headers for frameworks' do it 'installs umbrella headers for frameworks' do
@pod_target.stubs(:requires_frameworks? => true) @pod_target.stubs(:requires_frameworks? => true)
@target.stubs(:requires_frameworks? => true) @target.stubs(:requires_frameworks? => true)
@installer.install! build_files = @installer.install!.native_target.headers_build_phase.files
build_files = @installer.target.native_target.headers_build_phase.files
build_file = build_files.find { |bf| bf.file_ref.path.include?('Pods-SampleProject-umbrella.h') } build_file = build_files.find { |bf| bf.file_ref.path.include?('Pods-SampleProject-umbrella.h') }
build_file.should.not.be.nil build_file.should.not.be.nil
build_file.settings.should == { 'ATTRIBUTES' => ['Public'] } build_file.settings.should == { 'ATTRIBUTES' => ['Public'] }
......
...@@ -14,13 +14,12 @@ module Pod ...@@ -14,13 +14,12 @@ module Pod
@coconut_pod_target = PodTarget.new(config.sandbox, false, {}, [], Platform.ios, [@coconut_spec, *@coconut_spec.recursive_subspecs], [@target_definition]) @coconut_pod_target = PodTarget.new(config.sandbox, false, {}, [], Platform.ios, [@coconut_spec, *@coconut_spec.recursive_subspecs], [@target_definition])
@native_target = stub('NativeTarget', :shell_script_build_phases => [], :build_phases => [], :project => @project) @native_target = stub('NativeTarget', :shell_script_build_phases => [], :build_phases => [], :project => @project)
@test_native_target = stub('TestNativeTarget', :symbol_type => :unit_test_bundle, :build_phases => [], :shell_script_build_phases => [], :project => @project) @test_native_target = stub('TestNativeTarget', :symbol_type => :unit_test_bundle, :build_phases => [], :shell_script_build_phases => [], :project => @project)
@coconut_pod_target.stubs(:native_target).returns(@native_target) @target_installation_result = TargetInstallationResult.new(@coconut_pod_target, @native_target, [], [@test_native_target])
@coconut_pod_target.stubs(:test_native_targets).returns([@test_native_target])
end end
describe '#integrate!' do describe '#integrate!' do
it 'integrates test native targets with frameworks and resources script phases' do it 'integrates test native targets with frameworks and resources script phases' do
PodTargetIntegrator.new(@coconut_pod_target).integrate! PodTargetIntegrator.new(@target_installation_result).integrate!
@test_native_target.build_phases.count.should == 2 @test_native_target.build_phases.count.should == 2
@test_native_target.build_phases.map(&:display_name).should == [ @test_native_target.build_phases.map(&:display_name).should == [
'[CP] Embed Pods Frameworks', '[CP] Embed Pods Frameworks',
...@@ -36,7 +35,7 @@ module Pod ...@@ -36,7 +35,7 @@ module Pod
"${PODS_CONFIGURATION_BUILD_DIR}/DebugLib/DebugLibPng#{i}.png" "${PODS_CONFIGURATION_BUILD_DIR}/DebugLib/DebugLibPng#{i}.png"
end end
@coconut_pod_target.stubs(:resource_paths).returns(resource_paths) @coconut_pod_target.stubs(:resource_paths).returns(resource_paths)
PodTargetIntegrator.new(@coconut_pod_target).integrate! PodTargetIntegrator.new(@target_installation_result).integrate!
@test_native_target.build_phases.map(&:display_name).should == [ @test_native_target.build_phases.map(&:display_name).should == [
'[CP] Embed Pods Frameworks', '[CP] Embed Pods Frameworks',
'[CP] Copy Pods Resources', '[CP] Copy Pods Resources',
...@@ -50,7 +49,7 @@ module Pod ...@@ -50,7 +49,7 @@ module Pod
resource_paths = ['${PODS_CONFIGURATION_BUILD_DIR}/TestResourceBundle.bundle'] resource_paths = ['${PODS_CONFIGURATION_BUILD_DIR}/TestResourceBundle.bundle']
@coconut_pod_target.stubs(:framework_paths).returns(framework_paths) @coconut_pod_target.stubs(:framework_paths).returns(framework_paths)
@coconut_pod_target.stubs(:resource_paths).returns(resource_paths) @coconut_pod_target.stubs(:resource_paths).returns(resource_paths)
PodTargetIntegrator.new(@coconut_pod_target).integrate! PodTargetIntegrator.new(@target_installation_result).integrate!
@test_native_target.build_phases.count.should == 2 @test_native_target.build_phases.count.should == 2
@test_native_target.build_phases.map(&:display_name).should == [ @test_native_target.build_phases.map(&:display_name).should == [
'[CP] Embed Pods Frameworks', '[CP] Embed Pods Frameworks',
...@@ -74,7 +73,7 @@ module Pod ...@@ -74,7 +73,7 @@ module Pod
it 'integrates test native target with shell script phases' do it 'integrates test native target with shell script phases' do
@coconut_spec.test_specs.first.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"' } @coconut_spec.test_specs.first.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"' }
PodTargetIntegrator.new(@coconut_pod_target).integrate! PodTargetIntegrator.new(@target_installation_result).integrate!
@test_native_target.build_phases.count.should == 3 @test_native_target.build_phases.count.should == 3
@test_native_target.build_phases[2].display_name.should == '[CP-User] Hello World' @test_native_target.build_phases[2].display_name.should == '[CP-User] Hello World'
@test_native_target.build_phases[2].shell_script.should == 'echo "Hello World"' @test_native_target.build_phases[2].shell_script.should == 'echo "Hello World"'
...@@ -82,7 +81,7 @@ module Pod ...@@ -82,7 +81,7 @@ module Pod
it 'integrates native target with shell script phases' do it 'integrates native target with shell script phases' do
@coconut_spec.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"' } @coconut_spec.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"' }
PodTargetIntegrator.new(@coconut_pod_target).integrate! PodTargetIntegrator.new(@target_installation_result).integrate!
@native_target.build_phases.count.should == 1 @native_target.build_phases.count.should == 1
@native_target.build_phases[0].display_name.should == '[CP-User] Hello World' @native_target.build_phases[0].display_name.should == '[CP-User] Hello World'
@native_target.build_phases[0].shell_script.should == 'echo "Hello World"' @native_target.build_phases[0].shell_script.should == 'echo "Hello World"'
......
...@@ -15,8 +15,7 @@ module Pod ...@@ -15,8 +15,7 @@ module Pod
end end
it 'adds the architectures to the custom build configurations of the user target' do it 'adds the architectures to the custom build configurations of the user target' do
@installer.send(:add_target) @installer.send(:add_target).resolved_build_setting('ARCHS').should == {
@installer.send(:native_target).resolved_build_setting('ARCHS').should == {
'Release' => ['$(ARCHS_STANDARD_64_BIT)'], 'Release' => ['$(ARCHS_STANDARD_64_BIT)'],
'Debug' => ['$(ARCHS_STANDARD_64_BIT)'], 'Debug' => ['$(ARCHS_STANDARD_64_BIT)'],
'AppStore' => ['$(ARCHS_STANDARD_64_BIT)'], 'AppStore' => ['$(ARCHS_STANDARD_64_BIT)'],
...@@ -25,16 +24,15 @@ module Pod ...@@ -25,16 +24,15 @@ module Pod
end end
it 'always clears the OTHER_LDFLAGS and OTHER_LIBTOOLFLAGS, because these lib targets do not ever need any' do it 'always clears the OTHER_LDFLAGS and OTHER_LIBTOOLFLAGS, because these lib targets do not ever need any' do
@installer.send(:add_target) native_target = @installer.send(:add_target)
@installer.send(:native_target).resolved_build_setting('OTHER_LDFLAGS').values.uniq.should == [''] native_target.resolved_build_setting('OTHER_LDFLAGS').values.uniq.should == ['']
@installer.send(:native_target).resolved_build_setting('OTHER_LIBTOOLFLAGS').values.uniq.should == [''] native_target.resolved_build_setting('OTHER_LIBTOOLFLAGS').values.uniq.should == ['']
end end
it 'adds Swift-specific build settings to the build settings' do it 'adds Swift-specific build settings to the build settings' do
@target.stubs(:requires_frameworks?).returns(true) @target.stubs(:requires_frameworks?).returns(true)
@target.stubs(:uses_swift?).returns(true) @target.stubs(:uses_swift?).returns(true)
@installer.send(:add_target) @installer.send(:add_target).resolved_build_setting('SWIFT_OPTIMIZATION_LEVEL').should == {
@installer.send(:native_target).resolved_build_setting('SWIFT_OPTIMIZATION_LEVEL').should == {
'Release' => '-Owholemodule', 'Release' => '-Owholemodule',
'Debug' => '-Onone', 'Debug' => '-Onone',
'Test' => nil, 'Test' => nil,
...@@ -45,8 +43,7 @@ module Pod ...@@ -45,8 +43,7 @@ module Pod
it 'verify static framework is building a static library' do it 'verify static framework is building a static library' do
@target.stubs(:requires_frameworks?).returns(true) @target.stubs(:requires_frameworks?).returns(true)
@target.stubs(:static_framework?).returns(true) @target.stubs(:static_framework?).returns(true)
@installer.send(:add_target) @installer.send(:add_target).resolved_build_setting('MACH_O_TYPE').should == {
@installer.send(:native_target).resolved_build_setting('MACH_O_TYPE').should == {
'Release' => 'staticlib', 'Release' => 'staticlib',
'Debug' => 'staticlib', 'Debug' => 'staticlib',
'Test' => 'staticlib', 'Test' => 'staticlib',
......
...@@ -535,17 +535,6 @@ module Pod ...@@ -535,17 +535,6 @@ module Pod
@test_pod_target.app_host_label(:unit).should == 'AppHost-iOS-Unit-Tests' @test_pod_target.app_host_label(:unit).should == 'AppHost-iOS-Unit-Tests'
end end
it 'returns the correct native target based on the consumer provided' do
@test_pod_target.stubs(:native_target).returns(stub(:name => 'CoconutLib', :symbol_type => :dynamic_library, :product_reference => stub(:name => 'libCoconutLib.a')))
@test_pod_target.stubs(:test_native_targets).returns([stub(:name => 'CoconutLib-Unit-Tests', :symbol_type => :unit_test_bundle, :product_reference => stub(:name => 'CoconutLib-Unit-Tests'))])
native_target = @test_pod_target.native_target_for_spec(@coconut_spec)
native_target.name.should == 'CoconutLib'
native_target.product_reference.name.should == 'libCoconutLib.a'
test_native_target = @test_pod_target.native_target_for_spec(@coconut_spec.test_specs.first)
test_native_target.name.should == 'CoconutLib-Unit-Tests'
test_native_target.product_reference.name.should == 'CoconutLib-Unit-Tests'
end
it 'returns the correct product type for test type' do it 'returns the correct product type for test type' do
@test_pod_target.product_type_for_test_type(:unit).should == :unit_test_bundle @test_pod_target.product_type_for_test_type(:unit).should == :unit_test_bundle
end end
......
...@@ -1079,12 +1079,15 @@ module Pod ...@@ -1079,12 +1079,15 @@ module Pod
debug_configuration_two = stub(:build_settings => {}) debug_configuration_two = stub(:build_settings => {})
native_target_one = stub(:build_configuration_list => stub(:build_configurations => [debug_configuration_one])) native_target_one = stub(:build_configuration_list => stub(:build_configurations => [debug_configuration_one]))
native_target_two = stub(:build_configuration_list => stub(:build_configurations => [debug_configuration_two])) native_target_two = stub(:build_configuration_list => stub(:build_configurations => [debug_configuration_two]))
pod_target_one = stub(:uses_swift? => true, :swift_version => '4.0', :native_target => native_target_one, :test_native_targets => []) pod_target_one = stub(:name => 'PodTarget1', :uses_swift? => true, :swift_version => '4.0')
pod_target_two = stub(:uses_swift? => true, :swift_version => '3.2', :native_target => native_target_two, :test_native_targets => []) pod_target_two = stub(:name => 'PodTarget2', :uses_swift? => true, :swift_version => '3.2')
pod_target_installation_one = stub(:target => pod_target_one, :native_target => native_target_one, :test_native_targets => [])
pod_target_installation_two = stub(:target => pod_target_two, :native_target => native_target_two, :test_native_targets => [])
pod_target_installation_results = { 'PodTarget1' => pod_target_installation_one, 'PodTarget2' => pod_target_installation_two }
aggregate_target = stub(:pod_targets => [pod_target_one, pod_target_two]) aggregate_target = stub(:pod_targets => [pod_target_one, pod_target_two])
installer = stub(:pod_targets => [pod_target_one, pod_target_two]) installer = stub(:pod_targets => [pod_target_one, pod_target_two])
validator.instance_variable_set(:@installer, installer) validator.instance_variable_set(:@installer, installer)
validator.send(:configure_pod_targets, [aggregate_target], '9.0') validator.send(:configure_pod_targets, [aggregate_target], [pod_target_installation_results], '9.0')
debug_configuration_one.build_settings['SWIFT_VERSION'].should == '4.0' debug_configuration_one.build_settings['SWIFT_VERSION'].should == '4.0'
debug_configuration_two.build_settings['SWIFT_VERSION'].should == '3.2' debug_configuration_two.build_settings['SWIFT_VERSION'].should == '3.2'
end end
...@@ -1097,12 +1100,15 @@ module Pod ...@@ -1097,12 +1100,15 @@ module Pod
debug_configuration_two = stub(:build_settings => {}) debug_configuration_two = stub(:build_settings => {})
native_target_one = stub(:build_configuration_list => stub(:build_configurations => [debug_configuration_one])) native_target_one = stub(:build_configuration_list => stub(:build_configurations => [debug_configuration_one]))
native_target_two = stub(:build_configuration_list => stub(:build_configurations => [debug_configuration_two])) native_target_two = stub(:build_configuration_list => stub(:build_configurations => [debug_configuration_two]))
pod_target_one = stub(:uses_swift? => true, :swift_version => '4.0', :native_target => native_target_one, :test_native_targets => []) pod_target_one = stub(:name => 'PodTarget1', :uses_swift? => true, :swift_version => '4.0')
pod_target_two = stub(:uses_swift? => true, :swift_version => '3.2', :native_target => native_target_two, :test_native_targets => []) pod_target_two = stub(:name => 'PodTarget2', :uses_swift? => true, :swift_version => '3.2')
pod_target_installation_one = stub(:target => pod_target_one, :native_target => native_target_one, :test_native_targets => [])
pod_target_installation_two = stub(:target => pod_target_two, :native_target => native_target_two, :test_native_targets => [])
pod_target_installation_results = { 'PodTarget1' => pod_target_installation_one, 'PodTarget2' => pod_target_installation_two }
aggregate_target = stub(:pod_targets => [pod_target_one]) aggregate_target = stub(:pod_targets => [pod_target_one])
installer = stub(:pod_targets => [pod_target_one, pod_target_two]) installer = stub(:pod_targets => [pod_target_one, pod_target_two])
validator.instance_variable_set(:@installer, installer) validator.instance_variable_set(:@installer, installer)
validator.send(:configure_pod_targets, [aggregate_target], '9.0') validator.send(:configure_pod_targets, [aggregate_target], [pod_target_installation_results], '9.0')
debug_configuration_one.build_settings['SWIFT_VERSION'].should == '4.0' debug_configuration_one.build_settings['SWIFT_VERSION'].should == '4.0'
debug_configuration_two.build_settings['SWIFT_VERSION'].should == '3.2' debug_configuration_two.build_settings['SWIFT_VERSION'].should == '3.2'
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