diff --git a/CHANGELOG.md b/CHANGELOG.md index 55454a29bb..51db567831 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,11 @@ To install release candidates run `[sudo] gem install cocoapods --pre` [Dimitris Koutsogiorgas](https://github.com/dnkoutso) [#9230](https://github.com/CocoaPods/CocoaPods/pull/9230) +* Configure dependencies per configuration. + [Samuel Giddins](https://github.com/segiddins) + [Dimitris Koutsogiorgas](https://github.com/dnkoutso) + [#9149](https://github.com/CocoaPods/CocoaPods/pull/9149) + * Include Podfile Plugin changes for incremental installation. [Sebastian Shanus](https://github.com/sebastianv1) [#9147](https://github.com/CocoaPods/CocoaPods/pull/9147) diff --git a/examples/multiple test specs Example/ByConfig/ByConfig.podspec b/examples/multiple test specs Example/ByConfig/ByConfig.podspec new file mode 100644 index 0000000000..1f328c8de8 --- /dev/null +++ b/examples/multiple test specs Example/ByConfig/ByConfig.podspec @@ -0,0 +1,21 @@ +Pod::Spec.new do |s| + s.name = 'ByConfig' + s.version = '0.1.0' + s.summary = 'A short description of ByConfig.' + s.ios.deployment_target = '10.0' + s.author = { 'Jeff Overwatch' => 'jeff@overwatch.com' } + s.homepage = "https://github.com/" + s.license = 'MIT' + s.source = { :git => "https://github.com//ByConfig.git", :tag => s.version.to_s } + + s.source_files = 'ByConfig/Classes/**/*' + + s.swift_version = '4' + + s.app_spec 'App' do |app_spec| + app_spec.source_files = 'ByConfig/App/**/*' + + app_spec.dependency 'TestLib', configurations: %w[Debug] + app_spec.dependency 'HostedTestLib' + end +end diff --git a/examples/multiple test specs Example/ByConfig/ByConfig/.gitignore b/examples/multiple test specs Example/ByConfig/ByConfig/.gitignore new file mode 100644 index 0000000000..93c86d3b19 --- /dev/null +++ b/examples/multiple test specs Example/ByConfig/ByConfig/.gitignore @@ -0,0 +1,37 @@ +# OS X +.DS_Store + +# Xcode +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ +*.xccheckout +profile +*.moved-aside +DerivedData +*.hmap +*.ipa + +# Bundler +.bundle + +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control +# +# Note: if you ignore the Pods directory, make sure to uncomment +# `pod install` in .travis.yml +# +# Pods/ diff --git a/examples/multiple test specs Example/ByConfig/ByConfig/App/AppDelegate.swift b/examples/multiple test specs Example/ByConfig/ByConfig/App/AppDelegate.swift new file mode 100644 index 0000000000..8f864a3196 --- /dev/null +++ b/examples/multiple test specs Example/ByConfig/ByConfig/App/AppDelegate.swift @@ -0,0 +1,31 @@ +import UIKit +import ByConfig +import HostedTestLib + +#if DEBUG +import TestLib +#endif + +class ViewController: UIViewController { + override func viewDidLoad() { + view.backgroundColor = .purple + } +} + +@UIApplicationMain +class AppDelegate: NSObject, UIApplicationDelegate { + var window: UIWindow? + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + #if DEBUG + _ = TestLib() + #endif + _ = ByConfig() + _ = HostedTestLib() + window = UIWindow(frame: UIScreen.main.bounds) + window?.rootViewController = UINavigationController(rootViewController: ViewController()) + window?.makeKeyAndVisible() + + return true + } +} diff --git a/examples/multiple test specs Example/ByConfig/ByConfig/Classes/main.swift b/examples/multiple test specs Example/ByConfig/ByConfig/Classes/main.swift new file mode 100644 index 0000000000..5c19fbd2d5 --- /dev/null +++ b/examples/multiple test specs Example/ByConfig/ByConfig/Classes/main.swift @@ -0,0 +1,4 @@ +import Foundation + +public class ByConfig { +} diff --git a/examples/multiple test specs Example/InstallMultipleTestSpecs.xcodeproj/project.pbxproj b/examples/multiple test specs Example/InstallMultipleTestSpecs.xcodeproj/project.pbxproj index 3e1561e40a..928019f408 100644 --- a/examples/multiple test specs Example/InstallMultipleTestSpecs.xcodeproj/project.pbxproj +++ b/examples/multiple test specs Example/InstallMultipleTestSpecs.xcodeproj/project.pbxproj @@ -183,11 +183,13 @@ ); inputPaths = ( "${PODS_ROOT}/Target Support Files/Pods-InstallMultipleTestSpecs/Pods-InstallMultipleTestSpecs-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/ByConfig/ByConfig.framework", "${BUILT_PRODUCTS_DIR}/HostedTestLib/HostedTestLib.framework", "${BUILT_PRODUCTS_DIR}/TestLib/TestLib.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ByConfig.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HostedTestLib.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/TestLib.framework", ); diff --git a/examples/multiple test specs Example/Podfile b/examples/multiple test specs Example/Podfile index 3d7b6cfd42..a80641102e 100644 --- a/examples/multiple test specs Example/Podfile +++ b/examples/multiple test specs Example/Podfile @@ -14,4 +14,5 @@ target 'InstallMultipleTestSpecs' do # Pods for InstallMultipleTestSpecs pod 'TestLib', :path => 'TestLib', :testspecs => %w[UnitTests1 UnitTests2] pod 'HostedTestLib', :path => 'HostedTestLib', :testspecs => %w[UnitTests3 UnitTests4] + pod 'ByConfig', path: 'ByConfig', appspecs: %w[App] end diff --git a/lib/cocoapods/installer/analyzer.rb b/lib/cocoapods/installer/analyzer.rb index cc4f151f9d..e97d8a722b 100644 --- a/lib/cocoapods/installer/analyzer.rb +++ b/lib/cocoapods/installer/analyzer.rb @@ -415,11 +415,11 @@ def analyze_host_targets_in_podfile(aggregate_targets, embedded_aggregate_target # Creates the models that represent the targets generated by CocoaPods. # - # @param [Hash{Podfile::TargetDefinition => Array}] resolver_specs_by_target + # @param [Hash{TargetDefinition => Array}] resolver_specs_by_target # mapping of targets to resolved specs (containing information about test usage) # aggregate targets # - # @param [Array] target_inspections + # @param [Hash{TargetDefinition => TargetInspectionResult}] target_inspections # the user target inspections used to construct the aggregate and pod targets. # # @return [(Array, Array)] the list of aggregate targets generated, @@ -481,7 +481,7 @@ def generate_targets(resolver_specs_by_target, target_inspections) # @param [Hash{TargetDefinition => TargetInspectionResult}] target_inspections # the user target inspections used to construct the aggregate and pod targets. # - # @param [Hash{Podfile::TargetDefinition => Array}] pod_targets_by_target_definition + # @param [Hash{TargetDefinition => Array}] pod_targets_by_target_definition # the pod targets grouped by target. # # @return [AggregateTarget] @@ -541,16 +541,17 @@ def group_pod_targets_by_target_definition(pod_targets, resolver_specs_by_target # @param [TargetDefinition] target_definition # the target definition to use as the base for filtering # - # @param [Hash{Podfile::TargetDefinition => Array}] pod_targets_by_target_definition + # @param [Hash{TargetDefinition => Array}] pod_targets_by_target_definition # the pod targets grouped by target. # # @param [Array] build_configurations # The list of all build configurations the targets will be built for. # - # @return [Hash Array>] + # @return [Hash{String => Array}] # the filtered list of pod targets, grouped by build configuration. # - def filter_pod_targets_for_target_definition(target_definition, pod_targets_by_target_definition, build_configurations) + def filter_pod_targets_for_target_definition(target_definition, pod_targets_by_target_definition, + build_configurations) pod_targets_by_build_config = Hash.new([].freeze) build_configurations.each { |config| pod_targets_by_build_config[config] = [] } @@ -587,7 +588,7 @@ def filter_pod_targets_for_target_definition(target_definition, pod_targets_by_t # targets by grouping by platform and subspec by their root # to create a {PodTarget} for each spec. # - # @param [Hash{Podfile::TargetDefinition => Array}] resolver_specs_by_target + # @param [Hash{TargetDefinition => Array}] resolver_specs_by_target # the resolved specifications grouped by target. # # @param [Hash{TargetDefinition => TargetInspectionResult}] target_inspections @@ -671,23 +672,26 @@ def compute_pod_target_dependencies(pod_targets, all_specs) end pod_targets.each do |target| - dependencies = dependencies_for_specs(target.library_specs.to_set, target.platform, all_specs).group_by(&:root) - target.dependent_targets = filter_dependencies(dependencies, pod_targets_by_name, target) - target.test_dependent_targets_by_spec_name = target.test_specs.each_with_object({}) do |test_spec, hash| - test_dependencies = dependencies_for_specs([test_spec], target.platform, all_specs).group_by(&:root) - test_dependencies.delete_if { |k, _| dependencies.key? k } - hash[test_spec.name] = filter_dependencies(test_dependencies, pod_targets_by_name, target) + dependencies_by_config = dependencies_for_specs(target.library_specs, target.platform, all_specs) + target.dependent_targets_by_config = Hash[dependencies_by_config.map { |k, v| [k, filter_dependencies(v, pod_targets_by_name, target)] }] + + target.test_dependent_targets_by_spec_name_by_config = target.test_specs.each_with_object({}) do |test_spec, hash| + test_dependencies_by_config = dependencies_for_specs([test_spec], target.platform, all_specs) + test_dependencies_by_config.each { |config, deps| deps.delete_if { |k, _| dependencies_by_config[config].key? k } } + hash[test_spec.name] = Hash[test_dependencies_by_config.map { |k, v| [k, filter_dependencies(v, pod_targets_by_name, target)] }] end - target.app_dependent_targets_by_spec_name = target.app_specs.each_with_object({}) do |app_spec, hash| - app_dependencies = dependencies_for_specs([app_spec], target.platform, all_specs).group_by(&:root) - app_dependencies.delete_if { |k, _| dependencies.key? k } - hash[app_spec.name] = filter_dependencies(app_dependencies, pod_targets_by_name, target) + target.app_dependent_targets_by_spec_name_by_config = target.app_specs.each_with_object({}) do |app_spec, hash| + app_dependencies_by_config = dependencies_for_specs([app_spec], target.platform, all_specs) + app_dependencies_by_config.each { |config, deps| deps.delete_if { |k, _| dependencies_by_config[config].key? k } } + hash[app_spec.name] = Hash[app_dependencies_by_config.map { |k, v| [k, filter_dependencies(v, pod_targets_by_name, target)] }] end target.test_app_hosts_by_spec_name = target.test_specs.each_with_object({}) do |test_spec, hash| next unless app_host_name = test_spec.consumer(target.platform).app_host_name - app_host_spec = pod_targets_by_name[Specification.root_name(app_host_name)].flat_map(&:app_specs).find { |pt| pt.name == app_host_name } + app_host_spec = pod_targets_by_name[Specification.root_name(app_host_name)].flat_map(&:app_specs).find do |pt| + pt.name == app_host_name + end app_host_dependencies = { app_host_spec.root => [app_host_spec] } hash[test_spec.name] = [app_host_spec, filter_dependencies(app_host_dependencies, pod_targets_by_name, target).first] end @@ -716,32 +720,39 @@ def filter_dependencies(dependencies, pod_targets_by_name, target) # @param [Platform] platform # The platform for which the dependencies should be returned. # - # @param [Hash] all_specs + # @param [Hash{String => Array}] all_specs # All specifications which are installed alongside. # - # @return [Array] + # @return [Hash{Symbol => Set}] # def dependencies_for_specs(specs, platform, all_specs) - return [] if specs.empty? || all_specs.empty? - - dependent_specs = Set.new + dependent_specs = { + :debug => Set.new, + :release => Set.new, + } + + if !specs.empty? && !all_specs.empty? + specs.each do |s| + s.dependencies(platform).each do |dep| + all_specs[dep.name].each do |spec| + if spec.non_library_specification? + if s.test_specification? && spec.name == s.consumer(platform).app_host_name && spec.app_specification? + # This needs to be handled separately, since we _don't_ want to treat this as a "normal" dependency + next + end + raise Informative, "`#{s}` depends upon `#{spec}`, which is a `#{spec.spec_type}` spec." + end - specs.each do |s| - s.dependencies(platform).each do |dep| - all_specs[dep.name].each do |spec| - if spec.non_library_specification? - if s.test_specification? && spec.name == s.consumer(platform).app_host_name && spec.app_specification? - # This needs to be handled separately, since we _don't_ want to treat this as a "normal" dependency - next + dependent_specs.each do |config, set| + next unless s.dependency_whitelisted_for_configuration?(dep, config) + set << spec end - raise Informative, "#{s} depends upon `#{spec}`, which is a `#{spec.spec_type}` spec." end - dependent_specs << spec end end end - dependent_specs - specs + Hash[dependent_specs.map { |k, v| [k, (v - specs).group_by(&:root)] }].freeze end # Create a target for each spec group @@ -779,7 +790,9 @@ def generate_pod_target(target_definitions, build_type, target_inspections, spec target_inspections.flat_map(&:archs).compact.uniq.sort end else - user_build_configurations = Target::DEFAULT_BUILD_CONFIGURATIONS + user_build_configurations = Target::DEFAULT_BUILD_CONFIGURATIONS.merge( + target_definitions.map { |td| td.build_configurations || {} }.reduce({}, &:merge), + ) archs = target_requires_64_bit ? ['$(ARCHS_STANDARD_64_BIT)'] : [] end platform = determine_platform(specs, target_definitions, build_type) diff --git a/lib/cocoapods/installer/project_cache/target_cache_key.rb b/lib/cocoapods/installer/project_cache/target_cache_key.rb index f73e770b63..2a853618d0 100644 --- a/lib/cocoapods/installer/project_cache/target_cache_key.rb +++ b/lib/cocoapods/installer/project_cache/target_cache_key.rb @@ -116,12 +116,14 @@ def self.from_cache_hash(sandbox, key_hash) # def self.from_pod_target(sandbox, pod_target, is_local_pod: false, checkout_options: nil) build_settings = {} - build_settings[pod_target.label.to_s] = Digest::MD5.hexdigest(pod_target.build_settings.xcconfig.to_s) - pod_target.test_spec_build_settings.each do |name, settings| - build_settings[name] = Digest::MD5.hexdigest(settings.xcconfig.to_s) + build_settings[pod_target.label.to_s] = Hash[pod_target.build_settings.map do |k, v| + [k, Digest::MD5.hexdigest(v.xcconfig.to_s)] + end] + pod_target.test_spec_build_settings_by_config.each do |name, settings_by_config| + build_settings[name] = Hash[settings_by_config.map { |k, v| [k, Digest::MD5.hexdigest(v.xcconfig.to_s)] }] end - pod_target.app_spec_build_settings.each do |name, settings| - build_settings[name] = Digest::MD5.hexdigest(settings.xcconfig.to_s) + pod_target.app_spec_build_settings_by_config.each do |name, settings_by_config| + build_settings[name] = Hash[settings_by_config.map { |k, v| [k, Digest::MD5.hexdigest(v.xcconfig.to_s)] }] end contents = { diff --git a/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb b/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb index 0f3ac9dc9c..43f1a42a68 100644 --- a/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb +++ b/lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb @@ -148,14 +148,18 @@ def add_target # Removes overrides of the `pod_target_xcconfig` settings from the target's # build configurations. # - # @return [Void] - # - # @param [Target::BuildSettings] build_settings + # @param [Hash{Symbol => Pod::Target::BuildSettings}] build_settings_by_config the build settings by config + # of the target. # # @param [PBXNativeTarget] native_target + # the native target to remove pod target xcconfig overrides from. + # + # @return [Void] + # # - def remove_pod_target_xcconfig_overrides_from_target(build_settings, native_target) + def remove_pod_target_xcconfig_overrides_from_target(build_settings_by_config, native_target) native_target.build_configurations.each do |configuration| + build_settings = build_settings_by_config[target.user_build_configurations[configuration.name]] build_settings.merged_pod_target_xcconfigs.each_key do |setting| configuration.build_settings.delete(setting) end @@ -365,7 +369,7 @@ def add_test_targets configuration.build_settings['CODE_SIGN_IDENTITY'] = '' if target.platform == :osx end - remove_pod_target_xcconfig_overrides_from_target(target.build_settings_for_spec(test_spec), test_native_target) + remove_pod_target_xcconfig_overrides_from_target(target.test_spec_build_settings_by_config[test_spec.name], test_native_target) # Test native targets also need frameworks and resources to be copied over to their xctest bundle. create_test_target_embed_frameworks_script(test_spec) @@ -454,7 +458,7 @@ def add_app_targets end end - remove_pod_target_xcconfig_overrides_from_target(target.build_settings_for_spec(app_spec), app_native_target) + remove_pod_target_xcconfig_overrides_from_target(target.app_spec_build_settings_by_config[app_spec.name], app_native_target) create_app_target_embed_frameworks_script(app_spec) create_app_target_copy_resources_script(app_spec) @@ -489,7 +493,7 @@ def add_resources_to_target(paths, target) # @param [Array] file_accessors # the file accessors list to generate resource bundles for. # - # @return [Array] the resource bundle native targets created. + # @return [Hash{String=>Array}] the resource bundle native targets created. # def add_resources_bundle_targets(file_accessors) file_accessors.each_with_object({}) do |file_accessor, hash| @@ -548,7 +552,7 @@ def add_resources_bundle_targets(file_accessors) end end - remove_pod_target_xcconfig_overrides_from_target(target.build_settings_for_spec(file_accessor.spec), resource_bundle_target) + remove_pod_target_xcconfig_overrides_from_target(target.build_settings_by_config_for_spec(file_accessor.spec), resource_bundle_target) resource_bundle_target end @@ -566,12 +570,14 @@ def add_resources_bundle_targets(file_accessors) # @return [void] # def create_xcconfig_file(native_target, resource_bundle_targets) - path = target.xcconfig_path - update_changed_file(target.build_settings, path) - xcconfig_file_ref = add_file_to_support_group(path) + target.user_config_names_by_config_type.each do |config, names| + path = target.xcconfig_path(config) + update_changed_file(target.build_settings[config], path) + xcconfig_file_ref = add_file_to_support_group(path) - # also apply the private config to resource bundle targets. - apply_xcconfig_file_ref_to_targets([native_target] + resource_bundle_targets, xcconfig_file_ref) + # also apply the private config to resource bundle targets. + apply_xcconfig_file_ref_to_targets([native_target] + resource_bundle_targets, xcconfig_file_ref, names) + end end # Generates the contents of the xcconfig file used for each test target type and saves it to disk. @@ -588,19 +594,22 @@ def create_test_xcconfig_files(test_native_targets, test_resource_bundle_targets target.test_specs.each do |test_spec| spec_consumer = test_spec.consumer(target.platform) test_type = spec_consumer.test_type - path = target.xcconfig_path("#{test_type.capitalize}-#{target.subspec_label(test_spec)}") - test_spec_build_settings = target.build_settings_for_spec(test_spec) - update_changed_file(test_spec_build_settings, path) - test_xcconfig_file_ref = add_file_to_support_group(path) - test_native_target = test_native_target_from_spec(spec_consumer.spec, test_native_targets) + + target.user_config_names_by_config_type.each do |config, names| + path = target.xcconfig_path("#{test_type.capitalize}-#{target.subspec_label(test_spec)}.#{config}") + test_spec_build_settings = target.build_settings_for_spec(test_spec, :configuration => config) + update_changed_file(test_spec_build_settings, path) + test_xcconfig_file_ref = add_file_to_support_group(path) + + # also apply the private config to resource bundle test targets related to this test spec. + scoped_test_resource_bundle_targets = test_resource_bundle_targets[test_spec.name] + apply_xcconfig_file_ref_to_targets([test_native_target] + scoped_test_resource_bundle_targets, test_xcconfig_file_ref, names) + end + test_native_target.build_configurations.each do |test_native_target_bc| test_target_swift_debug_hack(test_spec, test_native_target_bc) end - - # also apply the private config to resource bundle test targets related to this test spec. - scoped_test_resource_bundle_targets = test_resource_bundle_targets[test_spec.name] - apply_xcconfig_file_ref_to_targets([test_native_target] + scoped_test_resource_bundle_targets, test_xcconfig_file_ref) end end @@ -613,12 +622,11 @@ def create_test_xcconfig_files(test_native_targets, test_resource_bundle_targets # def create_test_target_copy_resources_script(test_spec) path = target.copy_resources_script_path_for_spec(test_spec) - pod_targets = target.dependent_targets_for_test_spec(test_spec) host_target_spec_names = target.app_host_dependent_targets_for_spec(test_spec).flat_map do |pt| pt.specs.map(&:name) end.uniq - resource_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, resources_by_config| - resources_by_config[config] = pod_targets.flat_map do |pod_target| + resource_paths_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), resources_by_config| + resources_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target| spec_paths_to_include = pod_target.library_specs.map(&:name) spec_paths_to_include -= host_target_spec_names spec_paths_to_include << test_spec.name if pod_target == target @@ -641,12 +649,11 @@ def create_test_target_copy_resources_script(test_spec) # def create_test_target_embed_frameworks_script(test_spec) path = target.embed_frameworks_script_path_for_spec(test_spec) - pod_targets = target.dependent_targets_for_test_spec(test_spec) host_target_spec_names = target.app_host_dependent_targets_for_spec(test_spec).flat_map do |pt| pt.specs.map(&:name) end.uniq - framework_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, paths_by_config| - paths_by_config[config] = pod_targets.flat_map do |pod_target| + framework_paths_by_config = target.user_build_configurations.each_with_object({}) do |(config_name, config), paths_by_config| + paths_by_config[config_name] = target.dependent_targets_for_test_spec(test_spec, :configuration => config).flat_map do |pod_target| spec_paths_to_include = pod_target.library_specs.map(&:name) spec_paths_to_include -= host_target_spec_names spec_paths_to_include << test_spec.name if pod_target == target @@ -673,15 +680,18 @@ def create_test_target_embed_frameworks_script(test_spec) def create_app_xcconfig_files(app_native_targets, app_resource_bundle_targets) target.app_specs.each do |app_spec| spec_consumer = app_spec.consumer(target.platform) - path = target.xcconfig_path(target.subspec_label(app_spec)) - update_changed_file(target.build_settings_for_spec(app_spec), path) - app_xcconfig_file_ref = add_file_to_support_group(path) - app_native_target = app_native_target_from_spec(spec_consumer.spec, app_native_targets) - # also apply the private config to resource bundle app targets related to this app spec. - scoped_app_resource_bundle_targets = app_resource_bundle_targets[app_spec.name] - apply_xcconfig_file_ref_to_targets([app_native_target] + scoped_app_resource_bundle_targets, app_xcconfig_file_ref) + target.user_config_names_by_config_type.each do |config, names| + path = target.xcconfig_path("#{target.subspec_label(app_spec)}.#{config}") + app_spec_build_settings = target.build_settings_for_spec(app_spec, :configuration => config) + update_changed_file(app_spec_build_settings, path) + app_xcconfig_file_ref = add_file_to_support_group(path) + + # also apply the private config to resource bundle app targets related to this app spec. + scoped_app_resource_bundle_targets = app_resource_bundle_targets[app_spec.name] + apply_xcconfig_file_ref_to_targets([app_native_target] + scoped_app_resource_bundle_targets, app_xcconfig_file_ref, names) + end end end @@ -694,8 +704,8 @@ def create_app_xcconfig_files(app_native_targets, app_resource_bundle_targets) # def create_app_target_copy_resources_script(app_spec) path = target.copy_resources_script_path_for_spec(app_spec) - pod_targets = target.dependent_targets_for_app_spec(app_spec) resource_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, resources_by_config| + pod_targets = target.dependent_targets_for_app_spec(app_spec, :configuration => config) resources_by_config[config] = pod_targets.flat_map do |pod_target| spec_paths_to_include = pod_target.library_specs.map(&:name) spec_paths_to_include << app_spec.name if pod_target == target @@ -718,8 +728,8 @@ def create_app_target_copy_resources_script(app_spec) # def create_app_target_embed_frameworks_script(app_spec) path = target.embed_frameworks_script_path_for_spec(app_spec) - pod_targets = target.dependent_targets_for_app_spec(app_spec) framework_paths_by_config = target.user_build_configurations.keys.each_with_object({}) do |config, paths_by_config| + pod_targets = target.dependent_targets_for_app_spec(app_spec, :configuration => config) paths_by_config[config] = pod_targets.flat_map do |pod_target| spec_paths_to_include = pod_target.library_specs.map(&:name) spec_paths_to_include << app_spec.name if pod_target == target @@ -841,9 +851,10 @@ def compiler_flags_for_consumer(consumer, arc, language) flags * ' ' end - def apply_xcconfig_file_ref_to_targets(targets, xcconfig_file_ref) + def apply_xcconfig_file_ref_to_targets(targets, xcconfig_file_ref, configurations) targets.each do |config_target| config_target.build_configurations.each do |configuration| + next unless configurations.include?(configuration.name) configuration.base_configuration_reference = xcconfig_file_ref end end diff --git a/lib/cocoapods/target.rb b/lib/cocoapods/target.rb index 2b3b389c2a..dc6482b48b 100644 --- a/lib/cocoapods/target.rb +++ b/lib/cocoapods/target.rb @@ -202,7 +202,7 @@ def product_type # @return [String] A string suitable for debugging. # def inspect - "<#{self.class} name=#{name} >" + "#<#{self.class} name=#{name}>" end #-------------------------------------------------------------------------# @@ -237,7 +237,7 @@ def support_files_dir # def xcconfig_path(variant = nil) if variant - support_files_dir + "#{label}.#{variant.gsub(File::SEPARATOR, '-').downcase}.xcconfig" + support_files_dir + "#{label}.#{variant.to_s.gsub(File::SEPARATOR, '-').downcase}.xcconfig" else support_files_dir + "#{label}.xcconfig" end diff --git a/lib/cocoapods/target/aggregate_target.rb b/lib/cocoapods/target/aggregate_target.rb index 40cf9b8760..8ce67c50a6 100644 --- a/lib/cocoapods/target/aggregate_target.rb +++ b/lib/cocoapods/target/aggregate_target.rb @@ -429,8 +429,8 @@ def relative_to_pods_root(path) def create_build_settings settings = {} - user_build_configurations.each_key do |configuration_name| - settings[configuration_name] = BuildSettings::AggregateTargetSettings.new(self, configuration_name) + user_build_configurations.each do |configuration_name, configuration| + settings[configuration_name] = BuildSettings::AggregateTargetSettings.new(self, configuration_name, :configuration => configuration) end settings diff --git a/lib/cocoapods/target/build_settings.rb b/lib/cocoapods/target/build_settings.rb index 0e09423dd9..b4116ffb32 100644 --- a/lib/cocoapods/target/build_settings.rb +++ b/lib/cocoapods/target/build_settings.rb @@ -119,7 +119,7 @@ def self.define_build_settings_method(method_name, build_setting: false, retval = retval.dup if dup_before_freeze && retval.frozen? - retval.concat(pod_targets_to_link.flat_map { |pod_target| pod_target.build_settings.public_send("#{method_name}_to_import") }) if from_pod_targets_to_link + retval.concat(pod_targets_to_link.flat_map { |pod_target| pod_target.build_settings_for_spec(pod_target.root_spec, :configuration => configuration_name).public_send("#{method_name}_to_import") }) if from_pod_targets_to_link retval.concat(search_paths_aggregate_target_pod_target_build_settings.flat_map(&from_search_paths_aggregate_targets)) if from_search_paths_aggregate_targets retval.compact! if compacted @@ -515,7 +515,10 @@ def non_library_xcconfig? # @param [Specification] non_library_spec # see {#non_library_spec} # - def initialize(target, non_library_spec = nil) + # @param [Symbol] configuration + # see {#configuration} + # + def initialize(target, non_library_spec = nil, configuration: nil) super(target) if @non_library_spec = non_library_spec @test_xcconfig = non_library_spec.test_specification? @@ -527,6 +530,7 @@ def initialize(target, non_library_spec = nil) @xcconfig_spec_type = :library @library_xcconfig = true end + (@configuration = configuration) || raise("No configuration for #{self}.") end # @return [Xcodeproj::Xconfig] @@ -569,9 +573,9 @@ def initialize(target, non_library_spec = nil) # on the guard above, so include any vendored static frameworks. frameworks.concat vendored_static_frameworks.map { |l| File.basename(l, '.framework') } if target.should_build? # Also include any vendored dynamic frameworks of dependencies. - frameworks.concat dependent_targets.reject(&:should_build?).flat_map { |pt| pt.build_settings.dynamic_frameworks_to_import } + frameworks.concat dependent_targets.reject(&:should_build?).flat_map { |pt| pt.build_settings[@configuration].dynamic_frameworks_to_import } else - frameworks.concat dependent_targets_to_link.flat_map { |pt| pt.build_settings.frameworks_to_import } + frameworks.concat dependent_targets_to_link.flat_map { |pt| pt.build_settings[@configuration].frameworks_to_import } end frameworks @@ -598,7 +602,7 @@ def initialize(target, non_library_spec = nil) return [] if target.build_as_static? && library_xcconfig? weak_frameworks = spec_consumers.flat_map(&:weak_frameworks) - weak_frameworks.concat dependent_targets.flat_map { |pt| pt.build_settings.weak_frameworks_to_import } + weak_frameworks.concat dependent_targets.flat_map { |pt| pt.build_settings[@configuration].weak_frameworks_to_import } weak_frameworks end @@ -615,7 +619,7 @@ def initialize(target, non_library_spec = nil) # @return [Array] define_build_settings_method :framework_search_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true do paths = super().dup - paths.concat dependent_targets.flat_map { |t| t.build_settings.framework_search_paths_to_import } + paths.concat dependent_targets.flat_map { |pt| pt.build_settings[@configuration].framework_search_paths_to_import } paths.concat framework_search_paths_to_import paths.delete(target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)) if library_xcconfig? paths @@ -676,8 +680,8 @@ def linker_names_from_libraries(libraries) libraries.concat libraries_to_import end if non_library_xcconfig? - libraries.concat dependent_targets.flat_map { |pt| pt.build_settings.dynamic_libraries_to_import } - libraries.concat dependent_targets_to_link.flat_map { |pt| pt.build_settings.static_libraries_to_import } + libraries.concat dependent_targets.flat_map { |pt| pt.build_settings[@configuration].dynamic_libraries_to_import } + libraries.concat dependent_targets_to_link.flat_map { |pt| pt.build_settings[@configuration].static_libraries_to_import } end libraries end @@ -708,11 +712,11 @@ def linker_names_from_libraries(libraries) return [] if library_xcconfig? && target.build_as_static? vendored = library_search_paths_to_import.dup - vendored.concat dependent_targets.flat_map { |t| t.build_settings.vendored_dynamic_library_search_paths } + vendored.concat dependent_targets.flat_map { |pt| pt.build_settings[@configuration].vendored_dynamic_library_search_paths } if library_xcconfig? vendored.delete(target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)) else - vendored.concat(dependent_targets.flat_map { |t| t.build_settings.library_search_paths_to_import }) + vendored.concat(dependent_targets.flat_map { |pt| pt.build_settings[@configuration].library_search_paths_to_import }) end vendored end @@ -751,7 +755,7 @@ def linker_names_from_libraries(libraries) # @return [Array] define_build_settings_method :module_map_files, :memoized => true do - dependent_targets.map { |t| t.build_settings.module_map_file_to_import }.compact.sort + dependent_targets.map { |pt| pt.build_settings[@configuration].module_map_file_to_import }.compact.sort end # @return [Array] @@ -770,12 +774,12 @@ def linker_names_from_libraries(libraries) # @return [Array] define_build_settings_method :header_search_paths, :build_setting => true, :memoized => true, :sorted => true do - target.header_search_paths(:include_dependent_targets_for_test_spec => test_xcconfig? && non_library_spec, :include_dependent_targets_for_app_spec => app_xcconfig? && non_library_spec) + target.header_search_paths(:include_dependent_targets_for_test_spec => test_xcconfig? && non_library_spec, :include_dependent_targets_for_app_spec => app_xcconfig? && non_library_spec, :configuration => @configuration) end # @return [Array] define_build_settings_method :public_header_search_paths, :memoized => true, :sorted => true do - target.header_search_paths(:include_dependent_targets_for_test_spec => test_xcconfig? && non_library_spec, :include_dependent_targets_for_app_spec => app_xcconfig? && non_library_spec, :include_private_headers => false) + target.header_search_paths(:include_dependent_targets_for_test_spec => test_xcconfig? && non_library_spec, :include_dependent_targets_for_app_spec => app_xcconfig? && non_library_spec, :include_private_headers => false, :configuration => @configuration) end #-------------------------------------------------------------------------# @@ -803,7 +807,7 @@ def other_swift_flags_without_swift? # @return [Array] define_build_settings_method :swift_include_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true do - paths = dependent_targets.flat_map { |t| t.build_settings.swift_include_paths_to_import } + paths = dependent_targets.flat_map { |pt| pt.build_settings[@configuration].swift_include_paths_to_import } paths.concat swift_include_paths_to_import if non_library_xcconfig? paths end @@ -873,11 +877,11 @@ def requires_objc_linker_flag? define_build_settings_method :dependent_targets, :memoized => true do select_maximal_pod_targets( if test_xcconfig? - target.dependent_targets_for_test_spec(non_library_spec) + target.dependent_targets_for_test_spec(non_library_spec, :configuration => @configuration) elsif app_xcconfig? - target.dependent_targets_for_app_spec(non_library_spec) + target.dependent_targets_for_app_spec(non_library_spec, :configuration => @configuration) else - target.recursive_dependent_targets + target.recursive_dependent_targets(:configuration => @configuration) end, ) end @@ -886,7 +890,7 @@ def requires_objc_linker_flag? define_build_settings_method :dependent_targets_to_link, :memoized => true do if test_xcconfig? # we're embedding into an app defined by an app spec - host_targets = target.app_host_dependent_targets_for_spec(non_library_spec) + host_targets = target.app_host_dependent_targets_for_spec(non_library_spec, :configuration => @configuration) dependent_targets - host_targets else dependent_targets @@ -913,7 +917,7 @@ def pod_target_xcconfig_values_by_consumer_by_key # define_build_settings_method :merged_pod_target_xcconfigs, :memoized => true do merged_xcconfigs(pod_target_xcconfig_values_by_consumer_by_key, :pod_target_xcconfig, - :overriding => non_library_xcconfig? ? target.build_settings.merged_pod_target_xcconfigs : {}) + :overriding => non_library_xcconfig? ? target.build_settings[@configuration].merged_pod_target_xcconfigs : {}) end # @return [Array] @@ -948,21 +952,22 @@ def self.build_settings_names @build_settings_names | BuildSettings.build_settings_names end - # @return [String] + # @return [Symbol] # The build configuration these settings will be used for attr_reader :configuration_name - # Intializes a new instance + # Initializes a new instance # # @param [AggregateTarget] target # see {#target} # - # @param [String] configuration_name + # @param [Symbol] configuration_name # see {#configuration_name} # - def initialize(target, configuration_name) + def initialize(target, configuration_name, configuration: nil) super(target) @configuration_name = configuration_name + (@configuration = configuration) || raise("No configuration for #{self}.") end # @return [Xcodeproj::Config] xcconfig @@ -1034,7 +1039,7 @@ def initialize(target, configuration_name) # brackets, @import, etc.) paths.concat pod_targets. select { |pt| pt.build_as_framework? && pt.should_build? }. - map { |pt| pt.build_settings.framework_header_search_path } + map { |pt| pt.build_settings[@configuration].framework_header_search_path } paths.concat target.search_paths_aggregate_targets.flat_map { |at| at.build_settings(configuration_name).header_search_paths } @@ -1051,11 +1056,11 @@ def initialize(target, configuration_name) silenced_frameworks = [] pod_targets_inhibiting_warnings.each do |pt| if pt.build_as_framework? && pt.should_build? - silenced_headers.append pt.build_settings.framework_header_search_path + silenced_headers.append pt.build_settings[@configuration].framework_header_search_path else - silenced_headers.concat pt.build_settings.public_header_search_paths + silenced_headers.concat pt.build_settings[@configuration].public_header_search_paths end - silenced_frameworks.concat pt.build_settings.framework_search_paths_to_import + silenced_frameworks.concat pt.build_settings[@configuration].framework_search_paths_to_import end flags += silenced_headers.uniq.flat_map { |p| ['-isystem', p] } @@ -1066,7 +1071,7 @@ def initialize(target, configuration_name) # @return [Array] define_build_settings_method :module_map_files, :memoized => true, :sorted => true, :uniqued => true, :compacted => true, :from_search_paths_aggregate_targets => :module_map_file_to_import do - pod_targets.map { |t| t.build_settings.module_map_file_to_import } + pod_targets.map { |pt| pt.build_settings[@configuration].module_map_file_to_import } end #-------------------------------------------------------------------------# @@ -1180,7 +1185,7 @@ def other_swift_flags_without_swift? define_build_settings_method :search_paths_aggregate_target_pod_target_build_settings, :memoized => true, :uniqued => true do pod_targets = target.search_paths_aggregate_targets.flat_map { |at| at.build_settings(configuration_name).pod_targets } pod_targets = select_maximal_pod_targets(pod_targets) - pod_targets.flat_map(&:build_settings) + pod_targets.map { |pt| pt.build_settings[@configuration] } end # Returns the +user_target_xcconfig+ for all pod targets and their spec diff --git a/lib/cocoapods/target/pod_target.rb b/lib/cocoapods/target/pod_target.rb index c06c64f22b..42053803b7 100644 --- a/lib/cocoapods/target/pod_target.rb +++ b/lib/cocoapods/target/pod_target.rb @@ -48,15 +48,59 @@ class PodTarget < Target # @return [Array] the targets that this target has a dependency # upon. # - attr_accessor :dependent_targets + attr_reader :dependent_targets + attr_reader :dependent_targets_by_config + + # @deprecated + def dependent_targets=(dependent_targets) + @dependent_targets = dependent_targets + @dependent_targets_by_config = { :debug => dependent_targets, :release => dependent_targets } + end + + def dependent_targets_by_config=(dependent_targets_by_config) + @dependent_targets_by_config = dependent_targets_by_config + @dependent_targets = dependent_targets_by_config.each_value.reduce([], &:|) + end # @return [Hash{String=>Array}] all target dependencies by test spec name. # - attr_accessor :test_dependent_targets_by_spec_name + attr_reader :test_dependent_targets_by_spec_name + attr_reader :test_dependent_targets_by_spec_name_by_config + + # @deprecated + def test_dependent_targets_by_spec_name=(test_dependent_targets_by_spec_name) + @test_dependent_targets_by_spec_name = test_dependent_targets_by_spec_name + @test_dependent_targets_by_spec_name_by_config = Hash[test_dependent_targets_by_spec_name.map do |k, v| + [k, { :debug => v, :release => v }] + end] + end + + def test_dependent_targets_by_spec_name_by_config=(test_dependent_targets_by_spec_name_by_config) + @test_dependent_targets_by_spec_name_by_config = test_dependent_targets_by_spec_name_by_config + @test_dependent_targets_by_spec_name = Hash[test_dependent_targets_by_spec_name_by_config.map do |k, v| + [k, v.each_value.reduce(Set.new, &:|).to_a] + end] + end # @return [Hash{String=>Array}] all target dependencies by app spec name. # - attr_accessor :app_dependent_targets_by_spec_name + attr_reader :app_dependent_targets_by_spec_name + attr_reader :app_dependent_targets_by_spec_name_by_config + + # @deprecated + def app_dependent_targets_by_spec_name=(app_dependent_targets_by_spec_name) + @app_dependent_targets_by_spec_name = app_dependent_targets_by_spec_name + @app_dependent_targets_by_spec_name_by_config = Hash[app_dependent_targets_by_spec_name.map do |k, v| + [k, { :debug => v, :release => v }] + end] + end + + def app_dependent_targets_by_spec_name_by_config=(app_dependent_targets_by_spec_name_by_config) + @app_dependent_targets_by_spec_name_by_config = app_dependent_targets_by_spec_name_by_config + @app_dependent_targets_by_spec_name = Hash[app_dependent_targets_by_spec_name_by_config.map do |k, v| + [k, v.each_value.reduce(Set.new, &:|).to_a] + end] + end # @return [Hash{String => (Specification,PodTarget)}] tuples of app specs and pod targets by test spec name. # @@ -65,10 +109,12 @@ class PodTarget < Target # @return [Hash{String => BuildSettings}] the test spec build settings for this target. # attr_reader :test_spec_build_settings + attr_reader :test_spec_build_settings_by_config # @return [Hash{String => BuildSettings}] the app spec build settings for this target. # attr_reader :app_spec_build_settings + attr_reader :app_spec_build_settings_by_config # @return [String] the Swift version for this target. # @@ -103,13 +149,13 @@ def initialize(sandbox, build_type, user_build_configurations, archs, platform, @test_specs = all_specs_by_type[:test] || [] @app_specs = all_specs_by_type[:app] || [] @build_headers = Sandbox::HeadersStore.new(sandbox, 'Private', :private) - @dependent_targets = [] - @test_dependent_targets_by_spec_name = {} - @app_dependent_targets_by_spec_name = {} + self.dependent_targets = [] + self.test_dependent_targets_by_spec_name = Hash[test_specs.map { |ts| [ts.name, []] }] + self.app_dependent_targets_by_spec_name = Hash[app_specs.map { |as| [as.name, []] }] @test_app_hosts_by_spec_name = {} @build_config_cache = {} - @test_spec_build_settings = create_test_build_settings - @app_spec_build_settings = create_app_build_settings + @test_spec_build_settings_by_config = create_test_build_settings_by_config + @app_spec_build_settings_by_config = create_app_build_settings_by_config end # Scopes the current target based on the existing pod targets within the cache. @@ -131,12 +177,12 @@ def scoped(cache = {}) end end - target.dependent_targets = scope_dependent_targets[dependent_targets] - target.test_dependent_targets_by_spec_name = Hash[test_dependent_targets_by_spec_name.map do |spec_name, test_pod_targets| - [spec_name, scope_dependent_targets[test_pod_targets]] + target.dependent_targets_by_config = Hash[dependent_targets_by_config.map { |k, v| [k, scope_dependent_targets[v]] }] + target.test_dependent_targets_by_spec_name_by_config = Hash[test_dependent_targets_by_spec_name_by_config.map do |spec_name, test_pod_targets_by_config| + [spec_name, Hash[test_pod_targets_by_config.map { |k, v| [k, scope_dependent_targets[v]] }]] end] - target.app_dependent_targets_by_spec_name = Hash[app_dependent_targets_by_spec_name.map do |spec_name, app_pod_targets| - [spec_name, scope_dependent_targets[app_pod_targets]] + target.app_dependent_targets_by_spec_name_by_config = Hash[app_dependent_targets_by_spec_name_by_config.map do |spec_name, app_pod_targets_by_config| + [spec_name, Hash[app_pod_targets_by_config.map { |k, v| [k, scope_dependent_targets[v]] }]] end] target.test_app_hosts_by_spec_name = Hash[test_app_hosts_by_spec_name.map do |spec_name, (app_host_spec, app_pod_target)| [spec_name, [app_host_spec, app_pod_target.scoped(cache).find { |pt| pt.target_definitions == [target_definition] }]] @@ -533,16 +579,19 @@ def app_host_target_label(test_spec) # @param [Specification] spec # the spec to return app host dependencies for # + # @param [String] configuration + # the configuration to retrieve the app host dependent targets for. + # # @return [Array] the app host dependent targets for the given spec. # - def app_host_dependent_targets_for_spec(spec) + def app_host_dependent_targets_for_spec(spec, configuration: nil) return [] unless spec.test_specification? && spec.consumer(platform).test_type == :unit app_host_info = test_app_hosts_by_spec_name[spec.name] if app_host_info.nil? [] else app_spec, app_target = *app_host_info - app_target.dependent_targets_for_app_spec(app_spec) + app_target.dependent_targets_for_app_spec(app_spec, :configuration => configuration) end end @@ -647,16 +696,32 @@ def dependencies end.uniq end - # @return [Array] the recursive targets that this target has a - # dependency upon. + # Returns all dependent targets of this target. If a configuration is passed then the list can be scoped to a given + # configuration. + # + # @param [String] configuration + # The configuration to return the dependent targets for or `nil` if all configurations should be included. # - def recursive_dependent_targets - @recursive_dependent_targets ||= _add_recursive_dependent_targets(Set.new).delete(self).to_a + # @return [Array] the recursive targets that this target has a dependency upon. + # + def recursive_dependent_targets(configuration: nil) + @recursive_dependent_targets ||= begin + hash = Hash[config_variants.map do |config| + [config, _add_recursive_dependent_targets(Set.new, :configuration => config).delete(self).to_a.freeze] + end] + hash[nil] = hash.each_value.reduce(Set.new, &:|).to_a + hash + end + @recursive_dependent_targets[configuration] end - def _add_recursive_dependent_targets(set) + def _add_recursive_dependent_targets(set, configuration: nil) + if defined?(@recursive_dependent_targets) + return set.merge(@recursive_dependent_targets[configuration]) + end + dependent_targets = configuration ? dependent_targets_by_config[configuration] : self.dependent_targets dependent_targets.each do |target| - target._add_recursive_dependent_targets(set) if set.add?(target) + target._add_recursive_dependent_targets(set, :configuration => configuration) if set.add?(target) end set @@ -666,20 +731,31 @@ def _add_recursive_dependent_targets(set) # @param [Specification] test_spec # the test spec to scope dependencies for # + # @param [String] configuration + # the configuration to retrieve the test dependent targets for. + # # @return [Array] the recursive targets that this target has a # test dependency upon. # - def recursive_test_dependent_targets(test_spec) + def recursive_test_dependent_targets(test_spec, configuration: nil) @recursive_test_dependent_targets ||= {} - @recursive_test_dependent_targets[test_spec] ||= _add_recursive_test_dependent_targets(test_spec, Set.new).to_a + @recursive_test_dependent_targets[test_spec] ||= begin + hash = Hash[config_variants.map do |config| + [config, _add_recursive_test_dependent_targets(test_spec, Set.new, :configuration => config).to_a.freeze] + end] + hash[nil] = hash.each_value.reduce(Set.new, &:|).to_a.freeze + hash + end + @recursive_test_dependent_targets[test_spec][configuration] end - def _add_recursive_test_dependent_targets(test_spec, set) + def _add_recursive_test_dependent_targets(test_spec, set, configuration: nil) raise ArgumentError, 'Must give a test spec' unless test_spec - return unless dependent_targets = test_dependent_targets_by_spec_name[test_spec.name] + dependent_targets = configuration ? test_dependent_targets_by_spec_name_by_config[test_spec.name][configuration] : test_dependent_targets_by_spec_name[test_spec.name] + raise ArgumentError, "Unable to find deps for #{test_spec} for config #{configuration.inspect} (out of #{test_dependent_targets_by_spec_name_by_config.inspect})" unless dependent_targets dependent_targets.each do |target| - target._add_recursive_dependent_targets(set) if set.add?(target) + target._add_recursive_dependent_targets(set, :configuration => configuration) if set.add?(target) end set @@ -689,30 +765,44 @@ def _add_recursive_test_dependent_targets(test_spec, set) # @param [Specification] test_spec # the test spec to scope dependencies for # + # @param [String] configuration + # the configuration to retrieve the test dependent targets for. + # # @return [Array] the canonical list of dependent targets this target has a dependency upon. # This list includes the target itself as well as its recursive dependent and test dependent targets. # - def dependent_targets_for_test_spec(test_spec) - [self, *recursive_dependent_targets, *recursive_test_dependent_targets(test_spec)].uniq + def dependent_targets_for_test_spec(test_spec, configuration: nil) + [self, *recursive_dependent_targets(:configuration => configuration), *recursive_test_dependent_targets(test_spec, :configuration => configuration)].uniq end # @param [Specification] app_spec # the app spec to scope dependencies for # + # @param [String] configuration + # the configuration to retrieve the app dependent targets for. + # # @return [Array] the recursive targets that this target has a # app dependency upon. # - def recursive_app_dependent_targets(app_spec) + def recursive_app_dependent_targets(app_spec, configuration: nil) @recursive_app_dependent_targets ||= {} - @recursive_app_dependent_targets[app_spec] ||= _add_recursive_app_dependent_targets(app_spec, Set.new).to_a + @recursive_app_dependent_targets[app_spec] ||= begin + hash = Hash[config_variants.map do |config| + [config, _add_recursive_app_dependent_targets(app_spec, Set.new, :configuration => config).to_a.freeze] + end] + hash[nil] = hash.each_value.reduce(Set.new, &:|).to_a.freeze + hash + end + @recursive_app_dependent_targets[app_spec][configuration] end - def _add_recursive_app_dependent_targets(app_spec, set) + def _add_recursive_app_dependent_targets(app_spec, set, configuration: nil) raise ArgumentError, 'Must give a app spec' unless app_spec - return unless dependent_targets = app_dependent_targets_by_spec_name[app_spec.name] + dependent_targets = configuration ? app_dependent_targets_by_spec_name_by_config[app_spec.name][configuration] : app_dependent_targets_by_spec_name[app_spec.name] + raise ArgumentError, "Unable to find deps for #{app_spec} for config #{configuration.inspect} #{app_dependent_targets_by_spec_name_by_config.inspect}" unless dependent_targets dependent_targets.each do |target| - target._add_recursive_dependent_targets(set) if set.add?(target) + target._add_recursive_dependent_targets(set, :configuration => configuration) if set.add?(target) end set @@ -722,11 +812,14 @@ def _add_recursive_app_dependent_targets(app_spec, set) # @param [Specification] app_spec # the app spec to scope dependencies for # + # @param [String] configuration + # the configuration to retrieve the app dependent targets for. + # # @return [Array] the canonical list of dependent targets this target has a dependency upon. # This list includes the target itself as well as its recursive dependent and app dependent targets. # - def dependent_targets_for_app_spec(app_spec) - [self, *recursive_dependent_targets, *recursive_app_dependent_targets(app_spec)].uniq + def dependent_targets_for_app_spec(app_spec, configuration: nil) + [self, *recursive_dependent_targets(:configuration => configuration), *recursive_app_dependent_targets(app_spec, :configuration => configuration)].uniq end # Checks if warnings should be inhibited for this pod. @@ -798,33 +891,56 @@ def version # whether to include header search paths for private headers of this # target # + # @param [String] configuration + # the configuration to return header search paths for or `nil` for all configurations. + # # @return [Array] The set of header search paths this target uses. # - def header_search_paths(include_dependent_targets_for_test_spec: nil, include_dependent_targets_for_app_spec: nil, include_private_headers: true) + def header_search_paths(include_dependent_targets_for_test_spec: nil, include_dependent_targets_for_app_spec: nil, + include_private_headers: true, configuration: nil) header_search_paths = [] header_search_paths.concat(build_headers.search_paths(platform, nil, false)) if include_private_headers header_search_paths.concat(sandbox.public_headers.search_paths(platform, pod_name, uses_modular_headers?)) - dependent_targets = recursive_dependent_targets - dependent_targets += recursive_test_dependent_targets(include_dependent_targets_for_test_spec) if include_dependent_targets_for_test_spec - dependent_targets += recursive_app_dependent_targets(include_dependent_targets_for_app_spec) if include_dependent_targets_for_app_spec + dependent_targets = recursive_dependent_targets(:configuration => configuration) + if include_dependent_targets_for_test_spec + dependent_targets += recursive_test_dependent_targets(include_dependent_targets_for_test_spec, :configuration => configuration) + end + if include_dependent_targets_for_app_spec + dependent_targets += recursive_app_dependent_targets(include_dependent_targets_for_app_spec, :configuration => configuration) + end dependent_targets.uniq.each do |dependent_target| header_search_paths.concat(sandbox.public_headers.search_paths(platform, dependent_target.pod_name, defines_module? && dependent_target.uses_modular_headers?(false))) end header_search_paths.uniq end - # @param [Specification] spec + # @param [Specification] spec the specification to return build settings for. + # + # @param [String] configuration the configuration to scope the build settings. # # @return [BuildSettings::PodTargetSettings] The build settings for the given spec # - def build_settings_for_spec(spec) + def build_settings_for_spec(spec, configuration: nil) + raise ArgumentError, 'Must give configuration' unless configuration + configuration = user_build_configurations[configuration] if user_build_configurations.key?(configuration) + build_settings_by_config_for_spec(spec)[configuration] || raise(ArgumentError, "No build settings for #{spec} (configuration #{configuration.inspect}) (known configurations #{config_variants})") + end + + def build_settings_by_config_for_spec(spec) case spec.spec_type - when :test then test_spec_build_settings[spec.name] - when :app then app_spec_build_settings[spec.name] + when :test then test_spec_build_settings_by_config[spec.name] + when :app then app_spec_build_settings_by_config[spec.name] else build_settings end || raise(ArgumentError, "No build settings for #{spec}") end + def user_config_names_by_config_type + user_build_configurations.each_with_object({}) do |(user, type), hash| + hash[type] ||= [] + hash[type] << user + end.each_value(&:freeze).freeze + end + protected # Returns whether the pod target should use modular headers. @@ -844,19 +960,33 @@ def uses_modular_headers?(only_if_defines_modules = true) private + def config_variants + if user_build_configurations.empty? + %i(debug release) + else + user_build_configurations.values.uniq + end + end + def create_build_settings - BuildSettings::PodTargetSettings.new(self) + Hash[config_variants.map do |config| + [config, BuildSettings::PodTargetSettings.new(self, nil, :configuration => config)] + end] end - def create_test_build_settings + def create_test_build_settings_by_config Hash[test_specs.map do |test_spec| - [test_spec.name, BuildSettings::PodTargetSettings.new(self, test_spec)] + [test_spec.name, Hash[config_variants.map do |config| + [config, BuildSettings::PodTargetSettings.new(self, test_spec, :configuration => config)] + end]] end] end - def create_app_build_settings + def create_app_build_settings_by_config Hash[app_specs.map do |app_spec| - [app_spec.name, BuildSettings::PodTargetSettings.new(self, app_spec)] + [app_spec.name, Hash[config_variants.map do |config| + [config, BuildSettings::PodTargetSettings.new(self, app_spec, :configuration => config)] + end]] end] end diff --git a/spec/cocoapods-integration-specs b/spec/cocoapods-integration-specs index 9c7b64076a..38495a81dc 160000 --- a/spec/cocoapods-integration-specs +++ b/spec/cocoapods-integration-specs @@ -1 +1 @@ -Subproject commit 9c7b64076a7e8625f22f7c12f6be7548db803b76 +Subproject commit 38495a81dc73934cd1f1c49e081cb035e754eacb diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7521eb9c49..7f655431f0 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -116,16 +116,18 @@ def fixture_target_definition(name = 'Pods', platform = Pod::Platform.ios, conte Pod::Podfile::TargetDefinition.new(name, parent, contents) end -def fixture_pod_target(spec_or_name, build_type = Pod::BuildType.static_library, user_build_configurations = {}, - archs = [], platform = Pod::Platform.new(:ios, '6.0'), target_definitions = [], - scope_suffix = nil, swift_version = nil) +def fixture_pod_target(spec_or_name, build_type = Pod::BuildType.static_library, + user_build_configurations = Pod::Target::DEFAULT_BUILD_CONFIGURATIONS, archs = [], + platform = Pod::Platform.new(:ios, '6.0'), target_definitions = [], scope_suffix = nil, + swift_version = nil) spec = spec_or_name.is_a?(Pod::Specification) ? spec_or_name : fixture_spec(spec_or_name) fixture_pod_target_with_specs([spec], build_type, user_build_configurations, archs, platform, target_definitions, scope_suffix, swift_version) end -def fixture_pod_target_with_specs(specs, build_type = Pod::BuildType.static_library, user_build_configurations = {}, - archs = [], platform = Pod::Platform.new(:ios, '6.0'), target_definitions = [], +def fixture_pod_target_with_specs(specs, build_type = Pod::BuildType.static_library, + user_build_configurations = Pod::Target::DEFAULT_BUILD_CONFIGURATIONS, archs = [], + platform = Pod::Platform.new(:ios, '6.0'), target_definitions = [], scope_suffix = nil, swift_version = nil) target_definitions << fixture_target_definition if target_definitions.empty? target_definitions.each { |td| specs.each { |spec| td.store_pod(spec.name) } } diff --git a/spec/unit/installer/analyzer_spec.rb b/spec/unit/installer/analyzer_spec.rb index 9de5efe878..1d1d662fbb 100644 --- a/spec/unit/installer/analyzer_spec.rb +++ b/spec/unit/installer/analyzer_spec.rb @@ -371,7 +371,7 @@ module Pod end analyze.should.raise(Informative). - message.should.include 'b (1.0) depends upon `a/Tests (1.0)`, which is a `test` spec.' + message.should.include '`b (1.0)` depends upon `a/Tests (1.0)`, which is a `test` spec.' pod_b = Pod::Spec.new do |s| s.name = 'b' @@ -382,7 +382,7 @@ module Pod s.app_spec 'App' end analyze.should.raise(Informative). - message.should.include 'b/Tests (1.0) depends upon `b/App (1.0)`, which is a `app` spec' + message.should.include '`b/Tests (1.0)` depends upon `b/App (1.0)`, which is a `app` spec' end describe 'with deduplicate targets as true' do diff --git a/spec/unit/installer/project_cache/target_cache_key_spec.rb b/spec/unit/installer/project_cache/target_cache_key_spec.rb index 31badb02ae..4abc86c2bd 100644 --- a/spec/unit/installer/project_cache/target_cache_key_spec.rb +++ b/spec/unit/installer/project_cache/target_cache_key_spec.rb @@ -110,7 +110,7 @@ module ProjectCache 'CONFIGURATION_BUILD_DIR' => '${PODS_CONFIGURATION_BUILD_DIR}/BananaLib', 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) "${PODS_ROOT}/../../spec/fixtures/banana-lib"', } - changed_build_settings_target.build_settings.stubs(:xcconfig).returns(Xcodeproj::Config.new(changed_build_settings)) + changed_build_settings_target.build_settings.each_value { |settings| settings.stubs(:xcconfig).returns(Xcodeproj::Config.new(changed_build_settings)) } changed_build_settings_cache_key = TargetCacheKey.from_pod_target(config.sandbox, changed_build_settings_target) @banana_cache_key.key_difference(changed_build_settings_cache_key).should.equal(:project) diff --git a/spec/unit/installer/xcode/multi_pods_project_generator_spec.rb b/spec/unit/installer/xcode/multi_pods_project_generator_spec.rb index 313758c60e..d509efc495 100644 --- a/spec/unit/installer/xcode/multi_pods_project_generator_spec.rb +++ b/spec/unit/installer/xcode/multi_pods_project_generator_spec.rb @@ -67,9 +67,7 @@ class Xcode @grapefruits_app_spec], BuildType.static_library, user_build_configurations, [], @ios_platform, [@ios_target_definition], 'iOS') - @grapefruits_ios_pod_target.app_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@monkey_pod_target] } - - @grapefruits_ios_pod_target.app_dependent_targets_by_spec_name[@grapefruits_ios_pod_target.app_specs.first.name] = [@banana_ios_pod_target] + @grapefruits_ios_pod_target.app_dependent_targets_by_spec_name = { @grapefruits_app_spec.name => [@banana_ios_pod_target] } ios_pod_targets = [@banana_ios_pod_target, @monkey_ios_pod_target, @coconut_ios_pod_target, @orangeframework_pod_target, @watermelon_ios_pod_target, @grapefruits_ios_pod_target] diff --git a/spec/unit/installer/xcode/pods_project_generator/pod_target_installer_spec.rb b/spec/unit/installer/xcode/pods_project_generator/pod_target_installer_spec.rb index e8892b056c..0c323f7831 100644 --- a/spec/unit/installer/xcode/pods_project_generator/pod_target_installer_spec.rb +++ b/spec/unit/installer/xcode/pods_project_generator/pod_target_installer_spec.rb @@ -163,7 +163,7 @@ class PodsProjectGenerator unit_test_native_target.name.should == 'WatermelonLib-Unit-Tests' unit_test_native_target.product_reference.name.should == 'WatermelonLib-Unit-Tests' unit_test_native_target.build_configurations.each do |bc| - bc.base_configuration_reference.real_path.basename.to_s.should == 'WatermelonLib.unit-tests.xcconfig' + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.unit-tests.#{bc.name.downcase}.xcconfig" bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-Unit-Tests' bc.build_settings['MACH_O_TYPE'].should.be.nil bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil @@ -179,7 +179,7 @@ class PodsProjectGenerator ui_test_native_target.name.should == 'WatermelonLib-UI-UITests' ui_test_native_target.product_reference.name.should == 'WatermelonLib-UI-UITests' ui_test_native_target.build_configurations.each do |bc| - bc.base_configuration_reference.real_path.basename.to_s.should == 'WatermelonLib.ui-uitests.xcconfig' + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.ui-uitests.#{bc.name.downcase}.xcconfig" bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-UI-UITests' bc.build_settings['MACH_O_TYPE'].should.be.nil bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil @@ -195,7 +195,7 @@ class PodsProjectGenerator snapshot_test_native_target.name.should == 'WatermelonLib-Unit-SnapshotTests' snapshot_test_native_target.product_reference.name.should == 'WatermelonLib-Unit-SnapshotTests' snapshot_test_native_target.build_configurations.each do |bc| - bc.base_configuration_reference.real_path.basename.to_s.should == 'WatermelonLib.unit-snapshottests.xcconfig' + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.unit-snapshottests.#{bc.name.downcase}.xcconfig" bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-Unit-SnapshotTests' bc.build_settings['MACH_O_TYPE'].should.be.nil bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil @@ -210,7 +210,7 @@ class PodsProjectGenerator app_native_target.name.should == 'WatermelonLib-App' app_native_target.product_reference.name.should == 'WatermelonLib-App' app_native_target.build_configurations.each do |bc| - bc.base_configuration_reference.real_path.basename.to_s.should == 'WatermelonLib.app.xcconfig' + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.app.#{bc.name.downcase}.xcconfig" bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-App' bc.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}' bc.build_settings['CURRENT_PROJECT_VERSION'].should == '1' @@ -239,7 +239,7 @@ class PodsProjectGenerator unit_test_native_target.name.should == 'WatermelonLib-Unit-Tests' unit_test_native_target.product_reference.name.should == 'WatermelonLib-Unit-Tests' unit_test_native_target.build_configurations.each do |bc| - bc.base_configuration_reference.real_path.basename.to_s.should == 'WatermelonLib.unit-tests.xcconfig' + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.unit-tests.#{bc.name.downcase}.xcconfig" bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-Unit-Tests' bc.build_settings['MACH_O_TYPE'].should.be.nil bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil @@ -254,7 +254,7 @@ class PodsProjectGenerator ui_test_native_target.name.should == 'WatermelonLib-UI-UITests' ui_test_native_target.product_reference.name.should == 'WatermelonLib-UI-UITests' ui_test_native_target.build_configurations.each do |bc| - bc.base_configuration_reference.real_path.basename.to_s.should == 'WatermelonLib.ui-uitests.xcconfig' + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.ui-uitests.#{bc.name.downcase}.xcconfig" bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-UI-UITests' bc.build_settings['MACH_O_TYPE'].should.be.nil bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil @@ -270,7 +270,7 @@ class PodsProjectGenerator snapshot_test_native_target.name.should == 'WatermelonLib-Unit-SnapshotTests' snapshot_test_native_target.product_reference.name.should == 'WatermelonLib-Unit-SnapshotTests' snapshot_test_native_target.build_configurations.each do |bc| - bc.base_configuration_reference.real_path.basename.to_s.should == 'WatermelonLib.unit-snapshottests.xcconfig' + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.unit-snapshottests.#{bc.name.downcase}.xcconfig" bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-Unit-SnapshotTests' bc.build_settings['MACH_O_TYPE'].should.be.nil bc.build_settings['PRODUCT_MODULE_NAME'].should.be.nil @@ -285,7 +285,7 @@ class PodsProjectGenerator app_native_target.name.should == 'WatermelonLib-App' app_native_target.product_reference.name.should == 'WatermelonLib-App' app_native_target.build_configurations.each do |bc| - bc.base_configuration_reference.real_path.basename.to_s.should == 'WatermelonLib.app.xcconfig' + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.app.#{bc.name.downcase}.xcconfig" bc.build_settings['PRODUCT_NAME'].should == 'WatermelonLib-App' bc.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}' bc.build_settings['CURRENT_PROJECT_VERSION'].should == '1' @@ -360,14 +360,17 @@ class PodsProjectGenerator it 'adds xcconfig file reference for test native targets' do @ios_installer.install! group = @project['Pods/WatermelonLib/Support Files'] - group.children.map(&:display_name).sort.should.include 'WatermelonLib.unit-tests.xcconfig' - group.children.map(&:display_name).sort.should.include 'WatermelonLib.unit-snapshottests.xcconfig' + group.children.map(&:display_name).sort.should.include 'WatermelonLib.unit-tests.debug.xcconfig' + group.children.map(&:display_name).sort.should.include 'WatermelonLib.unit-tests.release.xcconfig' + group.children.map(&:display_name).sort.should.include 'WatermelonLib.unit-snapshottests.debug.xcconfig' + group.children.map(&:display_name).sort.should.include 'WatermelonLib.unit-snapshottests.release.xcconfig' end it 'adds xcconfig file reference for app native targets' do @ios_installer.install! group = @project['Pods/WatermelonLib/Support Files'] - group.children.map(&:display_name).sort.should.include 'WatermelonLib.app.xcconfig' + group.children.map(&:display_name).sort.should.include 'WatermelonLib.app.debug.xcconfig' + group.children.map(&:display_name).sort.should.include 'WatermelonLib.app.release.xcconfig' end it 'does not add test header imports to umbrella header' do @@ -412,7 +415,7 @@ class PodsProjectGenerator installation_result.test_resource_bundle_targets.count.should == 3 unit_test_resource_bundle_target = @project.targets.find { |t| t.name == 'WatermelonLib-WatermelonLibTestResources' } unit_test_resource_bundle_target.build_configurations.each do |bc| - bc.base_configuration_reference.real_path.basename.to_s.should == 'WatermelonLib.unit-tests.xcconfig' + bc.base_configuration_reference.real_path.basename.to_s.should == "WatermelonLib.unit-tests.#{bc.name.downcase}.xcconfig" bc.build_settings['CONFIGURATION_BUILD_DIR'].should.be.nil end @project.targets.find { |t| t.name == 'WatermelonLib-WatermelonLibSnapshotTestResources' }.should.be.nil @@ -700,7 +703,8 @@ class PodsProjectGenerator group.children.map(&:display_name).sort.should == [ 'BananaLib-Pods-SampleProject-dummy.m', 'BananaLib-Pods-SampleProject-prefix.pch', - 'BananaLib-Pods-SampleProject.xcconfig', + 'BananaLib-Pods-SampleProject.debug.xcconfig', + 'BananaLib-Pods-SampleProject.release.xcconfig', ] end @@ -711,7 +715,8 @@ class PodsProjectGenerator group.children.map(&:display_name).sort.should == [ 'BananaLib-Pods-SampleProject-dummy.m', 'BananaLib-Pods-SampleProject-prefix.pch', - 'BananaLib-Pods-SampleProject.xcconfig', + 'BananaLib-Pods-SampleProject.debug.xcconfig', + 'BananaLib-Pods-SampleProject.release.xcconfig', ] end @@ -721,7 +726,8 @@ class PodsProjectGenerator group = @project['Pods/BananaLib/Support Files'] group.children.map(&:display_name).sort.should == [ 'BananaLib-Pods-SampleProject-dummy.m', - 'BananaLib-Pods-SampleProject.xcconfig', + 'BananaLib-Pods-SampleProject.debug.xcconfig', + 'BananaLib-Pods-SampleProject.release.xcconfig', ] end @@ -732,8 +738,9 @@ class PodsProjectGenerator group.children.map(&:display_name).sort.should == [ 'BananaLib-Pods-SampleProject-dummy.m', 'BananaLib-Pods-SampleProject-prefix.pch', + 'BananaLib-Pods-SampleProject.debug.xcconfig', 'BananaLib-Pods-SampleProject.modulemap', - 'BananaLib-Pods-SampleProject.xcconfig', + 'BananaLib-Pods-SampleProject.release.xcconfig', ] end @@ -760,8 +767,8 @@ class PodsProjectGenerator it 'adds the build configurations to the resources bundle targets' do @installer.install! @bundle_target = @project.targets.find { |t| t.name == 'BananaLib-Pods-SampleProject-banana_bundle' } - file = config.sandbox.root + @pod_target.xcconfig_path @bundle_target.build_configurations.each do |bc| + file = config.sandbox.root + @pod_target.xcconfig_path(bc.name.downcase) bc.base_configuration_reference.real_path.should == file end end @@ -843,7 +850,8 @@ class PodsProjectGenerator group.children.map(&:display_name).sort.should == [ 'BananaLib-dummy.m', 'BananaLib-prefix.pch', - 'BananaLib.xcconfig', + 'BananaLib.debug.xcconfig', + 'BananaLib.release.xcconfig', ] end @@ -853,7 +861,8 @@ class PodsProjectGenerator group = @project['Pods/BananaLib/Support Files'] group.children.map(&:display_name).sort.should == [ 'BananaLib-dummy.m', - 'BananaLib.xcconfig', + 'BananaLib.debug.xcconfig', + 'BananaLib.release.xcconfig', ] end @@ -864,8 +873,9 @@ class PodsProjectGenerator group.children.map(&:display_name).sort.should == [ 'BananaLib-dummy.m', 'BananaLib-prefix.pch', + 'BananaLib.debug.xcconfig', 'BananaLib.modulemap', - 'BananaLib.xcconfig', + 'BananaLib.release.xcconfig', ] end @@ -891,8 +901,8 @@ class PodsProjectGenerator it 'adds the build configurations to the resources bundle targets' do @installer.install! @bundle_target = @project.targets.find { |t| t.name == 'BananaLib-banana_bundle' } - file = config.sandbox.root + @pod_target.xcconfig_path @bundle_target.build_configurations.each do |bc| + file = config.sandbox.root + @pod_target.xcconfig_path(bc.name.downcase) bc.base_configuration_reference.real_path.should == file end end @@ -923,9 +933,11 @@ class PodsProjectGenerator it 'creates the xcconfig file' do @installer.install! - file = config.sandbox.root + @pod_target.xcconfig_path - xcconfig = Xcodeproj::Config.new(file) - xcconfig.to_hash['PODS_ROOT'].should == '${SRCROOT}' + %w(debug release).each do |variant| + file = config.sandbox.root + @pod_target.xcconfig_path(variant) + xcconfig = Xcodeproj::Config.new(file) + xcconfig.to_hash['PODS_ROOT'].should == '${SRCROOT}' + end end it "creates a prefix header, including the contents of the specification's prefix header" do @@ -968,8 +980,9 @@ class PodsProjectGenerator 'BananaLib-Info.plist', 'BananaLib-dummy.m', 'BananaLib-prefix.pch', + 'BananaLib.debug.xcconfig', 'BananaLib.modulemap', - 'BananaLib.xcconfig', + 'BananaLib.release.xcconfig', ] end @@ -981,8 +994,9 @@ class PodsProjectGenerator 'BananaLib-Info.plist', 'BananaLib-dummy.m', 'BananaLib-prefix.pch', + 'BananaLib.debug.xcconfig', 'BananaLib.modulemap', - 'BananaLib.xcconfig', + 'BananaLib.release.xcconfig', ] end @@ -996,8 +1010,9 @@ class PodsProjectGenerator group.children.map(&:display_name).sort.should == [ 'BananaLib-dummy.m', 'BananaLib-prefix.pch', + 'BananaLib.debug.xcconfig', 'BananaLib.modulemap', - 'BananaLib.xcconfig', + 'BananaLib.release.xcconfig', ] end @@ -1017,7 +1032,7 @@ class PodsProjectGenerator @pod_target.stubs(:should_build?).returns(false) @installer.install! group = @project['Pods/BananaLib/Support Files'] - group.children.map(&:display_name).sort.should == ['BananaLib.xcconfig'] + group.children.map(&:display_name).sort.should == %w(BananaLib.debug.xcconfig BananaLib.release.xcconfig) end it 'does not set architectures for targets that should not build' do diff --git a/spec/unit/installer/xcode/single_pods_project_generator_spec.rb b/spec/unit/installer/xcode/single_pods_project_generator_spec.rb index cc24993980..3158053512 100644 --- a/spec/unit/installer/xcode/single_pods_project_generator_spec.rb +++ b/spec/unit/installer/xcode/single_pods_project_generator_spec.rb @@ -70,9 +70,7 @@ class Xcode BuildType.static_library, user_build_configurations, [], @ios_platform, [@ios_target_definition], 'iOS') - @grapefruits_ios_pod_target.app_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@monkey_pod_target] } - - @grapefruits_ios_pod_target.app_dependent_targets_by_spec_name[@grapefruits_ios_pod_target.app_specs.first.name] = [@banana_ios_pod_target] + @grapefruits_ios_pod_target.app_dependent_targets_by_spec_name = { @grapefruits_app_spec.name => [@banana_ios_pod_target] } ios_pod_targets = [@banana_ios_pod_target, @monkey_ios_pod_target, @coconut_ios_pod_target, @orangeframework_pod_target, @watermelon_ios_pod_target, @grapefruits_ios_pod_target] diff --git a/spec/unit/target/build_settings/aggregate_target_settings_spec.rb b/spec/unit/target/build_settings/aggregate_target_settings_spec.rb index 1b941bfdf9..98b0a7d5a6 100644 --- a/spec/unit/target/build_settings/aggregate_target_settings_spec.rb +++ b/spec/unit/target/build_settings/aggregate_target_settings_spec.rb @@ -9,7 +9,7 @@ def specs end def pod_target(spec, target_definition) - fixture_pod_target(spec, BuildType.static_library, {}, [], Platform.new(:ios, '6.0'), [target_definition]) + fixture_pod_target(spec, BuildType.static_library, { 'Release' => :release }, [], Platform.new(:ios, '6.0'), [target_definition]) end before do @@ -23,7 +23,7 @@ def pod_target(spec, target_definition) unless @specs.empty? @target.target_definition.whitelist_pod_for_configuration(@specs.first.name, 'Release') end - @generator = AggregateTargetSettings.new(@target, 'Release') + @generator = AggregateTargetSettings.new(@target, 'Release', :configuration => :release) end shared 'Aggregate' do @@ -153,7 +153,7 @@ def specs describe 'with a pod target inhibiting warnings' do def pod_target(spec, target_definition) - fixture_pod_target(spec, BuildType.static_library, {}, [], Platform.new(:ios, '6.0'), + fixture_pod_target(spec, BuildType.static_library, { 'Debug' => :debug, 'Release' => :release }, [], Platform.new(:ios, '6.0'), [target_definition]).tap { |pt| pt.stubs(:inhibit_warnings? => true) } end @@ -165,7 +165,7 @@ def pod_target(spec, target_definition) describe 'with pod targets that define modules' do def pod_target(spec, target_definition) - fixture_pod_target(spec, BuildType.static_library, {}, [], Platform.new(:ios, '6.0'), + fixture_pod_target(spec, BuildType.static_library, { 'Debug' => :debug, 'Release' => :release }, [], Platform.new(:ios, '6.0'), [target_definition]).tap { |pt| pt.stubs(:defines_module? => true) } end @@ -186,7 +186,7 @@ def pod_target(spec, target_definition) describe 'with a scoped pod target' do def pod_target(spec, target_definition) - fixture_pod_target(spec, BuildType.static_library, {}, [], Platform.new(:ios, '6.0'), [target_definition]).scoped.first + fixture_pod_target(spec, BuildType.static_library, { 'Debug' => :debug, 'Release' => :release }, [], Platform.new(:ios, '6.0'), [target_definition]).scoped.first end it 'links the pod targets with the aggregate target' do @@ -201,7 +201,7 @@ def pod_target(spec, target_definition) end it 'does not links the pod targets with the aggregate target for non-whitelisted configuration' do - @generator = AggregateTargetSettings.new(@target, 'Debug') + @generator = AggregateTargetSettings.new(@target, 'Debug', :configuration => :debug) @xcconfig = @generator.dup.generate @xcconfig.to_hash['OTHER_LDFLAGS'].should.be.nil end @@ -245,10 +245,11 @@ def pod_target(spec, target_definition) :build_product_path => 'BPP', :product_basename => 'PodTarget', :target_definitions => [target_definition], + :root_spec => spec, ) - pod_target.stubs(:build_settings => PodTargetSettings.new(pod_target)) + pod_target.stubs(:build_settings_for_spec => PodTargetSettings.new(pod_target, nil, :configuration => :release)) aggregate_target = fixture_aggregate_target([pod_target]) - @generator = AggregateTargetSettings.new(aggregate_target, 'Release') + @generator = AggregateTargetSettings.new(aggregate_target, 'Release', :configuration => :release) @generator.other_ldflags.should == %w(-ObjC -l"PodTarget" -l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "StaticFramework" -framework "VendoredFramework" -framework "XCTest") end end @@ -327,7 +328,7 @@ def specs def pod_target(spec, target_definition) target_definition = fixture_target_definition(spec.name) target_definition.stubs(:parent).returns(@target_definition.podfile) - fixture_pod_target(spec, BuildType.static_library, {}, [], Platform.new(:ios, '6.0'), [@target_definition], 'iOS') + fixture_pod_target(spec, BuildType.static_library, { 'Release' => :release }, [], Platform.new(:ios, '6.0'), [@target_definition], 'iOS') end it 'adds the framework build path to the xcconfig, with quotes, as framework search paths' do @@ -353,7 +354,7 @@ def pod_target(spec, target_definition) describe 'with a pod target inhibiting warnings' do def pod_target(spec, target_definition) - fixture_pod_target(spec, BuildType.static_library, {}, [], Platform.new(:ios, '6.0'), [target_definition]).tap { |pt| pt.stubs(:inhibit_warnings? => true) } + fixture_pod_target(spec, BuildType.static_library, { 'Release' => :release }, [], Platform.new(:ios, '6.0'), [target_definition]).tap { |pt| pt.stubs(:inhibit_warnings? => true) } end it 'adds the framework build path to the xcconfig, with quotes, as system framework search paths' do @@ -492,10 +493,11 @@ def pod_target(spec, target_definition) :build_product_path => 'BPP', :product_basename => 'PodTarget', :target_definitions => [target_definition], + :root_spec => spec, ) - pod_target.stubs(:build_settings => PodTargetSettings.new(pod_target)) + pod_target.stubs(:build_settings_for_spec => PodTargetSettings.new(pod_target, nil, :configuration => :release)) aggregate_target = fixture_aggregate_target([pod_target]) - @generator = AggregateTargetSettings.new(aggregate_target, 'Release') + @generator = AggregateTargetSettings.new(aggregate_target, 'Release', :configuration => :release) @generator.other_ldflags.should == %w(-ObjC -l"VendoredDyld" -l"xml2" -framework "PodTarget" -framework "VendoredFramework" -framework "XCTest") end @@ -539,10 +541,11 @@ def pod_target(spec, target_definition) :build_product_path => 'BPP', :product_basename => 'PodTarget', :target_definitions => [target_definition], + :root_spec => spec, ) - pod_target.stubs(:build_settings => PodTargetSettings.new(pod_target)) + pod_target.stubs(:build_settings_for_spec => PodTargetSettings.new(pod_target, nil, :configuration => :release)) aggregate_target = fixture_aggregate_target([pod_target]) - @generator = AggregateTargetSettings.new(aggregate_target, 'Release') + @generator = AggregateTargetSettings.new(aggregate_target, 'Release', :configuration => :release) @generator.other_ldflags.should == %w(-ObjC -l"PodTarget" -l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "StaticFramework" -framework "VendoredFramework" -framework "XCTest" -weak_framework "iAd") end @@ -586,10 +589,11 @@ def pod_target(spec, target_definition) :build_product_path => 'BPP', :product_basename => 'PodTarget', :target_definitions => [target_definition], + :root_spec => spec, ) - pod_target.stubs(:build_settings => PodTargetSettings.new(pod_target)) + pod_target.stubs(:build_settings_for_spec => PodTargetSettings.new(pod_target, :configuration => :release)) aggregate_target = fixture_aggregate_target([pod_target]) - @generator = AggregateTargetSettings.new(aggregate_target, 'Release') + @generator = AggregateTargetSettings.new(aggregate_target, 'Release', :configuration => :release) @generator.other_ldflags.should == %w(-ObjC -l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "PodTarget" -framework "StaticFramework" -framework "VendoredFramework" -framework "XCTest") end end @@ -709,7 +713,7 @@ def specs describe 'an empty pod target' do before do @blank_target = fixture_aggregate_target - @generator = AggregateTargetSettings.new(@blank_target, 'Release') + @generator = AggregateTargetSettings.new(@blank_target, 'Release', :configuration => :release) end it 'it should not have any framework search paths' do diff --git a/spec/unit/target/build_settings/pod_target_settings_spec.rb b/spec/unit/target/build_settings/pod_target_settings_spec.rb index f4a574a9a1..31b34179c1 100644 --- a/spec/unit/target/build_settings/pod_target_settings_spec.rb +++ b/spec/unit/target/build_settings/pod_target_settings_spec.rb @@ -46,7 +46,7 @@ class BuildSettings :uses_swift? => false, :specs => [vspec], ) - vendored_dep_target.stubs(:build_settings => PodTargetSettings.new(vendored_dep_target)) + vendored_dep_target.stubs(:build_settings => { :debug => PodTargetSettings.new(vendored_dep_target, nil, :configuration => :debug) }) @spec = fixture_spec('banana-lib/BananaLib.podspec') @pod_target = fixture_pod_target(@spec, BuildType.dynamic_framework) @@ -54,7 +54,7 @@ class BuildSettings @consumer = @pod_target.spec_consumers.first @podfile = @pod_target.podfile - @generator = PodTargetSettings.new(@pod_target) + @generator = PodTargetSettings.new(@pod_target, nil, :configuration => :debug) @spec.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' } @spec.user_target_xcconfig = { 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11' } @@ -218,7 +218,7 @@ class BuildSettings :sandbox => config.sandbox, :should_build? => true, ) - pod_target.stubs(:build_settings => PodTargetSettings.new(pod_target)) + pod_target.stubs(:build_settings => { :debug => PodTargetSettings.new(pod_target, nil, :configuration => :debug) }) @generator.spec_consumers.each { |sc| sc.stubs(:frameworks => []) } @generator.stubs(:dependent_targets => [pod_target]) @generator.other_ldflags.should. @@ -246,14 +246,14 @@ class BuildSettings @coconut_spec.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => 'NON_TEST_FLAG=1', 'PODS_ROOT' => 'OVERRIDDEN', 'GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED' => 'YES', 'GCC_TREAT_WARNINGS_AS_ERRORS' => 'YES' } @coconut_test_spec.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => 'TEST_ONLY=1', 'PODS_ROOT' => 'OVERRIDDEN2', 'GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED' => 'YES', 'GCC_TREAT_WARNINGS_AS_ERRORS' => 'NO' } - generator = PodTargetSettings.new(@coconut_pod_target) + generator = PodTargetSettings.new(@coconut_pod_target, nil, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['GCC_PREPROCESSOR_DEFINITIONS'].should == '$(inherited) COCOAPODS=1 NON_TEST_FLAG=1' xcconfig.to_hash['PODS_ROOT'].should == 'OVERRIDDEN' xcconfig.to_hash['GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED'].should == 'YES' xcconfig.to_hash['GCC_TREAT_WARNINGS_AS_ERRORS'].should == 'YES' - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['GCC_PREPROCESSOR_DEFINITIONS'].should == '$(inherited) COCOAPODS=1 NON_TEST_FLAG=1 TEST_ONLY=1' xcconfig.to_hash['PODS_ROOT'].should == 'OVERRIDDEN2' @@ -266,7 +266,7 @@ class BuildSettings it 'merges pod target xcconfig settings from subspecs' do @matryoshka_spec.subspecs[0].pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => 'FIRST_SUBSPEC_FLAG=1', 'PODS_ROOT' => 'OVERRIDDEN' } @matryoshka_spec.subspecs[1].pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => 'SECOND_SUBSPEC_FLAG=1' } - generator = PodTargetSettings.new(@matryoshka_pod_target) + generator = PodTargetSettings.new(@matryoshka_pod_target, nil, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['GCC_PREPROCESSOR_DEFINITIONS'].should == '$(inherited) COCOAPODS=1 FIRST_SUBSPEC_FLAG=1 SECOND_SUBSPEC_FLAG=1' xcconfig.to_hash['PODS_ROOT'].should == 'OVERRIDDEN' @@ -275,41 +275,41 @@ class BuildSettings it 'merges the pod target xcconfig of non test specifications for test xcconfigs' do @coconut_spec.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => 'NON_TEST_FLAG=1' } @coconut_test_spec.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => 'TEST_ONLY=1' } - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['GCC_PREPROCESSOR_DEFINITIONS'].should == '$(inherited) COCOAPODS=1 NON_TEST_FLAG=1 TEST_ONLY=1' end it 'includes correct other ld flags' do - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['OTHER_LDFLAGS'].should == '$(inherited) -ObjC -l"CoconutLib"' end it 'includes correct other ld flags when requires frameworks' do @coconut_pod_target.stubs(:build_type => BuildType.dynamic_framework) - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['OTHER_LDFLAGS'].should == '$(inherited) -ObjC -framework "CoconutLib"' end it 'includes other ld flags for transitive dependent targets' do @coconut_pod_target.dependent_targets = [@monkey_pod_target] - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['OTHER_LDFLAGS'].should == '$(inherited) -ObjC -l"CoconutLib" -l"monkey" -framework "dynamic-monkey"' end it 'includes other ld flags for test dependent targets' do @coconut_pod_target.test_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@monkey_pod_target] } - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['OTHER_LDFLAGS'].should == '$(inherited) -ObjC -l"CoconutLib" -l"monkey" -framework "dynamic-monkey"' end it 'adds settings for test dependent targets' do @coconut_pod_target.test_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@banana_pod_target] } - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/../../spec/fixtures/banana-lib"' xcconfig.to_hash['LIBRARY_SEARCH_PATHS'].should == '$(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BananaLib" "${PODS_CONFIGURATION_BUILD_DIR}/CoconutLib" "${PODS_ROOT}/../../spec/fixtures/banana-lib"' @@ -318,7 +318,7 @@ class BuildSettings it 'adds settings for test dependent targets excluding the parents targets' do @coconut_pod_target.dependent_targets = [@banana_pod_target] @coconut_pod_target.test_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@banana_pod_target] } - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/../../spec/fixtures/banana-lib"' xcconfig.to_hash['LIBRARY_SEARCH_PATHS'].should == '$(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BananaLib" "${PODS_CONFIGURATION_BUILD_DIR}/CoconutLib" "${PODS_ROOT}/../../spec/fixtures/banana-lib"' @@ -328,11 +328,11 @@ class BuildSettings @banana_pod_target.spec_consumers.each { |sc| sc.stubs(:frameworks => %w(XCTest), :vendored_frameworks => []) } @coconut_pod_target.dependent_targets = [@banana_pod_target] - generator = PodTargetSettings.new(@coconut_pod_target) + generator = PodTargetSettings.new(@coconut_pod_target, nil, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"' - generator = PodTargetSettings.new(@banana_pod_target) + generator = PodTargetSettings.new(@banana_pod_target, nil, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"' end @@ -348,7 +348,7 @@ class BuildSettings @coconut_pod_target.sandbox.public_headers.add_search_path('CoconutLib', Platform.ios) @coconut_pod_target.test_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@monkey_pod_target] } @coconut_pod_target.dependent_targets = [@banana_pod_target] - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/Headers/Private"' \ ' "${PODS_ROOT}/Headers/Private/CoconutLib"' \ @@ -370,7 +370,7 @@ class BuildSettings @coconut_pod_target.test_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@monkey_pod_target] } @coconut_pod_target.dependent_targets = [@banana_pod_target] # This is not an test xcconfig so it should exclude header search paths for the 'monkey' pod - generator = PodTargetSettings.new(@coconut_pod_target) + generator = PodTargetSettings.new(@coconut_pod_target, nil, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/Headers/Private"' \ ' "${PODS_ROOT}/Headers/Private/CoconutLib"' \ @@ -390,7 +390,7 @@ class BuildSettings @coconut_pod_target.sandbox.public_headers.add_search_path('CoconutLib', Platform.ios) @coconut_pod_target.test_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@monkey_pod_target] } @coconut_pod_target.dependent_targets = [@banana_pod_target] - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/Headers/Private"' \ ' "${PODS_ROOT}/Headers/Private/CoconutLib"' \ @@ -408,7 +408,7 @@ class BuildSettings @coconut_pod_target.sandbox.public_headers.add_search_path('CoconutLib', Platform.ios) @coconut_pod_target.test_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@monkey_pod_target] } @coconut_pod_target.dependent_targets = [@banana_pod_target] - generator = PodTargetSettings.new(@coconut_pod_target) + generator = PodTargetSettings.new(@coconut_pod_target, nil, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/Headers/Private"' \ ' "${PODS_ROOT}/Headers/Private/CoconutLib"' \ @@ -417,27 +417,27 @@ class BuildSettings it 'does not include other ld flags for test dependent targets if its not a test xcconfig' do @coconut_pod_target.test_dependent_targets_by_spec_name = { @coconut_test_spec.name => [@monkey_pod_target] } - generator = PodTargetSettings.new(@coconut_pod_target) + generator = PodTargetSettings.new(@coconut_pod_target, nil, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['LIBRARY_SEARCH_PATHS'].should.be.nil xcconfig.to_hash['OTHER_LDFLAGS'].should.be.nil end it 'includes default runpath search path list for test xcconfigs' do - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['LD_RUNPATH_SEARCH_PATHS'].should == "$(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'" end it 'includes default runpath search path list for test xcconfigs for test bundle' do @coconut_pod_target.stubs(:platform).returns(Platform.new(:osx, '10.10')) - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['LD_RUNPATH_SEARCH_PATHS'].should == "$(inherited) '@executable_path/../Frameworks' '@loader_path/../Frameworks'" end it 'does not set configuration build dir for test xcconfigs' do - generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec) + generator = PodTargetSettings.new(@coconut_pod_target, @coconut_test_spec, :configuration => :debug) xcconfig = generator.generate xcconfig.to_hash['CONFIGURATION_BUILD_DIR'].should.be.nil end diff --git a/spec/unit/target/build_settings_spec.rb b/spec/unit/target/build_settings_spec.rb index 73064ba445..ac4c7c56c1 100644 --- a/spec/unit/target/build_settings_spec.rb +++ b/spec/unit/target/build_settings_spec.rb @@ -4,11 +4,11 @@ module Pod class Target describe BuildSettings do def pod(pod_target) - BuildSettings::PodTargetSettings.new(pod_target) + BuildSettings::PodTargetSettings.new(pod_target, nil, :configuration => :debug) end def aggregate(aggregate_target, configuration_name = 'Release') - BuildSettings::AggregateTargetSettings.new(aggregate_target, configuration_name) + BuildSettings::AggregateTargetSettings.new(aggregate_target, configuration_name, :configuration => configuration_name.downcase.to_sym) end describe 'memoization' do @@ -174,8 +174,9 @@ def aggregate(aggregate_target, configuration_name = 'Release') :build_as_static? => false, :product_basename => 'PodTarget', :target_definitions => [target_definition], + :root_spec => spec, ) - pod_target.stubs(:build_settings => pod(pod_target)) + pod_target.stubs(:build_settings_for_spec => pod(pod_target)) aggregate_target = fixture_aggregate_target([pod_target]) aggregate(aggregate_target).other_ldflags.should.not.include '-framework' end @@ -210,8 +211,9 @@ def aggregate(aggregate_target, configuration_name = 'Release') :build_as_static? => false, :product_basename => 'PodTarget', :target_definitions => [target_definition], + :root_spec => spec, ) - pod_target.stubs(:build_settings => pod(pod_target)) + pod_target.stubs(:build_settings_for_spec => pod(pod_target)) aggregate_target = fixture_aggregate_target([pod_target]) aggregate(aggregate_target).other_ldflags.should.not.include '-framework' end @@ -244,8 +246,9 @@ def aggregate(aggregate_target, configuration_name = 'Release') :build_as_static? => false, :product_basename => 'PodTarget', :target_definitions => [target_definition], + :root_spec => spec, ) - pod_target.stubs(:build_settings => pod(pod_target)) + pod_target.stubs(:build_settings_for_spec => pod(pod_target)) aggregate_target = fixture_aggregate_target([pod_target], true) aggregate(aggregate_target).other_ldflags.should.not.include '-ObjC' end @@ -280,8 +283,9 @@ def aggregate(aggregate_target, configuration_name = 'Release') :build_as_static? => true, :product_basename => 'PodTarget', :target_definitions => [target_definition], + :root_spec => spec, ) - pod_target.stubs(:build_settings => pod(pod_target)) + pod_target.stubs(:build_settings_for_spec => pod(pod_target)) aggregate_target = fixture_aggregate_target([pod_target], true) aggregate(aggregate_target).other_ldflags.should.include '-ObjC' end diff --git a/spec/unit/target/pod_target_spec.rb b/spec/unit/target/pod_target_spec.rb index 565ed3e13e..7b7eb27be2 100644 --- a/spec/unit/target/pod_target_spec.rb +++ b/spec/unit/target/pod_target_spec.rb @@ -95,6 +95,20 @@ module Pod @pod_target.should_build?.should == false end + it 'returns empty sets of dependent targets' do + grapefruits = fixture_spec('grapefruits-lib/GrapefruitsLib.podspec') + @pod_target = fixture_pod_target_with_specs([grapefruits, *grapefruits.recursive_subspecs], false, {}, [], Platform.ios, [@target_definition]) + + @pod_target.dependent_targets.should == [] + @pod_target.dependent_targets_by_config.should == { :debug => [], :release => [] } + + @pod_target.test_dependent_targets_by_spec_name.should == { 'GrapefruitsLib/Tests' => [] } + @pod_target.test_dependent_targets_by_spec_name_by_config.should == { 'GrapefruitsLib/Tests' => { :debug => [], :release => [] } } + + @pod_target.app_dependent_targets_by_spec_name.should == { 'GrapefruitsLib/App' => [] } + @pod_target.app_dependent_targets_by_spec_name_by_config.should == { 'GrapefruitsLib/App' => { :debug => [], :release => [] } } + end + describe '#headers_sandbox' do it 'returns the correct path' do @pod_target.headers_sandbox.should == Pathname.new('BananaLib') @@ -117,7 +131,7 @@ module Pod before do @watermelon_spec = fixture_spec('grapefruits-lib/GrapefruitsLib.podspec') @pod_target = fixture_pod_target_with_specs([@watermelon_spec, *@watermelon_spec.recursive_subspecs], - true, {}, [], Platform.new(:ios, '6.0'), [@target_definition]) + true, Pod::Target::DEFAULT_BUILD_CONFIGURATIONS, [], Platform.new(:ios, '6.0'), [@target_definition]) end it 'raises when the target does not contain the spec' do @@ -125,17 +139,20 @@ module Pod end it 'returns the build settings for a library spec' do - @pod_target.build_settings_for_spec(@watermelon_spec).should.equal @pod_target.build_settings + @pod_target.build_settings_for_spec(@watermelon_spec, :configuration => :debug).should.equal @pod_target.build_settings[:debug] + @pod_target.build_settings_for_spec(@watermelon_spec, :configuration => :release).should.equal @pod_target.build_settings[:release] end it 'returns the build settings for a test spec' do test_spec = @watermelon_spec.recursive_subspecs.find { |s| s.name == 'GrapefruitsLib/Tests' } - @pod_target.build_settings_for_spec(test_spec).non_library_spec.should == test_spec + @pod_target.build_settings_for_spec(test_spec, :configuration => :debug).non_library_spec.should == test_spec + @pod_target.build_settings_for_spec(test_spec, :configuration => :release).non_library_spec.should == test_spec end it 'returns the build settings for an app spec' do app_spec = @watermelon_spec.recursive_subspecs.find { |s| s.name == 'GrapefruitsLib/App' } - @pod_target.build_settings_for_spec(app_spec).non_library_spec.should == app_spec + @pod_target.build_settings_for_spec(app_spec, :configuration => :debug).non_library_spec.should == app_spec + @pod_target.build_settings_for_spec(app_spec, :configuration => :release).non_library_spec.should == app_spec end end end @@ -328,7 +345,7 @@ module Pod monkey_spec = fixture_spec('monkey/monkey.podspec') monkey_pod_target = PodTarget.new(config.sandbox, BuildType.static_library, {}, [], Platform.ios, [monkey_spec], [@target_definition]) - @pod_target.stubs(:dependent_targets).returns([monkey_pod_target]) + @pod_target.dependent_targets = [monkey_pod_target] header_search_paths = @pod_target.header_search_paths header_search_paths.sort.should == [ '${PODS_ROOT}/Headers/Private', @@ -409,7 +426,7 @@ module Pod @pod_target.sandbox.public_headers.add_search_path('monkey', Platform.ios) @monkey_pod_target = fixture_pod_target('monkey/monkey.podspec') @monkey_pod_target.stubs(:platform).returns(Platform.ios) - @pod_target.stubs(:dependent_targets).returns([@monkey_pod_target]) + @pod_target.dependent_targets = [@monkey_pod_target] @file_accessor = @monkey_pod_target.file_accessors.first @file_accessor.spec_consumer.stubs(:header_dir).returns('Sub_dir') header_search_paths = @pod_target.header_search_paths @@ -638,20 +655,24 @@ module Pod describe 'With dependencies' do before do - @pod_dependency = fixture_pod_target('orange-framework/OrangeFramework.podspec', BuildType.static_library, {}, [], Platform.ios, - @pod_target.target_definitions) - @test_pod_dependency = fixture_pod_target('matryoshka/matryoshka.podspec', BuildType.static_library, {}, [], Platform.ios, - @pod_target.target_definitions) - @app_pod_dependency = fixture_pod_target('monkey/monkey.podspec', BuildType.static_library, {}, [], Platform.ios, - @pod_target.target_definitions) - @pod_target.dependent_targets = [@pod_dependency] - @pod_target.test_dependent_targets_by_spec_name = { @pod_dependency.name => [@test_pod_dependency] } - @pod_target.app_dependent_targets_by_spec_name = { @pod_dependency.name => [@app_pod_dependency] } - @pod_target.test_app_hosts_by_spec_name = { @pod_dependency.name => [@test_pod_dependency.specs.first, @test_pod_dependency] } + @orangeframework_pod_target = fixture_pod_target('orange-framework/OrangeFramework.podspec', + BuildType.static_library, {}, [], Platform.ios, + @pod_target.target_definitions) + @matryoshka_pod_target = fixture_pod_target('matryoshka/matryoshka.podspec', BuildType.static_library, {}, [], + Platform.ios, @pod_target.target_definitions) + @monkey_pod_target = fixture_pod_target('monkey/monkey.podspec', BuildType.static_library, {}, [], + Platform.ios, @pod_target.target_definitions) + @coconut_pod_target = fixture_pod_target('coconut-lib/CoconutLib.podspec', BuildType.static_library, {}, [], + Platform.ios, @pod_target.target_definitions) + @pod_target.dependent_targets = [@orangeframework_pod_target] + @pod_target.test_dependent_targets_by_spec_name = { @orangeframework_pod_target.name => [@matryoshka_pod_target] } + @pod_target.app_dependent_targets_by_spec_name = { @orangeframework_pod_target.name => [@monkey_pod_target] } + @pod_target.test_app_hosts_by_spec_name = { @orangeframework_pod_target.name => [@matryoshka_pod_target.specs.first, + @matryoshka_pod_target] } end it 'resolves simple dependencies' do - @pod_target.recursive_dependent_targets.should == [@pod_dependency] + @pod_target.recursive_dependent_targets.should == [@orangeframework_pod_target] end it 'scopes test and non test dependencies' do @@ -667,19 +688,57 @@ module Pod it 'scopes test app host dependencies' do scoped_pod_target = @pod_target.scoped scoped_pod_target.first.test_app_hosts_by_spec_name.count.should == 1 - scoped_pod_target.first.test_app_hosts_by_spec_name['OrangeFramework'].first.should == @test_pod_dependency.specs.first + scoped_pod_target.first.test_app_hosts_by_spec_name['OrangeFramework'].first.should == @matryoshka_pod_target.specs.first scoped_pod_target.first.test_app_hosts_by_spec_name['OrangeFramework'].last.name.should == 'matryoshka-Pods' end describe 'With cyclic dependencies' do before do - @pod_dependency = fixture_pod_target('orange-framework/OrangeFramework.podspec') - @pod_dependency.dependent_targets = [@pod_target] - @pod_target.dependent_targets = [@pod_dependency] + @orangeframework_pod_target = fixture_pod_target('orange-framework/OrangeFramework.podspec') + @orangeframework_pod_target.dependent_targets = [@pod_target] + @pod_target.dependent_targets = [@orangeframework_pod_target] end it 'resolves the cycle' do - @pod_target.recursive_dependent_targets.should == [@pod_dependency] + @pod_target.recursive_dependent_targets.should == [@orangeframework_pod_target] + end + end + + describe 'With per configuration dependencies' do + before do + @per_config_dependencies = { :debug => [@orangeframework_pod_target, @matryoshka_pod_target], :release => [@coconut_pod_target] } + end + + it 'returns correct set of dependencies depending on configuration' do + @pod_target.dependent_targets_by_config = @per_config_dependencies + @pod_target.recursive_dependent_targets(:configuration => :debug).should == [@orangeframework_pod_target, @matryoshka_pod_target] + @pod_target.recursive_dependent_targets(:configuration => :release).should == [@coconut_pod_target] + @pod_target.recursive_dependent_targets.should == [@orangeframework_pod_target, @matryoshka_pod_target, @coconut_pod_target] + end + + it 'returns correct set of test dependencies depending on configuration' do + watermelon_spec = fixture_spec('watermelon-lib/WatermelonLib.podspec') + watermelon_pod_target = fixture_pod_target_with_specs([watermelon_spec, + *watermelon_spec.recursive_subspecs], + BuildType.static_library, {}, [], Platform.ios, + @pod_target.target_definitions) + test_spec = watermelon_pod_target.test_specs.first + watermelon_pod_target.test_dependent_targets_by_spec_name_by_config = { test_spec.name => @per_config_dependencies } + watermelon_pod_target.recursive_test_dependent_targets(test_spec, :configuration => :debug).should == [@orangeframework_pod_target, @matryoshka_pod_target] + watermelon_pod_target.recursive_test_dependent_targets(test_spec, :configuration => :release).should == [@coconut_pod_target] + watermelon_pod_target.recursive_test_dependent_targets(test_spec).should == [@orangeframework_pod_target, @matryoshka_pod_target, @coconut_pod_target] + end + + it 'returns correct set of app dependencies depending on configuration' do + watermelon_spec = fixture_spec('watermelon-lib/WatermelonLib.podspec') + watermelon_pod_target = fixture_pod_target_with_specs([watermelon_spec, + *watermelon_spec.recursive_subspecs], + BuildType.static_library, {}, [], Platform.ios, + @pod_target.target_definitions) + app_spec = watermelon_pod_target.app_specs.first + watermelon_pod_target.app_dependent_targets_by_spec_name_by_config = { app_spec.name => @per_config_dependencies } + watermelon_pod_target.recursive_app_dependent_targets(app_spec, :configuration => :debug).should == [@orangeframework_pod_target, @matryoshka_pod_target] + watermelon_pod_target.recursive_app_dependent_targets(app_spec, :configuration => :release).should == [@coconut_pod_target] end end end @@ -754,7 +813,7 @@ module Pod it 'returns an empty scheme configuration for a spec with an unsupported platform' do @matryoshka_spec.ios.deployment_target = '7.0' @matryoshka_spec.subspecs.first.watchos.deployment_target = '4.2' - pod_target = fixture_pod_target(@matryoshka_spec.subspecs.first, BuildType.dynamic_framework, [], {}, Platform.watchos) + pod_target = fixture_pod_target(@matryoshka_spec.subspecs.first, BuildType.dynamic_framework, {}, {}, Platform.watchos) pod_target.scheme_for_spec(@matryoshka_spec).should == {} end end