Unverified Commit 071e84d9 authored by Samuel Giddins's avatar Samuel Giddins Committed by GitHub

Merge pull request #7631 from CocoaPods/segiddins/build-settings-refactor

Refactor build settings generation to be memoizable
parents 42688f78 08ea793e
......@@ -18,6 +18,9 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
* Improve performance of Pods project generator by skipping native targets for which dependent targets have already been added.
[Jacek Suliga](https://github.com/jmkk)
* Refactor build settings generation to perform much better on large projects.
[Samuel Giddins](https://github.com/segiddins)
##### Bug Fixes
* Remove [system] declaration attribute from generated module maps
......@@ -56,6 +59,12 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
[Maxime Le Moine](https://github.com/MaximeLM)
[#7590](https://github.com/CocoaPods/CocoaPods/issues/7590)
* When integrating a vendored framework while building pods as static
libraries, public headers will be found via `FRAMEWORK_SEARCH_PATHS`
instead of via the sandbox headers store.
[Samuel Giddins](https://github.com/segiddins)
## 1.5.0 (2018-04-04)
##### Enhancements
......
......@@ -66,7 +66,6 @@ module Pod
autoload :ModuleMap, 'cocoapods/generator/module_map'
autoload :PrefixHeader, 'cocoapods/generator/prefix_header'
autoload :UmbrellaHeader, 'cocoapods/generator/umbrella_header'
autoload :XCConfig, 'cocoapods/generator/xcconfig'
autoload :AppTargetHelper, 'cocoapods/generator/app_target_helper'
end
......
module Pod
module Generator
# Generates Xcode configuration files. A configuration file is generated
# for each Pod and for each Pod target definition. The aggregates the
# configurations of the Pods and define target specific settings.
#
module XCConfig
autoload :AggregateXCConfig, 'cocoapods/generator/xcconfig/aggregate_xcconfig'
autoload :PodXCConfig, 'cocoapods/generator/xcconfig/pod_xcconfig'
autoload :XCConfigHelper, 'cocoapods/generator/xcconfig/xcconfig_helper'
end
end
end
module Pod
module Generator
module XCConfig
# Generates the xcconfigs for the aggregate targets.
#
class AggregateXCConfig
# @return [AggregateTarget] the target represented by this xcconfig.
#
attr_reader :target
# @return [String] the name of the build configuration to generate this
# xcconfig for.
#
attr_reader :configuration_name
# Initialize a new instance
#
# @param [Target] target @see #target
# @param [String] configuration_name @see #configuration_name
#
def initialize(target, configuration_name)
@target = target
@configuration_name = configuration_name
end
# Generates and saves the xcconfig to the given path.
#
# @param [Pathname] path
# the path where the xcconfig should be stored.
#
# @return [Xcodeproj::Config]
#
def save_as(path)
result = generate
result.save_as(path)
result
end
# Generates the xcconfig.
#
# @note The xcconfig file for a Pods integration target includes the
# namespaced xcconfig files for each spec target dependency.
# Each namespaced configuration value is merged into the Pod
# xcconfig file.
#
# @todo This doesn't include the specs xcconfigs anymore and now the
# logic is duplicated.
#
# @return [Xcodeproj::Config]
#
def generate
includes_static_libs = !target.requires_frameworks?
includes_static_libs ||= pod_targets.flat_map(&:file_accessors).any? { |fa| !fa.vendored_static_artifacts.empty? }
config = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
'HEADER_SEARCH_PATHS' => '$(inherited) ',
'LIBRARY_SEARCH_PATHS' => '$(inherited) ',
'OTHER_CFLAGS' => '$(inherited) ',
'OTHER_LDFLAGS' => '$(inherited) ' + XCConfigHelper.default_ld_flags(target, includes_static_libs),
'OTHER_SWIFT_FLAGS' => '$(inherited) ',
'PODS_PODFILE_DIR_PATH' => target.podfile_dir_relative_path,
'PODS_ROOT' => target.relative_pods_root,
'SWIFT_INCLUDE_PATHS' => '$(inherited) ',
}.merge(embedded_content_settings)
xcconfig = Xcodeproj::Config.new(config)
xcconfig.merge!(merged_user_target_xcconfigs)
generate_settings_to_import_pod_targets(xcconfig)
XCConfigHelper.add_target_specific_settings(target, xcconfig)
targets = pod_targets + target.search_paths_aggregate_targets.flat_map(&:pod_targets)
XCConfigHelper.generate_vendored_build_settings(target, targets, xcconfig)
XCConfigHelper.generate_other_ld_flags(target, pod_targets, xcconfig)
# TODO: Need to decide how we are going to ensure settings like these
# are always excluded from the user's project.
#
# See https://github.com/CocoaPods/CocoaPods/issues/1216
xcconfig.attributes.delete('USE_HEADERMAP')
# If any of the aggregate target dependencies bring in any vendored dynamic artifacts we should ensure to
# update the runpath search paths.
vendored_dynamic_artifacts = pod_targets.flat_map(&:file_accessors).flat_map(&:vendored_dynamic_artifacts)
symbol_type = target.user_targets.map(&:symbol_type).uniq.first
test_bundle = symbol_type == :octest_bundle || symbol_type == :unit_test_bundle || symbol_type == :ui_test_bundle
XCConfigHelper.generate_ld_runpath_search_paths(target, target.requires_host_target?, test_bundle, xcconfig) if target.requires_frameworks? || vendored_dynamic_artifacts.count > 0
xcconfig
end
#---------------------------------------------------------------------#
protected
# @return [Hash<String, String>] the build settings necessary to import
# the pod targets.
#
def settings_to_import_pod_targets
if target.requires_frameworks?
build_pod_targets = pod_targets.select(&:should_build?)
framework_header_search_paths = build_pod_targets.map do |target|
"#{target.build_product_path}/Headers"
end
build_settings = {
# TODO: remove quote imports in CocoaPods 2.0
# Make framework headers discoverable by `import "…"`
'OTHER_CFLAGS' => XCConfigHelper.quote(framework_header_search_paths, '-iquote'),
}
if pod_targets.any? { |t| !t.should_build? }
# Make library headers discoverable by `#import "…"`
library_header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
# TODO: remove quote imports in CocoaPods 2.0
build_settings['HEADER_SEARCH_PATHS'] = XCConfigHelper.quote(library_header_search_paths)
build_settings['OTHER_CFLAGS'] += ' ' + XCConfigHelper.quote(library_header_search_paths, '-isystem')
end
build_settings
else
# Make headers discoverable from $PODS_ROOT/Headers directory
header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
{
# TODO: remove quote imports in CocoaPods 2.0
# by `#import "…"`
'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(header_search_paths),
# by `#import <…>`
'OTHER_CFLAGS' => XCConfigHelper.quote(header_search_paths, '-isystem'),
}
end
end
#---------------------------------------------------------------------#
private
# @return String the SWIFT_VERSION of the target being integrated
#
def target_swift_version
target.target_definition.swift_version unless target.target_definition.swift_version.blank?
end
EMBED_STANDARD_LIBRARIES_MINIMUM_VERSION = Gem::Version.new('2.3')
# @return [Hash<String, String>] the build settings necessary for Swift
# targets to be correctly embedded in their host.
#
def embedded_content_settings
# For embedded targets, which live in a host target, CocoaPods
# copies all of the embedded target's pod_targets its host
# target. Therefore, this check will properly require the Swift
# libs in the host target, if the embedded target has any pod targets
# that use Swift. Setting this for the embedded target would
# cause an App Store rejection because frameworks cannot be embedded
# in embedded targets.
swift_version = Gem::Version.new(target_swift_version)
should_embed = !target.requires_host_target? && pod_targets.any?(&:uses_swift?)
config = {}
if should_embed
if swift_version >= EMBED_STANDARD_LIBRARIES_MINIMUM_VERSION
config['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'] = 'YES'
else
config['EMBEDDED_CONTENT_CONTAINS_SWIFT'] = 'YES'
end
end
config
end
# Add build settings, which ensure that the pod targets can be imported from the integrating target.
# For >= 1.5.0 we use modular (stricter) header search paths this means that the integrated target will only be
# able to import public headers using `<>` or `@import` notation, but never import any private headers.
#
# For < 1.5.0 legacy header search paths the same rules apply: It's the wild west.
#
def generate_settings_to_import_pod_targets(xcconfig)
xcconfig.merge! XCConfigHelper.search_paths_for_dependent_targets(target, pod_targets)
xcconfig.merge!(settings_to_import_pod_targets)
target.search_paths_aggregate_targets.each do |search_paths_target|
generator = AggregateXCConfig.new(search_paths_target, configuration_name)
xcconfig.merge! XCConfigHelper.search_paths_for_dependent_targets(nil, search_paths_target.pod_targets)
xcconfig.merge!(generator.settings_to_import_pod_targets)
# Propagate any HEADER_SEARCH_PATHS settings from the search paths.
XCConfigHelper.propagate_header_search_paths_from_search_paths(search_paths_target, xcconfig)
end
end
#---------------------------------------------------------------------#
# !@group Private Helpers
# Returns the {PodTarget}s which are active for the current
# configuration name.
#
# @return [Array<PodTarget>]
#
def pod_targets
target.pod_targets_for_build_configuration(configuration_name)
end
# Returns the +user_target_xcconfig+ for all pod targets and their spec
# consumers grouped by keys
#
# @return [Hash{String,Hash{Target,String}]
#
def user_target_xcconfig_values_by_consumer_by_key
pod_targets.each_with_object({}) do |target, hash|
target.spec_consumers.each do |spec_consumer|
spec_consumer.user_target_xcconfig.each do |k, v|
(hash[k] ||= {})[spec_consumer] = v
end
end
end
end
# Merges the +user_target_xcconfig+ for all pod targets into the
# #xcconfig and warns on conflicting definitions.
#
# @return [Hash{String, String}]
#
def merged_user_target_xcconfigs
settings = user_target_xcconfig_values_by_consumer_by_key
settings.each_with_object({}) do |(key, values_by_consumer), xcconfig|
uniq_values = values_by_consumer.values.uniq
values_are_bools = uniq_values.all? { |v| v =~ /^(yes|no)$/i }
if values_are_bools
# Boolean build settings
if uniq_values.count > 1
UI.warn 'Can\'t merge user_target_xcconfig for pod targets: ' \
"#{values_by_consumer.keys.map(&:name)}. Boolean build "\
"setting #{key} has different values."
else
xcconfig[key] = uniq_values.first
end
elsif key =~ /S$/
# Plural build settings
xcconfig[key] = uniq_values.join(' ')
else
# Singular build settings
if uniq_values.count > 1
UI.warn 'Can\'t merge user_target_xcconfig for pod targets: ' \
"#{values_by_consumer.keys.map(&:name)}. Singular build "\
"setting #{key} has different values."
else
xcconfig[key] = uniq_values.first
end
end
end
end
#---------------------------------------------------------------------#
end
end
end
end
module Pod
module Generator
module XCConfig
# Generates the private xcconfigs for the pod targets.
#
# The xcconfig file for a Pod target merges the pod target
# configuration values with the default configuration values
# required by CocoaPods.
#
class PodXCConfig
# @return [Target] the target represented by this xcconfig.
#
attr_reader :target
# @return [Boolean] whether this xcconfig is for a test target.
#
attr_reader :test_xcconfig
alias test_xcconfig? test_xcconfig
# Initialize a new instance
#
# @param [Target] target @see #target
#
# @param [Boolean] test_xcconfig
# whether this is an xcconfig for a test native target.
#
def initialize(target, test_xcconfig = false)
@target = target
@test_xcconfig = test_xcconfig
end
# Generates and saves the xcconfig to the given path.
#
# @param [Pathname] path
# the path where the xcconfig should be stored.
#
# @return [Xcodeproj::Config]
#
def save_as(path)
result = generate
result.save_as(path)
result
end
# Generates the xcconfig.
#
# @return [Xcodeproj::Config]
#
def generate
config = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
'HEADER_SEARCH_PATHS' => '$(inherited) ' + XCConfigHelper.quote(target.header_search_paths(test_xcconfig?)),
'LIBRARY_SEARCH_PATHS' => '$(inherited) ',
'OTHER_CFLAGS' => '$(inherited) ',
'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target, test_xcconfig?),
'OTHER_SWIFT_FLAGS' => '$(inherited) ',
'PODS_ROOT' => '${SRCROOT}',
'PODS_TARGET_SRCROOT' => target.pod_target_srcroot,
'PRODUCT_BUNDLE_IDENTIFIER' => 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}',
'SKIP_INSTALL' => 'YES',
'SWIFT_ACTIVE_COMPILATION_CONDITIONS' => '$(inherited) ',
'SWIFT_INCLUDE_PATHS' => '$(inherited) ',
}
xcconfig = Xcodeproj::Config.new(config)
XCConfigHelper.add_settings_for_file_accessors_of_target(nil, target, xcconfig, true, test_xcconfig?)
target.file_accessors.each do |file_accessor|
xcconfig.merge!(file_accessor.spec_consumer.pod_target_xcconfig) if test_xcconfig? == file_accessor.spec.test_specification?
end
XCConfigHelper.add_target_specific_settings(target, xcconfig)
recursive_dependent_targets = target.recursive_dependent_targets
xcconfig.merge! XCConfigHelper.search_paths_for_dependent_targets(target, recursive_dependent_targets, test_xcconfig?)
XCConfigHelper.generate_vendored_build_settings(target, recursive_dependent_targets, xcconfig, false, test_xcconfig?)
if test_xcconfig?
test_dependent_targets = [target, *target.recursive_test_dependent_targets].uniq
xcconfig.merge! XCConfigHelper.search_paths_for_dependent_targets(target, test_dependent_targets - recursive_dependent_targets, test_xcconfig?)
XCConfigHelper.generate_vendored_build_settings(nil, target.all_dependent_targets, xcconfig, true, test_xcconfig?)
XCConfigHelper.generate_other_ld_flags(nil, target.all_dependent_targets, xcconfig)
XCConfigHelper.generate_ld_runpath_search_paths(target, false, true, xcconfig)
end
xcconfig
end
#-----------------------------------------------------------------------#
end
end
end
end
require 'active_support/core_ext/object/try'
module Pod
module Generator
module XCConfig
# Stores the shared logic of the classes of the XCConfig module.
#
module XCConfigHelper
# @return [String] Used as alias for BUILD_DIR, so that when this
# is overridden in the user target, the user can override
# this variable to point to the standard directory, which
# will be used by CocoaPods.
#
BUILD_DIR_VARIABLE = '${PODS_BUILD_DIR}'.freeze
# @return [String] Used as alias for CONFIGURATION_BUILD_DIR, so that
# when this is overridden per {PodTarget}, it is still possible
# to reference other build products relative to the original
# path. Furthermore if it was overridden in the user target,
# the user can override this variable to point to the standard
# directory, which will be used by CocoaPods.
#
CONFIGURATION_BUILD_DIR_VARIABLE = '${PODS_CONFIGURATION_BUILD_DIR}'.freeze
# Converts an array of strings to a single string where the each string
# is surrounded by double quotes and separated by a space. Used to
# represent strings in a xcconfig file.
#
# @param [Array<String>] strings
# a list of strings.
#
# @param [String] prefix
# optional prefix, such as a flag or option.
#
# @return [String] the resulting string.
#
def self.quote(strings, prefix = nil)
prefix = "#{prefix} " if prefix
strings.sort.map { |s| %W( #{prefix}"#{s}" ) }.join(' ')
end
# Return the default linker flags
#
# @param [Target] target
# the target, which is used to check if the ARC compatibility
# flag is required.
#
# @param [Boolean] include_objc_flag
# whether to include `-ObjC` in the other linker flags
#
# @return [String] the default linker flags. `-ObjC` is optionally included depending
# on the target while `-fobjc-arc` is included only if requested in the Podfile.
#
def self.default_ld_flags(target, include_objc_flag = false)
ld_flags = ''
ld_flags << '-ObjC' if include_objc_flag
if target.podfile.set_arc_compatibility_flag? &&
target.spec_consumers.any?(&:requires_arc?)
ld_flags << ' -fobjc-arc'
end
ld_flags.strip
end
# Configures the given Xcconfig
#
# @param [Target] target
# The root target, may be nil.
#
# @param [PodTarget] pod_target
# The pod target, which holds the list of +Spec::FileAccessor+.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @param [Boolean] include_ld_flags
# Indicates whether or not to generate ld flags in addition to compile flags
#
# @param [Boolean] test_xcconfig
# Whether the settings for dependent targets are being generated for a test xcconfig or not.
#
# @return [void]
#
def self.add_settings_for_file_accessors_of_target(target, pod_target, xcconfig, include_ld_flags = true, test_xcconfig = false)
file_accessors = pod_target.file_accessors
file_accessors = file_accessors.reject { |f| f.spec.test_specification? } unless test_xcconfig
file_accessors.each do |file_accessor|
if target.nil? || !file_accessor.spec.test_specification?
XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, xcconfig) if include_ld_flags
XCConfigHelper.add_static_dependency_build_settings(target, pod_target, xcconfig, file_accessor, include_ld_flags)
end
end
XCConfigHelper.add_dynamic_dependency_build_settings(target, pod_target, xcconfig, include_ld_flags, test_xcconfig)
if pod_target.requires_frameworks?
pod_target.dependent_targets.each do |dependent_target|
XCConfigHelper.add_dynamic_dependency_build_settings(target, dependent_target, xcconfig, include_ld_flags, test_xcconfig)
end
end
end
# Adds build settings for static vendored frameworks and libraries.
#
# @param [Target] target
# The root target, may be nil.
#
# @param [PodTarget] pod_target
# The pod target, which holds the list of +Spec::FileAccessor+.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @param [Spec::FileAccessor] file_accessor
# The file accessor, which holds the list of static frameworks.
#
# @param [Boolean] include_ld_flags
# Indicates whether or not to generate ld flags in addition to compile flags
#
# @return [void]
#
def self.add_static_dependency_build_settings(target, pod_target, xcconfig, file_accessor, include_ld_flags)
if target.nil? || !file_accessor.spec.test_specification?
adds_other_ldflags = include_ld_flags && XCConfigHelper.links_dependency?(target, pod_target)
file_accessor.vendored_static_frameworks.each do |vendored_static_framework|
XCConfigHelper.add_framework_build_settings(vendored_static_framework, xcconfig, pod_target.sandbox.root, adds_other_ldflags)
end
file_accessor.vendored_static_libraries.each do |vendored_static_library|
XCConfigHelper.add_library_build_settings(vendored_static_library, xcconfig, pod_target.sandbox.root, adds_other_ldflags)
end
end
end
# @param [AggregateTarget] aggregate_target
# The aggregate target, may be nil.
#
# @param [PodTarget] pod_target
# The pod target to link or not.
#
# @return [Boolean] Whether static dependency should be added to the 'OTHER_LDFLAGS'
# of the aggregate target. Aggregate targets that inherit search paths will only link
# if the target has explicitly declared the pod dependency.
#
def self.links_dependency?(aggregate_target, pod_target)
return true if aggregate_target.nil? || aggregate_target.target_definition.inheritance == 'complete'
aggregate_target.pod_targets_to_link.include?(pod_target)
end
# Adds build settings for dynamic vendored frameworks and libraries.
#
# @param [Target] target
# The root target, may be nil.
#
# @param [PodTarget] pod_target
# The pod target, which holds the list of +Spec::FileAccessor+.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @param [Boolean] include_ld_flags
# Indicates whether or not to generate ld flags in addition to compile flags
#
# @param [Boolean] test_xcconfig
# Whether the settings for dependent targets are being generated for a test xcconfig or not.
#
# @return [void]
#
def self.add_dynamic_dependency_build_settings(target, pod_target, xcconfig, include_ld_flags, test_xcconfig)
file_accessors = pod_target.file_accessors
file_accessors = file_accessors.reject { |f| f.spec.test_specification? } unless test_xcconfig
file_accessors.each do |file_accessor|
if target.nil? || !file_accessor.spec.test_specification?
file_accessor.vendored_dynamic_frameworks.each do |vendored_dynamic_framework|
XCConfigHelper.add_framework_build_settings(vendored_dynamic_framework, xcconfig, pod_target.sandbox.root, include_ld_flags)
end
file_accessor.vendored_dynamic_libraries.each do |vendored_dynamic_library|
XCConfigHelper.add_library_build_settings(vendored_dynamic_library, xcconfig, pod_target.sandbox.root, include_ld_flags)
end
end
end
end
# Configures the given Xcconfig according to the build settings of the
# given Specification.
#
# @param [Specification::Consumer] consumer
# The consumer of the specification.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @return [void]
#
def self.add_spec_build_settings_to_xcconfig(consumer, xcconfig)
xcconfig.libraries.merge(consumer.libraries)
xcconfig.frameworks.merge(consumer.frameworks)
xcconfig.weak_frameworks.merge(consumer.weak_frameworks)
add_developers_frameworks_if_needed(xcconfig)
end
# Configures the given Xcconfig with the build settings for the given
# framework path.
#
# @param [Pathname] framework_path
# The path of the framework.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @param [Pathname] sandbox_root
# The path retrieved from Sandbox#root.
#
# @param [Boolean] include_ld_flags
# Indicates whether or not to generate ld flags in addition to compile flags
#
# @return [void]
#
def self.add_framework_build_settings(framework_path, xcconfig, sandbox_root, include_ld_flags = true)
name = File.basename(framework_path, '.framework')
dirname = '${PODS_ROOT}/' + framework_path.dirname.relative_path_from(sandbox_root).to_s
build_settings = {
'FRAMEWORK_SEARCH_PATHS' => quote([dirname]),
}
build_settings['OTHER_LDFLAGS'] = "-framework \"#{name}\"" if include_ld_flags
xcconfig.merge!(build_settings)
end
# Configures the given Xcconfig with the build settings for the given
# library path.
#
# @param [Pathname] library_path
# The path of the library.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @param [Pathname] sandbox_root
# The path retrieved from Sandbox#root.
#
# @param [Boolean] include_ld_flags
# Indicates whether or not to generate ld flags in addition to compile flags
#
# @return [void]
#
def self.add_library_build_settings(library_path, xcconfig, sandbox_root, include_ld_flags = true)
extension = File.extname(library_path)
name = File.basename(library_path, extension).sub(/\Alib/, '')
dirname = '${PODS_ROOT}/' + library_path.dirname.relative_path_from(sandbox_root).to_s
build_settings = {
'LIBRARY_SEARCH_PATHS' => quote([dirname]),
}
build_settings['OTHER_LDFLAGS'] = "-l\"#{name}\"" if include_ld_flags
xcconfig.merge!(build_settings)
end
# Add the code signing settings for generated targets to ensure that
# frameworks are correctly signed to be integrated and re-signed when
# building the application and embedding the framework
#
# @param [Target] target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @return [void]
#
def self.add_code_signing_settings(target, xcconfig)
build_settings = {}
if target.platform.to_sym == :osx
build_settings['CODE_SIGN_IDENTITY'] = ''
end
xcconfig.merge!(build_settings)
end
# Checks if the given target requires specific settings and configures
# the given Xcconfig.
#
# @param [Target] target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @return [void]
#
def self.add_target_specific_settings(target, xcconfig)
if target.requires_frameworks?
add_code_signing_settings(target, xcconfig)
end
add_language_specific_settings(target, xcconfig)
end
# Returns the search paths for frameworks and libraries the given target
# depends on, so that it can be correctly built and linked.
#
# @param [Target] target
# The target.
#
# @param [Array<PodTarget>] dependent_targets
# The pod targets the given target depends on.
#
# @param [Boolean] test_xcconfig
# Whether the settings for dependent targets are being generated for a test xcconfig or not.
#
# @return [Hash<String, String>] the settings
#
def self.search_paths_for_dependent_targets(target, dependent_targets, test_xcconfig = false)
dependent_targets = dependent_targets.select(&:should_build?)
# Filter out dependent targets that are subsets of another target.
subset_targets = []
dependent_targets.uniq.combination(2) do |a, b|
if (a.specs - b.specs).empty?
subset_targets << a
elsif (b.specs - a.specs).empty?
subset_targets << b
end
end
dependent_targets -= subset_targets
# Alias build dirs to avoid recursive definitions for pod targets and depending
# on build settings which could be overwritten in the user target.
build_settings = {
BUILD_DIR_VARIABLE[2..-2] => '${BUILD_DIR}',
CONFIGURATION_BUILD_DIR_VARIABLE[2..-2] => "#{BUILD_DIR_VARIABLE}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)",
}
# Scope pod targets as long as they are not test targets.
if !test_xcconfig && target.respond_to?(:configuration_build_dir)
build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)
end
module_map_files = []
unless dependent_targets.empty?
framework_search_paths = []
library_search_paths = []
swift_import_paths = []
dependent_targets.each do |dependent_target|
if dependent_target.requires_frameworks?
framework_search_paths << dependent_target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)
else
library_search_paths << dependent_target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)
if dependent_target.defines_module?
module_map_file = if dependent_target.uses_swift?
# for swift, we have a custom build phase that copies in the module map, appending the .Swift module
"${PODS_CONFIGURATION_BUILD_DIR}/#{dependent_target.label}/#{dependent_target.product_module_name}.modulemap"
else
"${PODS_ROOT}/#{dependent_target.module_map_path.relative_path_from(dependent_target.sandbox.root)}"
end
module_map_files << %(-fmodule-map-file="#{module_map_file}")
swift_import_paths << dependent_target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE) if dependent_target.uses_swift?
end
end
end
build_settings['FRAMEWORK_SEARCH_PATHS'] = XCConfigHelper.quote(framework_search_paths.uniq)
build_settings['LIBRARY_SEARCH_PATHS'] = XCConfigHelper.quote(library_search_paths.uniq)
build_settings['SWIFT_INCLUDE_PATHS'] = XCConfigHelper.quote(swift_import_paths.uniq)
end
other_swift_flags = module_map_files.tap(&:uniq!).flat_map { |f| ['-Xcc', f] }
if target.is_a?(PodTarget) && !target.requires_frameworks? && target.defines_module? && !test_xcconfig
# make it possible for a mixed swift/objc static library to be able to import the objc from within swift
other_swift_flags += ['-import-underlying-module', '-Xcc', '-fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}"']
end
# unconditionally set these, because of (the possibility of) having to add the pod targets own module map file
build_settings['OTHER_CFLAGS'] = module_map_files.join(' ')
build_settings['OTHER_SWIFT_FLAGS'] = other_swift_flags.join(' ')
build_settings
end
# Updates xcconfig with the HEADER_SEARCH_PATHS from the search_paths.
#
# @param [Target] search_paths_target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
def self.propagate_header_search_paths_from_search_paths(search_paths_target, xcconfig)
header_search_paths_list = []
search_paths_target.pod_targets.each do |target|
target.spec_consumers.each do |spec_consumer|
paths = spec_consumer.user_target_xcconfig['HEADER_SEARCH_PATHS']
header_search_paths_list <<= paths unless paths.nil?
end
unless header_search_paths_list == []
header_search_paths = header_search_paths_list.join(' ')
unless header_search_paths.include? '$(inherited)'
header_search_paths = '$(inherited) ' + header_search_paths
end
build_settings = { 'HEADER_SEARCH_PATHS' => header_search_paths }
xcconfig.merge!(build_settings)
end
end
end
# Add custom build settings and required build settings to link to
# vendored libraries and frameworks.
#
# @param [Target] target
# The root target, may be nil.
#
# @param [Array<PodTarget] dep_targets
# The dependency targets to add the vendored build settings for.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @param [Boolean] include_ld_flags
# Indicates whether or not to generate ld flags in addition to compile flags
#
# @param [Boolean] test_xcconfig
# Indicates whether or not the generated ld flags are for a test xcconfig or not
#
# @note
# In case of generated pod targets, which require frameworks, the
# vendored frameworks and libraries are already linked statically
# into the framework binary and must not be linked again to the
# user target.
#
def self.generate_vendored_build_settings(target, dep_targets, xcconfig, include_ld_flags = true, test_xcconfig = false)
dep_targets.each do |dep_target|
unless dep_target.should_build? && dep_target.requires_frameworks? && !dep_target.static_framework?
XCConfigHelper.add_settings_for_file_accessors_of_target(target, dep_target, xcconfig, include_ld_flags, test_xcconfig)
end
end
end
# Ensure to add the default linker run path search paths as they could
# be not present due to being historically absent in the project or
# target template or just being removed by being superficial when
# linking third-party dependencies exclusively statically. This is not
# something a project needs specifically for the integration with
# CocoaPods, but makes sure that it is self-contained for the given
# constraints.
#
# @param [Target] target
# The target, this can be an aggregate target or a pod target.
#
# @param [Boolean] requires_host_target
# If this target requires a host target
#
# @param [Boolean] test_bundle
# Whether this is a test bundle or not. This has an effect when the platform is `osx` and changes
# the runtime search paths accordingly.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @return [void]
#
def self.generate_ld_runpath_search_paths(target, requires_host_target, test_bundle, xcconfig)
ld_runpath_search_paths = ['$(inherited)']
if target.platform.symbolic_name == :osx
ld_runpath_search_paths << "'@executable_path/../Frameworks'"
ld_runpath_search_paths << \
if test_bundle
"'@loader_path/../Frameworks'"
else
"'@loader_path/Frameworks'"
end
else
ld_runpath_search_paths << [
"'@executable_path/Frameworks'",
"'@loader_path/Frameworks'",
]
ld_runpath_search_paths << "'@executable_path/../../Frameworks'" if requires_host_target
end
xcconfig.merge!('LD_RUNPATH_SEARCH_PATHS' => ld_runpath_search_paths.join(' '))
end
# Add pod target to list of frameworks / libraries that are linked
# with the user’s project.
#
# @param [AggregateTarget] aggregate_target
# The aggregate target, may be nil.
#
# @param [Array<PodTarget] pod_targets
# The pod targets to add the vendored build settings for.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @return [void]
#
def self.generate_other_ld_flags(aggregate_target, pod_targets, xcconfig)
# Make sure -framework option gets added for the search paths when static_frameworks are involved.
# Otherwise test targets won't link in their primary target's dependencies.
unless aggregate_target.nil?
dependent_targets = aggregate_target.search_paths_aggregate_targets
dependent_targets.each do |dependent_target|
if aggregate_target.requires_frameworks? && dependent_target.pod_targets.any?(&:static_framework?)
generate_other_ld_flags(dependent_target, dependent_target.pod_targets, xcconfig)
end
end
end
other_ld_flags = pod_targets.select(&:should_build?).map do |pod_target|
if pod_target.requires_frameworks?
%(-framework "#{pod_target.product_basename}")
elsif XCConfigHelper.links_dependency?(aggregate_target, pod_target)
%(-l "#{pod_target.product_basename}")
end
end
xcconfig.merge!('OTHER_LDFLAGS' => other_ld_flags.compact.join(' '))
end
# Checks if the given target requires language specific settings and
# configures the given Xcconfig.
#
# @param [Target] target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @return [void]
#
def self.add_language_specific_settings(target, xcconfig)
if target.uses_swift?
other_swift_flags = ['$(inherited)', quote(%w(-D COCOAPODS))]
other_swift_flags << quote(%w(-suppress-warnings)) if target.try(:inhibit_warnings?)
build_settings = { 'OTHER_SWIFT_FLAGS' => other_swift_flags.join(' ') }
xcconfig.merge!(build_settings)
end
end
# Adds the search paths of the developer frameworks to the specification
# if needed. This is done because the `SenTestingKit` requires them and
# adding them to each specification which requires it is repetitive and
# error prone.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
# @return [void]
#
def self.add_developers_frameworks_if_needed(xcconfig)
matched_frameworks = xcconfig.frameworks & %w(XCTest SenTestingKit)
unless matched_frameworks.empty?
search_paths = xcconfig.attributes['FRAMEWORK_SEARCH_PATHS'] ||= ''
search_paths_to_add = []
search_paths_to_add << '$(inherited)'
frameworks_path = '"$(PLATFORM_DIR)/Developer/Library/Frameworks"'
search_paths_to_add << frameworks_path
search_paths_to_add.each do |search_path|
unless search_paths.include?(search_path)
search_paths << ' ' unless search_paths.empty?
search_paths << search_path
end
end
end
end
#---------------------------------------------------------------------#
end
end
end
end
......@@ -441,7 +441,7 @@ module Pod
user_project = nil
client_root = config.installation_root.realpath
user_target_uuids = []
user_build_configurations = target_definition.build_configurations || { 'Release' => :release, 'Debug' => :debug }
user_build_configurations = target_definition.build_configurations || Target::DEFAULT_BUILD_CONFIGURATIONS
archs = []
if target_definition.platform && target_definition.platform.name == :osx
archs = ['$(ARCHS_STANDARD_64_BIT)']
......
......@@ -96,9 +96,9 @@ module Pod
def create_xcconfig_file(native_target)
native_target.build_configurations.each do |configuration|
path = target.xcconfig_path(configuration.name)
gen = Generator::XCConfig::AggregateXCConfig.new(target, configuration.name)
xcconfig = update_changed_file(gen, path)
target.xcconfigs[configuration.name] = xcconfig
build_settings = target.build_settings(configuration.name)
update_changed_file(build_settings, path)
target.xcconfigs[configuration.name] = build_settings.xcconfig
xcconfig_file_ref = add_file_to_support_group(path)
configuration.base_configuration_reference = xcconfig_file_ref
end
......
......@@ -158,13 +158,6 @@ module Pod
added_public_headers = true
sandbox.public_headers.add_files(namespaced_path, files)
end
unless pod_target.requires_frameworks?
vendored_frameworks_header_mappings(headers_sandbox, file_accessor).each do |namespaced_path, files|
added_public_headers = true
sandbox.public_headers.add_files(namespaced_path, files)
end
end
end
pod_target.build_headers.add_search_path(headers_sandbox, pod_target.platform) if added_build_headers
......@@ -332,36 +325,6 @@ module Pod
mappings
end
# Computes the destination sub-directory in the sandbox for headers
# from inside vendored frameworks.
#
# @param [Pathname] headers_sandbox
# The sandbox where the header links should be stored for this
# Pod.
#
# @param [Sandbox::FileAccessor] file_accessor
# The consumer file accessor for which the headers need to be
# linked.
#
def vendored_frameworks_header_mappings(headers_sandbox, file_accessor)
mappings = {}
file_accessor.vendored_frameworks.each do |framework|
headers_dir = Sandbox::FileAccessor.vendored_frameworks_headers_dir(framework)
headers = Sandbox::FileAccessor.vendored_frameworks_headers(framework)
framework_name = framework.basename(framework.extname)
dir = headers_sandbox + framework_name
headers.each do |header|
# the relative path of framework headers should be kept,
# not flattened like is done for most public headers.
relative_path = header.relative_path_from(headers_dir)
sub_dir = dir + relative_path.dirname
mappings[sub_dir] ||= []
mappings[sub_dir] << header
end
end
mappings
end
#-----------------------------------------------------------------------#
end
end
......
......@@ -402,8 +402,7 @@ module Pod
#
def create_xcconfig_file(native_target, resource_bundle_targets)
path = target.xcconfig_path
xcconfig_gen = Generator::XCConfig::PodXCConfig.new(target)
update_changed_file(xcconfig_gen, path)
update_changed_file(target.build_settings, path)
xcconfig_file_ref = add_file_to_support_group(path)
native_target.build_configurations.each do |c|
......@@ -427,8 +426,7 @@ module Pod
def create_test_xcconfig_files(test_native_targets, test_resource_bundle_targets)
target.supported_test_types.each do |test_type|
path = target.xcconfig_path(test_type.to_s)
xcconfig_gen = Generator::XCConfig::PodXCConfig.new(target, true)
update_changed_file(xcconfig_gen, path)
update_changed_file(Target::BuildSettings::PodTargetSettings.new(target, true), path)
xcconfig_file_ref = add_file_to_support_group(path)
test_native_targets.each do |test_target|
......
......@@ -63,7 +63,7 @@ module Pod
paths << "${PODS_ROOT}/#{headers_dir}/#{@relative_path}" if !use_modular_headers || @visibility_scope == :public
paths << "${PODS_ROOT}/#{headers_dir}/#{entry[:path]}" if !use_modular_headers || @visibility_scope == :private
paths
end.uniq
end.tap(&:uniq!).freeze
end
# Removes the directory as it is regenerated from scratch during each
......
require 'cocoapods/target/build_settings'
module Pod
# Model class which describes a Pods target.
#
......@@ -8,6 +10,7 @@ module Pod
class Target
DEFAULT_VERSION = '1.0.0'.freeze
DEFAULT_NAME = 'Default'.freeze
DEFAULT_BUILD_CONFIGURATIONS = { 'Release' => :release, 'Debug' => :debug }.freeze
# @return [Sandbox] The sandbox where the Pods should be installed.
#
......@@ -33,6 +36,10 @@ module Pod
#
attr_reader :platform
# @return [BuildSettings] the build settings for this target.
#
attr_reader :build_settings
# Initialize a new target
#
# @param [Sandbox] sandbox @see #sandbox
......@@ -47,6 +54,8 @@ module Pod
@user_build_configurations = user_build_configurations
@archs = archs
@platform = platform
@build_settings = create_build_settings
end
# @return [String] the name of the library.
......@@ -228,5 +237,9 @@ module Pod
def c99ext_identifier(name)
name.gsub(/^([0-9])/, '_\1').gsub(/[^a-zA-Z0-9_]/, '_')
end
def create_build_settings
BuildSettings.new(self)
end
end
end
......@@ -77,6 +77,16 @@ module Pod
@xcconfigs = {}
end
def build_settings(configuration_name = nil)
if configuration_name
@build_settings[configuration_name] ||
raise(ArgumentError, "#{self} does not contain a build setting for the #{configuration_name.inspect} configuration, only #{@build_settings.keys.inspect}")
else
@build_settings.each_value.first ||
raise(ArgumentError, "#{self} does not contain any build settings")
end
end
# @return [Boolean] True if the user_target refers to a
# library (framework, static or dynamic lib).
#
......@@ -153,10 +163,6 @@ module Pod
end
end
def pod_targets_to_link
@pod_targets_to_link ||= pod_targets.to_set - search_paths_aggregate_targets.flat_map(&:pod_targets)
end
# @return [Array<Specification>] The specifications used by this aggregate target.
#
def specs
......@@ -309,5 +315,15 @@ module Pod
def relative_to_srcroot(path)
path.relative_path_from(client_root).to_s
end
def create_build_settings
settings = {}
user_build_configurations.each_key do |configuration_name|
settings[configuration_name] = BuildSettings::AggregateTargetSettings.new(self, configuration_name)
end
settings
end
end
end
# frozen_string_literal: true
module Pod
class Target
# @since 1.5.0
class BuildSettings
#-------------------------------------------------------------------------#
# @!group Constants
# @return [Set<String>]
# The build settings that should be treated as arrays, rather than strings.
#
PLURAL_SETTINGS = %w(
ALTERNATE_PERMISSIONS_FILES
ARCHS
BUILD_VARIANTS
EXCLUDED_SOURCE_FILE_NAMES
FRAMEWORK_SEARCH_PATHS
GCC_PREPROCESSOR_DEFINITIONS
GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS
HEADER_SEARCH_PATHS
INFOPLIST_PREPROCESSOR_DEFINITIONS
LD_RUNPATH_SEARCH_PATHS
LIBRARY_SEARCH_PATHS
OTHER_CFLAGS
OTHER_CPLUSPLUSFLAGS
OTHER_LDFLAGS
OTHER_SWIFT_FLAGS
REZ_SEARCH_PATHS
SECTORDER_FLAGS
SWIFT_ACTIVE_COMPILATION_CONDITIONS
SWIFT_INCLUDE_PATHS
WARNING_CFLAGS
WARNING_LDFLAGS
).to_set.freeze
# @return [String]
# The variable for the configuration build directory used when building pod targets.
#
CONFIGURATION_BUILD_DIR_VARIABLE = '${PODS_CONFIGURATION_BUILD_DIR}'.freeze
#-------------------------------------------------------------------------#
# @!group DSL
# Creates a method that calculates a part of the build settings for the {#target}.
#
# @!visibility private
#
# @param [Symbol,String] method_name
# The name of the method to define
#
# @param [Boolean] build_setting
# Whether the method name should be added (upcased) to {.build_setting_names}
#
# @param [Boolean] memoized
# Whether the method should be memoized
#
# @param [Boolean] sorted
# Whether the return value should be sorted
#
# @param [Boolean] uniqued
# Whether the return value should be uniqued
#
# @param [Boolean] compacted
# Whether the return value should be compacted
#
# @param [Boolean] frozen
# Whether the return value should be frozen
#
# @param [Boolean, Symbol] from_search_paths_aggregate_targets
# If truthy, the method from {Aggregate} that should be used to concatenate build settings from
# {::Pod::AggregateTarget#search_paths_aggregate_target}
#
# @param [Symbol] from_pod_targets_to_link
# If truthy, the `_to_import` values from `BuildSettings#pod_targets_to_link` will be concatenated
#
# @param [Block] implementation
#
# @macro [attach] define_build_settings_method
# @!method $1
#
# The `$1` build setting for the {#target}.
#
# The return value from this method will be: `${1--1}`.
#
def self.define_build_settings_method(method_name, build_setting: false,
memoized: false, sorted: false, uniqued: false, compacted: false, frozen: true,
from_search_paths_aggregate_targets: false, from_pod_targets_to_link: false,
&implementation)
memoized_key = "#{self}##{method_name}".freeze
(@build_settings_names ||= Set.new) << method_name.to_s.upcase if build_setting
raw_method_name = :"_raw_#{method_name}"
define_method(raw_method_name, &implementation)
private(raw_method_name)
dup_before_freeze = frozen && (from_pod_targets_to_link || from_search_paths_aggregate_targets || uniqued || sorted)
define_method(method_name) do
if memoized
@__memoized ||= {}
retval = @__memoized.fetch(memoized_key, :not_found)
return retval if :not_found != retval
end
retval = send(raw_method_name)
if retval.nil?
@__memoized[memoized_key] = retval if memoized
return
end
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(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
retval.uniq! if uniqued
retval.sort! if sorted
retval.freeze if frozen
@__memoized[memoized_key] = retval if memoized
retval
end
end
private_class_method :define_build_settings_method
class << self
#-------------------------------------------------------------------------#
# @!group Public API
# @return [Set<String>] a set of all the build settings names that will
# be present in the #xcconfig
#
attr_reader :build_settings_names
end
#-------------------------------------------------------------------------#
# @!group Public API
# @return [Target]
# The target this build settings object is generating build settings for
#
attr_reader :target
# Initialize a new instance
#
# @param [Target] target
# see {#target}
#
def initialize(target)
@target = target
end
# @return [Xcodeproj::Config]
define_build_settings_method :xcconfig, :memoized => true do
settings = add_inherited_to_plural(to_h)
Xcodeproj::Config.new(settings)
end
# @return [Xcodeproj::Config]
#
# @!visibility private
# @see #__clear__
# @see #xcconfig
def generate
__clear__
xcconfig
end
# Saves the generated xcconfig to the given path
#
# @return [Xcodeproj::Config]
#
# @see #xcconfig
#
# @param [String,Pathname] path
# The path the xcconfig will be saved to
#
def save_as(path)
xcconfig.save_as(path)
end
#-------------------------------------------------------------------------#
# @!group Paths
# @return [String]
define_build_settings_method :pods_build_dir, :build_setting => true do
'${BUILD_DIR}'
end
# @return [String]
define_build_settings_method :pods_configuration_build_dir, :build_setting => true do
'${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)'
end
#-------------------------------------------------------------------------#
# @!group Code Signing
# @return [String]
define_build_settings_method :code_sign_identity, :build_setting => true do
return unless target.requires_frameworks?
return unless target.platform.to_sym == :osx
''
end
#-------------------------------------------------------------------------#
# @!group Frameworks
# @return [Array<String>]
define_build_settings_method :frameworks do
[]
end
# @return [Array<String>]
define_build_settings_method :weak_frameworks do
[]
end
# @return [Array<String>]
define_build_settings_method :framework_search_paths, :build_setting => true, :memoized => true do
framework_search_paths_to_import_developer_frameworks(frameworks)
end
# @param [Array<String>] frameworks
# The list of framework names
#
# @return [Array<String>]
# the `FRAMEWORK_SEARCH_PATHS` needed to import developer frameworks
def framework_search_paths_to_import_developer_frameworks(frameworks)
if frameworks.include?('XCTest') || frameworks.include?('SenTestingKit')
%w[ $(PLATFORM_DIR)/Developer/Library/Frameworks ]
else
[]
end
end
#-------------------------------------------------------------------------#
# @!group Libraries
# @return [Array<String>]
define_build_settings_method :libraries do
[]
end
#-------------------------------------------------------------------------#
# @!group Clang
# @return [Array<String>]
define_build_settings_method :gcc_preprocessor_definitions, :build_setting => true do
%w( COCOAPODS=1 )
end
# @return [Array<String>]
define_build_settings_method :other_cflags, :build_setting => true, :memoized => true do
module_map_files.map { |f| "-fmodule-map-file=#{f}" }
end
# @return [Array<String>]
define_build_settings_method :module_map_files do
[]
end
#-------------------------------------------------------------------------#
# @!group Swift
# @return [Boolean]
# Whether `OTHER_SWIFT_FLAGS` should be generated when the target
# does not use swift.
#
def other_swift_flags_without_swift?
false
end
# @return [Array<String>]
define_build_settings_method :other_swift_flags, :build_setting => true, :memoized => true do
return unless target.uses_swift? || other_swift_flags_without_swift?
flags = %w(-D COCOAPODS)
flags.concat module_map_files.flat_map { |f| ['-Xcc', "-fmodule-map-file=#{f}"] }
flags
end
#-------------------------------------------------------------------------#
# @!group Linking
# @return [Boolean]
define_build_settings_method :requires_objc_linker_flag? do
false
end
# @return [Boolean]
define_build_settings_method :requires_fobjc_arc? do
false
end
# @return [Array<String>]
# the `LD_RUNPATH_SEARCH_PATHS` needed for dynamically linking the {#target}
#
# @param [Boolean] requires_host_target
#
# @param [Boolean] test_bundle
#
def _ld_runpath_search_paths(requires_host_target: false, test_bundle: false)
if target.platform.symbolic_name == :osx
["'@executable_path/../Frameworks'",
test_bundle ? "'@loader_path/../Frameworks'" : "'@loader_path/Frameworks'"]
else
paths = [
"'@executable_path/Frameworks'",
"'@loader_path/Frameworks'",
]
paths << "'@executable_path/../../Frameworks'" if requires_host_target
paths
end
end
private :_ld_runpath_search_paths
# @return [Array<String>]
define_build_settings_method :other_ldflags, :build_setting => true, :memoized => true do
ld_flags = []
ld_flags << '-ObjC' if requires_objc_linker_flag?
if requires_fobjc_arc?
ld_flags << '-fobjc-arc'
end
libraries.each { |l| ld_flags << %(-l"#{l}") }
frameworks.each { |f| ld_flags << '-framework' << %("#{f}") }
weak_frameworks.each { |f| ld_flags << '-weak_framework' << %("#{f}") }
ld_flags
end
#-------------------------------------------------------------------------#
# @!group Private Methods
# Clears all memoized settings.
# @!visibility private
# @return [Void]
def __clear__
@__memoized = nil
end
private
# @return [Hash<String => String|Array<String>>]
def to_h
hash = {}
self.class.build_settings_names.sort.each do |setting|
hash[setting] = public_send(setting.downcase)
end
hash
end
# @return [Hash<String => String>]
def add_inherited_to_plural(hash)
Hash[hash.map do |key, value|
next [key, '$(inherited)'] if value.nil?
if PLURAL_SETTINGS.include?(key)
raise ArgumentError, "#{key} is a plural setting, cannot have #{value.inspect} as its value" unless value.is_a? Array
value = "$(inherited) #{quote_array(value)}"
else
raise ArgumentError, "#{key} is not a plural setting, cannot have #{value.inspect} as its value" unless value.is_a? String
end
[key, value]
end]
end
# @return [Array<String>]
#
# @param [Array<String>] array
#
def quote_array(array)
array.map do |element|
case element
when /\A([\w-]+?)=(.+)\z/
key = Regexp.last_match(1)
value = Regexp.last_match(2)
value = %("#{value}") if value =~ /[^\w\d]/
%(#{key}=#{value})
when /[\$\[\]\ ]/
%("#{element}")
else
element
end
end.join(' ')
end
# @param [Hash] xcconfig_values_by_consumer_by_key
#
# @param [#to_s] attribute
# The name of the attribute being merged
#
# @return [Hash<String, String>]
#
def merged_xcconfigs(xcconfig_values_by_consumer_by_key, attribute)
xcconfig_values_by_consumer_by_key.each_with_object({}) do |(key, values_by_consumer), xcconfig|
uniq_values = values_by_consumer.values.uniq
values_are_bools = uniq_values.all? { |v| v =~ /\A(yes|no)\z/i }
if values_are_bools
# Boolean build settings
if uniq_values.count > 1
UI.warn "Can't merge #{attribute} for pod targets: " \
"#{values_by_consumer.keys.map(&:name)}. Boolean build " \
"setting #{key} has different values."
else
xcconfig[key] = uniq_values.first
end
elsif PLURAL_SETTINGS.include? key
# Plural build settings
xcconfig[key] = uniq_values.join(' ')
elsif uniq_values.count > 1
# Singular build settings
UI.warn "Can't merge #{attribute} for pod targets: " \
"#{values_by_consumer.keys.map(&:name)}. Singular build " \
"setting #{key} has different values."
else
xcconfig[key] = uniq_values.first
end
end
end
# Filters out pod targets whose `specs` are a subset of
# another target's.
#
# @param [Array<PodTarget>] dependent_targets
#
# @return [Array<PodTarget>]
#
def select_maximal_pod_targets(pod_targets)
subset_targets = []
pod_targets.uniq.combination(2) do |a, b|
if (a.specs - b.specs).empty?
subset_targets << a
elsif (b.specs - a.specs).empty?
subset_targets << b
end
end
pod_targets - subset_targets
end
# A subclass that generates build settings for a {PodTarget}
class PodTargetSettings < BuildSettings
#-------------------------------------------------------------------------#
# @!group Public API
# @see BuildSettings.build_settings_names
def self.build_settings_names
@build_settings_names | BuildSettings.build_settings_names
end
# @return [Boolean]
# whether settings are being generated for a test bundle
#
attr_reader :test_xcconfig
alias test_xcconfig? test_xcconfig
# Intializes a new instance
#
# @param [PodTarget] target
# see {#target}
#
# @param [String] configuration_name
# see {#configuration_name}
#
# @param [Boolean] test_xcconfig
# see {#test_xcconfig?}
#
def initialize(target, test_xcconfig)
super(target)
@test_xcconfig = test_xcconfig
end
# @return [Xcodeproj::Xconfig]
define_build_settings_method :xcconfig, :memoized => true do
xcconfig = super()
xcconfig.merge(pod_target_xcconfig)
end
#-------------------------------------------------------------------------#
# @!group Paths
# @return [String]
define_build_settings_method :pods_root, :build_setting => true do
'${SRCROOT}'
end
# @return [String]
define_build_settings_method :pods_target_srcroot, :build_setting => true do
target.pod_target_srcroot
end
#-------------------------------------------------------------------------#
# @!group Frameworks
# @return [Array<String>]
define_build_settings_method :consumer_frameworks, :memoized => true do
spec_consumers.flat_map(&:frameworks)
end
# @return [Array<String>]
define_build_settings_method :frameworks, :memoized => true, :sorted => true, :uniqued => true do
return [] if (!target.requires_frameworks? || target.static_framework?) && !test_xcconfig?
frameworks = vendored_dynamic_frameworks.map { |l| File.basename(l, '.framework') }
frameworks.concat vendored_static_frameworks.map { |l| File.basename(l, '.framework') } unless test_xcconfig?
frameworks.concat consumer_frameworks
frameworks.concat dependent_targets.flat_map { |pt| pt.build_settings.dynamic_frameworks_to_import }
frameworks.concat dependent_targets.flat_map { |pt| pt.build_settings.static_frameworks_to_import } if test_xcconfig?
frameworks
end
# @return [Array<String>]
define_build_settings_method :static_frameworks_to_import, :memoized => true do
static_frameworks_to_import = []
static_frameworks_to_import.concat vendored_static_frameworks.map { |f| File.basename(f, '.framework') } unless target.should_build? && target.requires_frameworks? && !target.static_framework?
static_frameworks_to_import << target.product_basename if target.should_build? && target.requires_frameworks? && target.static_framework?
static_frameworks_to_import
end
# @return [Array<String>]
define_build_settings_method :dynamic_frameworks_to_import, :memoized => true do
dynamic_frameworks_to_import = vendored_dynamic_frameworks.map { |f| File.basename(f, '.framework') }
dynamic_frameworks_to_import << target.product_basename if target.should_build? && target.requires_frameworks? && !target.static_framework?
dynamic_frameworks_to_import.concat consumer_frameworks
dynamic_frameworks_to_import
end
# @return [Array<String>]
define_build_settings_method :weak_frameworks, :memoized => true do
return [] if (!target.requires_frameworks? || target.static_framework?) && !test_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
end
# @return [Array<String>]
define_build_settings_method :frameworks_to_import, :memoized => true, :sorted => true, :uniqued => true do
static_frameworks_to_import + dynamic_frameworks_to_import
end
# @return [Array<String>]
define_build_settings_method :weak_frameworks_to_import, :memoized => true, :sorted => true, :uniqued => true do
[]
end
# @return [Array<String>]
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 framework_search_paths_to_import
paths.delete(target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)) unless test_xcconfig?
paths
end
# @return [Array<String>]
define_build_settings_method :vendored_framework_search_paths, :memoized => true do
file_accessors.flat_map(&:vendored_frameworks).map { |f| File.join '${PODS_ROOT}', f.dirname.relative_path_from(target.sandbox.root) }
end
# @return [Array<String>]
define_build_settings_method :framework_search_paths_to_import, :memoized => true do
paths = framework_search_paths_to_import_developer_frameworks(consumer_frameworks)
paths.concat vendored_framework_search_paths
return paths unless target.requires_frameworks? && target.should_build?
paths + [target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)]
end
# @return [Array<String>]
define_build_settings_method :vendored_static_frameworks, :memoized => true do
file_accessors.flat_map(&:vendored_static_frameworks)
end
# @return [Array<String>]
define_build_settings_method :vendored_dynamic_frameworks, :memoized => true do
file_accessors.flat_map(&:vendored_dynamic_frameworks)
end
#-------------------------------------------------------------------------#
# @!group Libraries
# @return [Array<String>]
define_build_settings_method :libraries, :memoized => true, :sorted => true, :uniqued => true do
return [] if (!target.requires_frameworks? || target.static_framework?) && !test_xcconfig?
libraries = vendored_dynamic_libraries.map { |l| File.basename(l, l.extname).sub(/\Alib/, '') }
libraries.concat spec_consumers.flat_map(&:libraries)
libraries.concat dependent_targets.flat_map { |pt| pt.build_settings.dynamic_libraries_to_import }
libraries.concat dependent_targets.flat_map { |pt| pt.build_settings.static_libraries_to_import } if test_xcconfig?
libraries
end
# @return [Array<String>]
define_build_settings_method :static_libraries_to_import, :memoized => true do
static_libraries_to_import = vendored_static_libraries.map { |l| File.basename(l, l.extname).sub(/\Alib/, '') }
static_libraries_to_import << target.product_basename if target.should_build? && !target.requires_frameworks?
static_libraries_to_import
end
# @return [Array<String>]
define_build_settings_method :dynamic_libraries_to_import, :memoized => true do
vendored_dynamic_libraries.map { |l| File.basename(l, l.extname).sub(/\Alib/, '') } +
spec_consumers.flat_map(&:libraries)
end
# @return [Array<String>]
define_build_settings_method :libraries_to_import, :memoized => true, :sorted => true, :uniqued => true do
static_libraries_to_import + dynamic_libraries_to_import
end
# @return [Array<String>]
define_build_settings_method :library_search_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true do
vendored = vendored_dynamic_library_search_paths.dup
vendored.concat dependent_targets.flat_map { |t| t.build_settings.vendored_dynamic_library_search_paths }
if test_xcconfig?
vendored.concat dependent_targets.flat_map { |t| t.build_settings.library_search_paths_to_import }
else
vendored.delete(target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE))
end
vendored
end
# @return [Array<String>]
define_build_settings_method :vendored_static_libraries, :memoized => true do
file_accessors.flat_map(&:vendored_static_libraries)
end
# @return [Array<String>]
define_build_settings_method :vendored_dynamic_libraries, :memoized => true do
file_accessors.flat_map(&:vendored_dynamic_libraries)
end
# @return [Array<String>]
define_build_settings_method :vendored_static_library_search_paths, :memoized => true do
vendored_static_libraries.map { |f| File.join '${PODS_ROOT}', f.dirname.relative_path_from(target.sandbox.root) }
end
# @return [Array<String>]
define_build_settings_method :vendored_dynamic_library_search_paths, :memoized => true do
vendored_dynamic_libraries.map { |f| File.join '${PODS_ROOT}', f.dirname.relative_path_from(target.sandbox.root) }
end
# @return [Array<String>]
define_build_settings_method :library_search_paths_to_import, :memoized => true do
vendored_library_search_paths = vendored_static_library_search_paths + vendored_dynamic_library_search_paths
return vendored_library_search_paths if target.requires_frameworks? || !target.should_build?
vendored_library_search_paths << target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)
end
#-------------------------------------------------------------------------#
# @!group Clang
# @return [Array<String>]
define_build_settings_method :module_map_files, :memoized => true do
dependent_targets.map { |t| t.build_settings.module_map_file_to_import }.compact.sort
end
# @return [Array<String>]
define_build_settings_method :module_map_file_to_import, :memoized => true do
return unless target.should_build?
return if target.requires_frameworks?
return unless target.defines_module?
if target.uses_swift?
# for swift, we have a custom build phase that copies in the module map, appending the .Swift module
"${PODS_CONFIGURATION_BUILD_DIR}/#{target.label}/#{target.product_module_name}.modulemap"
else
"${PODS_ROOT}/#{target.module_map_path.relative_path_from(target.sandbox.root)}"
end
end
# @return [Array<String>]
define_build_settings_method :header_search_paths, :build_setting => true, :memoized => true, :sorted => true do
target.header_search_paths(test_xcconfig?)
end
#-------------------------------------------------------------------------#
# @!group Swift
# @return [Array<String>]
define_build_settings_method :other_swift_flags, :build_setting => true, :memoized => true do
return unless target.uses_swift?
flags = super()
flags << '-suppress-warnings' if target.inhibit_warnings?
if !target.requires_frameworks? && target.defines_module? && !test_xcconfig?
flags.concat %w( -import-underlying-module -Xcc -fmodule-map-file=${SRCROOT}/${MODULEMAP_FILE} )
end
flags
end
# @return [Array<String>]
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.concat swift_include_paths_to_import if test_xcconfig?
paths
end
# @return [Array<String>]
define_build_settings_method :swift_include_paths_to_import, :memoized => true do
return [] unless target.uses_swift? && !target.requires_frameworks?
[target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)]
end
#-------------------------------------------------------------------------#
# @!group Linking
# @return [Boolean] whether the `-ObjC` linker flag is required.
#
# @note this is only true when generating build settings for a test bundle
#
def requires_objc_linker_flag?
test_xcconfig?
end
# @return [Boolean] whether the `-fobjc-arc` linker flag is required.
#
define_build_settings_method :requires_fobjc_arc?, :memoized => true do
target.podfile.set_arc_compatibility_flag? &&
file_accessors.any? { |fa| fa.spec_consumer.requires_arc? }
end
# @return [Array<String>]
define_build_settings_method :ld_runpath_search_paths, :build_setting => true, :memoized => true do
return unless test_xcconfig?
_ld_runpath_search_paths(:test_bundle => true)
end
#-------------------------------------------------------------------------#
# @!group Packaging
# @return [String]
define_build_settings_method :skip_install, :build_setting => true do
'YES'
end
# @return [String]
define_build_settings_method :product_bundle_identifier, :build_setting => true do
'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}'
end
# @return [String]
define_build_settings_method :configuration_build_dir, :build_setting => true, :memoized => true do
return if test_xcconfig?
target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)
end
#-------------------------------------------------------------------------#
# @!group Target Properties
# @return [Array<PodTarget>]
define_build_settings_method :dependent_targets, :memoized => true do
select_maximal_pod_targets(
if test_xcconfig?
target.all_dependent_targets
else
target.recursive_dependent_targets
end,
)
end
# @return [Hash<String => String>]
define_build_settings_method :pod_target_xcconfig, :memoized => true do
config = {}
spec_consumers.each do |consumer|
config.update(consumer.pod_target_xcconfig) # TODO: resolve conflicts
end
config
end
# Returns the +pod_target_xcconfig+ for the pod target and its spec
# consumers grouped by keys
#
# @return [Hash{String,Hash{Target,String}]
#
def pod_target_xcconfig_values_by_consumer_by_key
spec_consumers.each_with_object({}) do |spec_consumer, hash|
spec_consumer.user_target_xcconfig.each do |k, v|
(hash[k] ||= {})[spec_consumer] = v
end
end
end
# Merges the +pod_target_xcconfig+ for all pod targets into a
# single hash and warns on conflicting definitions.
#
# @return [Hash{String, String}]
#
define_build_settings_method :merged_pod_target_xcconfigs, :memoized => true do
merged_xcconfigs(pod_target_xcconfig_values_by_consumer_by_key, :pod_target_xcconfig)
end
# @return [Array<Sandbox::FileAccessor>]
define_build_settings_method :file_accessors, :memoized => true do
target.file_accessors.select { |fa| fa.spec.test_specification? == test_xcconfig? }
end
# @return [Array<Specification::Consumer>]
define_build_settings_method :spec_consumers, :memoized => true do
target.spec_consumers.select { |c| c.spec.test_specification? == test_xcconfig? }
end
#-------------------------------------------------------------------------#
# @!group Private Methods
def __clear__
super
dependent_targets.each { |pt| pt.build_settings.__clear__ }
end
end
# A subclass that generates build settings for a `PodTarget`
class AggregateTargetSettings < BuildSettings
#-------------------------------------------------------------------------#
# @!group Public API
# @see BuildSettings.build_settings_names
def self.build_settings_names
@build_settings_names | BuildSettings.build_settings_names
end
# @return [String]
# The build configuration these settings will be used for
attr_reader :configuration_name
# Intializes a new instance
#
# @param [AggregateTarget] target
# see {#target}
#
# @param [String] configuration_name
# see {#configuration_name}
#
def initialize(target, configuration_name)
super(target)
@configuration_name = configuration_name
end
# @return [Xcodeproj::Config] xcconfig
define_build_settings_method :xcconfig, :memoized => true do
xcconfig = super()
xcconfig.merge(merged_user_target_xcconfigs)
end
#-------------------------------------------------------------------------#
# @!group Paths
# @return [String]
define_build_settings_method :pods_podfile_dir_path, :build_setting => true, :memoized => true do
target.podfile_dir_relative_path
end
# @return [String]
define_build_settings_method :pods_root, :build_setting => true, :memoized => true do
target.relative_pods_root
end
#-------------------------------------------------------------------------#
# @!group Frameworks
# @return [Array<String>]
define_build_settings_method :frameworks, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets_to_link => true, :from_search_paths_aggregate_targets => :dynamic_frameworks_to_import do
[]
end
# @return [Array<String>]
define_build_settings_method :weak_frameworks, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets_to_link => true, :from_search_paths_aggregate_targets => :weak_frameworks do
[]
end
# @return [Array<String>]
define_build_settings_method :framework_search_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets_to_link => true, :from_search_paths_aggregate_targets => :framework_search_paths_to_import do
[]
end
#-------------------------------------------------------------------------#
# @!group Libraries
# @return [Array<String>]
define_build_settings_method :libraries, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets_to_link => true, :from_search_paths_aggregate_targets => :dynamic_libraries_to_import do
[]
end
# @return [Array<String>]
define_build_settings_method :library_search_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets_to_link => true, :from_search_paths_aggregate_targets => :vendored_dynamic_library_search_paths do
[]
end
#-------------------------------------------------------------------------#
# @!group Clang
# @return [Array<String>]
define_build_settings_method :header_search_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true do
paths = []
if !target.requires_frameworks? || !pod_targets.all?(&:should_build?)
paths.concat target.sandbox.public_headers.search_paths(target.platform)
end
paths.concat target.search_paths_aggregate_targets.flat_map { |at| at.build_settings(configuration_name).header_search_paths }
paths
end
# @return [Array<String>]
define_build_settings_method :other_cflags, :build_setting => true, :memoized => true do
flags = super()
flags +
header_search_paths.flat_map { |p| ['-isystem', p] } +
framework_header_paths_for_iquote.flat_map { |p| ['-iquote', p] }
end
# @return [Array<String>]
define_build_settings_method :framework_header_paths_for_iquote, :memoized => true, :sorted => true, :uniqued => true do
paths = pod_targets.
select { |pt| pt.should_build? && pt.requires_frameworks? }.
map { |pt| "#{pt.build_product_path}/Headers" }
paths.concat target.search_paths_aggregate_targets.flat_map { |at| at.build_settings(configuration_name).framework_header_paths_for_iquote }
paths
end
# @return [Array<String>]
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 }
end
#-------------------------------------------------------------------------#
# @!group Swift
# @see BuildSettings#other_swift_flags_without_swift?
def other_swift_flags_without_swift?
module_map_files.any?
end
# @return [Array<String>]
define_build_settings_method :swift_include_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets_to_link => true, :from_search_paths_aggregate_targets => :swift_include_paths_to_import do
[]
end
# @return [String]
define_build_settings_method :always_embed_swift_standard_libraries, :build_setting => true, :memoized => true do
return unless must_embed_swift?
return if target_swift_version < EMBED_STANDARD_LIBRARIES_MINIMUM_VERSION
'YES'
end
# @return [String]
define_build_settings_method :embedded_content_contains_swift, :build_setting => true, :memoized => true do
return unless must_embed_swift?
return if target_swift_version >= EMBED_STANDARD_LIBRARIES_MINIMUM_VERSION
'YES'
end
# @return [Boolean]
define_build_settings_method :must_embed_swift?, :memoized => true do
!target.requires_host_target? && pod_targets.any?(&:uses_swift?)
end
#-------------------------------------------------------------------------#
# @!group Linking
# @return [Array<String>]
define_build_settings_method :ld_runpath_search_paths, :build_setting => true, :memoized => true, :uniqued => true do
return unless target.requires_frameworks? || any_vendored_dynamic_artifacts?
symbol_type = target.user_targets.map(&:symbol_type).uniq.first
test_bundle = symbol_type == :octest_bundle || symbol_type == :unit_test_bundle || symbol_type == :ui_test_bundle
_ld_runpath_search_paths(:requires_host_target => target.requires_host_target?, :test_bundle => test_bundle)
end
# @return [Boolean]
define_build_settings_method :any_vendored_dynamic_artifacts?, :memoized => true do
pod_targets.any? do |pt|
pt.file_accessors.any? do |fa|
fa.vendored_dynamic_artifacts.any?
end
end
end
# @return [Boolean]
define_build_settings_method :requires_objc_linker_flag?, :memoized => true do
includes_static_libs = !target.requires_frameworks?
includes_static_libs || pod_targets.flat_map(&:file_accessors).any? { |fa| !fa.vendored_static_artifacts.empty? }
end
# @return [Boolean]
define_build_settings_method :requires_fobjc_arc?, :memoized => true do
target.podfile.set_arc_compatibility_flag? &&
target.spec_consumers.any?(&:requires_arc?)
end
#-------------------------------------------------------------------------#
# @!group Target Properties
# @return [Version] the SWIFT_VERSION of the target being integrated
#
define_build_settings_method :target_swift_version, :memoized => true, :frozen => false do
swift_version = target.target_definition.swift_version
swift_version = nil if swift_version.blank?
Version.new(swift_version)
end
EMBED_STANDARD_LIBRARIES_MINIMUM_VERSION = Version.new('2.3')
private_constant :EMBED_STANDARD_LIBRARIES_MINIMUM_VERSION
# Returns the {PodTarget}s which are active for the current
# configuration name.
#
# @return [Array<PodTarget>]
#
define_build_settings_method :pod_targets, :memoized => true do
target.pod_targets_for_build_configuration(configuration_name)
end
# @return [Array<PodTarget>]
define_build_settings_method :pod_targets_to_link, :memoized => true do
pod_targets -
target.search_paths_aggregate_targets.flat_map { |at| at.build_settings(configuration_name).pod_targets_to_link }
end
# @return [Array<PodTarget>]
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)
end
# Returns the +user_target_xcconfig+ for all pod targets and their spec
# consumers grouped by keys
#
# @return [Hash{String,Hash{Target,String}]
#
def user_target_xcconfig_values_by_consumer_by_key
pod_targets.each_with_object({}) do |target, hash|
target.spec_consumers.each do |spec_consumer|
spec_consumer.user_target_xcconfig.each do |k, v|
(hash[k] ||= {})[spec_consumer] = v
end
end
end
end
# Merges the +user_target_xcconfig+ for all pod targets into a
# single hash and warns on conflicting definitions.
#
# @return [Hash{String, String}]
#
define_build_settings_method :merged_user_target_xcconfigs, :memoized => true do
merged_xcconfigs(user_target_xcconfig_values_by_consumer_by_key, :user_target_xcconfig)
end
#-------------------------------------------------------------------------#
# @!group Private Methods
def __clear__
super
pod_targets.each { |pt| pt.build_settings.__clear__ }
target.search_paths_aggregate_targets.each { |at| at.build_settings(configuration_name).__clear__ }
end
end
end
end
end
......@@ -275,7 +275,7 @@ module Pod
accessor.resources.flat_map { |res| "${PODS_ROOT}/#{res.relative_path_from(sandbox.project.path.dirname)}" }
end
resource_bundles = accessors.flat_map do |accessor|
prefix = Generator::XCConfig::XCConfigHelper::CONFIGURATION_BUILD_DIR_VARIABLE
prefix = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE
prefix = configuration_build_dir unless accessor.spec.test_specification?
accessor.resource_bundles.keys.map { |name| "#{prefix}/#{name.shellescape}.bundle" }
end
......@@ -535,7 +535,7 @@ module Pod
#
# @return [String] The absolute path to the configuration build dir
#
def configuration_build_dir(dir = Generator::XCConfig::XCConfigHelper::CONFIGURATION_BUILD_DIR_VARIABLE)
def configuration_build_dir(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE)
"#{dir}/#{label}"
end
......@@ -544,7 +544,7 @@ module Pod
#
# @return [String] The absolute path to the build product
#
def build_product_path(dir = Generator::XCConfig::XCConfigHelper::CONFIGURATION_BUILD_DIR_VARIABLE)
def build_product_path(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE)
"#{configuration_build_dir(dir)}/#{product_name}"
end
......@@ -610,5 +610,9 @@ module Pod
Specification.root_name(dependency.name) == pod_name
end
end
def create_build_settings
BuildSettings::PodTargetSettings.new(self, false)
end
end
end
Subproject commit f85066239cc102e9386b2417e7638512d2b696eb
Subproject commit 2faa5dd550afc3158b119ebc1fe90eea5fa15825
......@@ -146,7 +146,7 @@ def fixture_pod_target_with_specs(specs, host_requires_frameworks = false, user_
target_definitions, file_accessors, scope_suffix)
end
def fixture_aggregate_target(pod_targets = [], host_requires_frameworks = false, user_build_configurations = {},
def fixture_aggregate_target(pod_targets = [], host_requires_frameworks = false, user_build_configurations = Pod::Target::DEFAULT_BUILD_CONFIGURATIONS,
archs = [], platform = Pod::Platform.new(:ios, '6.0'), target_definition = nil)
target_definition ||= pod_targets.flat_map(&:target_definitions).first || fixture_target_definition
Pod::AggregateTarget.new(config.sandbox, host_requires_frameworks, user_build_configurations, archs, platform,
......
require File.expand_path('../../../../spec_helper', __FILE__)
module Pod
module Generator
module XCConfig
describe XCConfigHelper do
before do
@sut = XCConfigHelper
end
#---------------------------------------------------------------------#
describe '::default_ld_flags' do
it 'returns the default linker flags' do
podfile = stub('podfile', :set_arc_compatibility_flag? => false)
target = stub('target', :podfile => podfile)
result = @sut.default_ld_flags(target)
result.should == ''
result = @sut.default_ld_flags(target, true)
result.should == '-ObjC'
end
it 'includes the ARC compatibility flag if required by the Podfile' do
podfile = stub('podfile', :set_arc_compatibility_flag? => true)
spec_consumer = stub('spec_consumer', :requires_arc? => true)
target = stub('target', :podfile => podfile, :spec_consumers => [spec_consumer])
result = @sut.default_ld_flags(target)
result.should == '-fobjc-arc'
result = @sut.default_ld_flags(target, true)
result.should == '-ObjC -fobjc-arc'
end
end
#---------------------------------------------------------------------#
describe '::quote' do
it 'quotes strings' do
result = @sut.quote(%w(string1 string2))
result.should == '"string1" "string2"'
end
it 'inserts an optional string and then the normal quoted string' do
result = @sut.quote(%w(string1 string2), '-isystem')
result.should == '-isystem "string1" -isystem "string2"'
end
end
#---------------------------------------------------------------------#
describe '::add_spec_build_settings_to_xcconfig' do
it 'adds the libraries of the xcconfig' do
xcconfig = Xcodeproj::Config.new
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => ['xml2'],
:frameworks => [],
:weak_frameworks => [],
:platform_name => :ios,
)
@sut.add_spec_build_settings_to_xcconfig(consumer, xcconfig)
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-l"xml2"'
end
it 'check that subspec subsets are removed from frameworks search paths' do
target1 = stub('target1',
:specs => %w(A, B),
:should_build? => true,
:requires_frameworks? => true,
:configuration_build_dir => 'AB',
:uses_swift? => false,
)
target2 = stub('target2',
:specs => ['B'],
:should_build? => true,
:requires_frameworks? => true,
:configuration_build_dir => 'B',
:uses_swift? => false,
)
dependent_targets = [target1, target2]
build_settings = @sut.search_paths_for_dependent_targets(nil, dependent_targets)
build_settings['FRAMEWORK_SEARCH_PATHS'].should == '"AB"'
end
it 'adds the frameworks search paths once if there are duplicated targets' do
target = stub(
:specs => %w(A, B),
:should_build? => true,
:requires_frameworks? => true,
:configuration_build_dir => 'AB',
)
dependent_targets = [target, target]
build_settings = @sut.search_paths_for_dependent_targets(nil, dependent_targets)
build_settings['FRAMEWORK_SEARCH_PATHS'].should == '"AB"'
end
it 'adds the libraries of the xcconfig for a static framework' do
spec = stub('spec', :test_specification? => false)
target_definition = stub('target_definition', :inheritance => 'search_paths')
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => ['xml2'],
:frameworks => [],
:weak_frameworks => [],
:platform_name => :ios,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [],
:vendored_dynamic_frameworks => [],
:vendored_static_libraries => [],
:vendored_dynamic_libraries => [],
)
pod_target = stub('pod_target',
:name => 'BananaLib',
:sandbox => config.sandbox,
:should_build? => true,
:requires_frameworks? => true,
:static_framework? => true,
:dependent_targets => [],
:file_accessors => [file_accessor],
)
pod_targets = [pod_target]
aggregate_target = stub('aggregate_target',
:target_definition => target_definition,
:pod_targets => pod_targets,
:search_paths_aggregate_targets => [],
:pod_targets_to_link => pod_targets,
)
xcconfig = Xcodeproj::Config.new
@sut.generate_vendored_build_settings(aggregate_target, pod_targets, xcconfig)
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-l"xml2"'
end
it 'checks OTHER_LDFLAGS and FRAMEWORK_SEARCH_PATHS for a vendored dependencies to a static framework' do
spec = stub('spec', :test_specification? => false)
target_definition = stub('target_definition', :inheritance => 'search_paths')
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => ['xml2'],
:frameworks => [],
:weak_frameworks => [],
:platform_name => :ios,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
dep_target = stub('dep_target',
:name => 'BananaLib',
:sandbox => config.sandbox,
:should_build? => false,
:requires_frameworks? => true,
:static_framework? => false,
:dependent_targets => [],
:file_accessors => [file_accessor],
)
dep_targets = [dep_target]
target = stub('target',
:target_definition => target_definition,
:pod_targets => dep_targets,
:search_paths_aggregate_targets => [],
:static_framework => true,
:pod_targets_to_link => dep_targets,
)
xcconfig = Xcodeproj::Config.new
@sut.generate_vendored_build_settings(target, dep_targets, xcconfig, true)
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "StaticFramework" -framework "VendoredFramework"'
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '"${PODS_ROOT}/."'
end
it 'quotes OTHER_LDFLAGS to properly handle spaces' do
framework_path = config.sandbox.root + 'Sample/Framework with Spaces.framework'
library_path = config.sandbox.root + 'Sample/libSample Lib.a'
xcconfig = Xcodeproj::Config.new
@sut.add_framework_build_settings(framework_path, xcconfig, config.sandbox.root)
@sut.add_library_build_settings(library_path, xcconfig, config.sandbox.root)
hash_config = xcconfig.to_hash
hash_config['OTHER_LDFLAGS'].should == '-l"Sample Lib" -framework "Framework with Spaces"'
end
it 'check that include_ld_flags being false doesnt generate OTHER_LDFLAGS' do
spec = stub('spec', :test_specification? => false)
target_definition = stub('target_definition', :inheritance => 'search_paths')
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => ['xml2'],
:frameworks => [],
:weak_frameworks => [],
:platform_name => :ios,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
dep_target = stub('dep_target',
:name => 'BananaLib',
:sandbox => config.sandbox,
:should_build? => false,
:requires_frameworks? => true,
:static_framework? => false,
:dependent_targets => [],
:file_accessors => [file_accessor],
)
dep_targets = [dep_target]
target = stub('target',
:target_definition => target_definition,
:pod_targets => dep_targets,
:search_paths_aggregate_targets => [],
)
xcconfig = Xcodeproj::Config.new
@sut.generate_vendored_build_settings(target, dep_targets, xcconfig, false)
xcconfig.to_hash['OTHER_LDFLAGS'].should.nil?
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '"${PODS_ROOT}/."'
end
it 'makes sure setting from search_paths get propagated for static frameworks' do
target_definition = stub('target_definition', :inheritance => 'search_paths')
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => ['xml2'],
:frameworks => ['Foo'],
:weak_frameworks => [],
:platform_name => :ios,
)
file_accessor = stub('file_accessor',
:spec_consumer => consumer,
:vendored_static_frameworks => [],
:vendored_dynamic_frameworks => [],
:vendored_static_libraries => [],
:vendored_dynamic_libraries => [],
)
pod_target = stub('pod_target',
:name => 'BananaLib',
:sandbox => config.sandbox,
:should_build? => true,
:requires_frameworks? => true,
:static_framework? => true,
:dependent_targets => [],
:file_accessors => [file_accessor],
:product_basename => 'Foo',
)
pod_targets = [pod_target]
aggregate_target = stub('aggregate_target',
:target_definition => target_definition,
:pod_targets => pod_targets,
:search_paths_aggregate_targets => [],
)
test_aggregate_target = stub('test_aggregate_target',
:target_definition => target_definition,
:pod_targets => [],
:search_paths_aggregate_targets => [aggregate_target],
:requires_frameworks? => true,
)
xcconfig = Xcodeproj::Config.new
@sut.generate_other_ld_flags(test_aggregate_target, [], xcconfig)
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-framework "Foo"'
end
it 'makes sure setting from search_paths dont propagate for static frameworks when static linking' do
target_definition = stub('target_definition', :inheritance => 'search_paths')
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => ['xml2'],
:frameworks => ['Foo'],
:weak_frameworks => [],
:platform_name => :ios,
)
file_accessor = stub('file_accessor',
:spec_consumer => consumer,
:vendored_static_frameworks => [],
:vendored_dynamic_frameworks => [],
:vendored_static_libraries => [],
:vendored_dynamic_libraries => [],
)
pod_target = stub('pod_target',
:name => 'BananaLib',
:sandbox => config.sandbox,
:should_build? => true,
:requires_frameworks? => false,
:static_framework? => true,
:dependent_targets => [],
:file_accessors => [file_accessor],
:product_basename => 'Foo',
)
pod_targets = [pod_target]
aggregate_target = stub('aggregate_target',
:target_definition => target_definition,
:pod_targets => pod_targets,
:search_paths_aggregate_targets => [],
)
test_aggregate_target = stub('test_aggregate_target',
:target_definition => target_definition,
:pod_targets => [],
:search_paths_aggregate_targets => [aggregate_target],
:requires_frameworks? => false,
)
xcconfig = Xcodeproj::Config.new
@sut.generate_other_ld_flags(test_aggregate_target, [], xcconfig)
xcconfig.to_hash['OTHER_LDFLAGS'].should.be.nil
end
it 'includes HEADER_SEARCH_PATHS from search paths' do
xcconfig = Xcodeproj::Config.new
spec_consumer = stub('spec_consumer', :user_target_xcconfig => { 'HEADER_SEARCH_PATHS' => 'my/path' })
pod_target = stub('pod_target', :spec_consumers => [spec_consumer])
search_path_target = stub('search_path_target',
:pod_targets_for_build_configuration => [pod_target],
:pod_targets => [pod_target],
)
@sut.propagate_header_search_paths_from_search_paths(search_path_target, xcconfig)
xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '$(inherited) my/path'
end
it 'adds the frameworks of the xcconfig' do
xcconfig = Xcodeproj::Config.new
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => [],
:frameworks => ['CoreAnimation'],
:weak_frameworks => [],
:platform_name => :ios,
)
@sut.add_spec_build_settings_to_xcconfig(consumer, xcconfig)
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-framework "CoreAnimation"'
end
it 'adds the weak frameworks of the xcconfig' do
xcconfig = Xcodeproj::Config.new
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => [],
:frameworks => [],
:weak_frameworks => ['iAd'],
:platform_name => :ios,
)
@sut.add_spec_build_settings_to_xcconfig(consumer, xcconfig)
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-weak_framework "iAd"'
end
it 'adds the ios developer frameworks search paths if needed' do
xcconfig = Xcodeproj::Config.new
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => [],
:frameworks => ['SenTestingKit'],
:weak_frameworks => [],
:platform_name => :ios,
)
@sut.add_spec_build_settings_to_xcconfig(consumer, xcconfig)
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.not.include('SDKROOT')
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.not.include('DEVELOPER_LIBRARY_DIR')
end
it 'adds the osx developer frameworks search paths if needed' do
xcconfig = Xcodeproj::Config.new
consumer = stub('consumer',
:pod_target_xcconfig => {},
:libraries => [],
:frameworks => ['SenTestingKit'],
:weak_frameworks => [],
:platform_name => :osx,
)
@sut.add_spec_build_settings_to_xcconfig(consumer, xcconfig)
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.not.include('DEVELOPER_LIBRARY_DIR')
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.not.include('SDKROOT')
end
end
#---------------------------------------------------------------------#
describe '::add_framework_build_settings' do
it 'adds the build settings of a framework to the given xcconfig' do
framework_path = config.sandbox.root + 'Parse/Parse.framework'
xcconfig = Xcodeproj::Config.new
@sut.add_framework_build_settings(framework_path, xcconfig, config.sandbox.root)
hash_config = xcconfig.to_hash
hash_config['OTHER_LDFLAGS'].should == '-framework "Parse"'
hash_config['FRAMEWORK_SEARCH_PATHS'].should == '"${PODS_ROOT}/Parse"'
end
it "doesn't override existing linker flags" do
framework_path = config.sandbox.root + 'Parse/Parse.framework'
xcconfig = Xcodeproj::Config.new('OTHER_LDFLAGS' => '-framework CoreAnimation')
@sut.add_framework_build_settings(framework_path, xcconfig, config.sandbox.root)
hash_config = xcconfig.to_hash
hash_config['OTHER_LDFLAGS'].should == '-framework "CoreAnimation" -framework "Parse"'
end
it "doesn't override existing frameworks search paths" do
framework_path = config.sandbox.root + 'Parse/Parse.framework'
xcconfig = Xcodeproj::Config.new('FRAMEWORK_SEARCH_PATHS' => '"path/to/frameworks"')
@sut.add_framework_build_settings(framework_path, xcconfig, config.sandbox.root)
hash_config = xcconfig.to_hash
hash_config['FRAMEWORK_SEARCH_PATHS'].should == '"path/to/frameworks" "${PODS_ROOT}/Parse"'
end
end
#---------------------------------------------------------------------#
describe '::add_library_build_settings' do
it 'adds the build settings of a framework to the given xcconfig' do
path = config.sandbox.root + 'MapBox/Proj4/libProj4.a'
xcconfig = Xcodeproj::Config.new
@sut.add_library_build_settings(path, xcconfig, config.sandbox.root)
hash_config = xcconfig.to_hash
hash_config['OTHER_LDFLAGS'].should == '-l"Proj4"'
hash_config['LIBRARY_SEARCH_PATHS'].should == '"${PODS_ROOT}/MapBox/Proj4"'
end
it 'adds dylib build settings to the given xcconfig' do
path = config.sandbox.root + 'MapBox/Proj4/libProj4.dylib'
xcconfig = Xcodeproj::Config.new
@sut.add_library_build_settings(path, xcconfig, config.sandbox.root)
hash_config = xcconfig.to_hash
hash_config['OTHER_LDFLAGS'].should == '-l"Proj4"'
hash_config['LIBRARY_SEARCH_PATHS'].should == '"${PODS_ROOT}/MapBox/Proj4"'
end
end
#---------------------------------------------------------------------#
describe '::add_developers_frameworks_if_needed' do
it 'adds the developer frameworks search paths to the xcconfig if SenTestingKit has been detected' do
xcconfig = Xcodeproj::Config.new('OTHER_LDFLAGS' => '-framework SenTestingKit')
@sut.add_developers_frameworks_if_needed(xcconfig)
frameworks_search_paths = xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS']
frameworks_search_paths.should.include?('$(inherited)')
frameworks_search_paths.should.not.include?('"$(SDKROOT)/Developer/Library/Frameworks"')
frameworks_search_paths.should.not.include?('"$(DEVELOPER_LIBRARY_DIR)/Frameworks"')
end
it 'adds the developer frameworks search paths to the xcconfig if XCTest has been detected' do
xcconfig = Xcodeproj::Config.new('OTHER_LDFLAGS' => '-framework XCTest')
@sut.add_developers_frameworks_if_needed(xcconfig)
frameworks_search_paths = xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS']
frameworks_search_paths.should.include?('$(inherited)')
frameworks_search_paths.should.not.include?('"$(SDKROOT)/Developer/Library/Frameworks"')
frameworks_path = '"$(PLATFORM_DIR)/Developer/Library/Frameworks"'
frameworks_search_paths.should.include?(frameworks_path)
frameworks_search_paths.should.not.include?('"$(DEVELOPER_LIBRARY_DIR)/Frameworks"')
end
end
#---------------------------------------------------------------------#
describe '::add_language_specific_settings' do
it 'does not add OTHER_SWIFT_FLAGS to the xcconfig if the target does not use swift' do
target = stub('target', :uses_swift? => false)
xcconfig = Xcodeproj::Config.new
@sut.add_language_specific_settings(target, xcconfig)
other_swift_flags = xcconfig.to_hash['OTHER_SWIFT_FLAGS']
other_swift_flags.should.nil?
end
it 'does not add the -suppress-warnings flag to the xcconfig if the target uses swift, but does not inhibit warnings' do
target = stub('target', :uses_swift? => true, :inhibit_warnings? => false)
xcconfig = Xcodeproj::Config.new
@sut.add_language_specific_settings(target, xcconfig)
other_swift_flags = xcconfig.to_hash['OTHER_SWIFT_FLAGS']
other_swift_flags.should.not.include?('-suppress-warnings')
end
it 'adds the -suppress-warnings flag to the xcconfig if the target uses swift and inhibits warnings' do
target = stub('target', :uses_swift? => true, :inhibit_warnings? => true)
xcconfig = Xcodeproj::Config.new
@sut.add_language_specific_settings(target, xcconfig)
other_swift_flags = xcconfig.to_hash['OTHER_SWIFT_FLAGS']
other_swift_flags.should.include?('-suppress-warnings')
end
end
#---------------------------------------------------------------------#
describe 'concerning settings for file accessors' do
it 'does not propagate framework or libraries from a test specification to an aggregate target' do
spec = stub('spec', :test_specification? => true)
consumer = stub('consumer',
:libraries => ['xml2'],
:frameworks => ['XCTest'],
:weak_frameworks => [],
:spec => spec,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
pod_target = stub('pod_target',
:file_accessors => [file_accessor],
:requires_frameworks? => true,
:dependent_targets => [],
:sandbox => config.sandbox,
)
target_definition = stub('target_definition', :inheritance => 'complete')
aggregate_target = stub('aggregate_target', :target_definition => target_definition)
xcconfig = Xcodeproj::Config.new
@sut.add_settings_for_file_accessors_of_target(aggregate_target, pod_target, xcconfig)
xcconfig.to_hash['OTHER_LDFLAGS'].should.be.nil
end
it 'propagates correct frameworks or libraries to both test and non test xcconfigs' do
spec = stub('spec', :test_specification? => false)
consumer = stub('consumer',
:libraries => [],
:frameworks => [],
:weak_frameworks => [],
:spec => spec,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
test_spec = stub('test_spec', :test_specification? => true)
test_consumer = stub('test_consumer',
:libraries => ['xml2'],
:frameworks => ['XCTest'],
:weak_frameworks => [],
:spec => test_spec,
)
test_file_accessor = stub('test_file_accessor',
:spec => test_spec,
:spec_consumer => test_consumer,
:vendored_static_frameworks => [],
:vendored_static_libraries => [],
:vendored_dynamic_frameworks => [],
:vendored_dynamic_libraries => [],
)
pod_target = stub('pod_target',
:file_accessors => [file_accessor, test_file_accessor],
:requires_frameworks? => true,
:dependent_targets => [],
:sandbox => config.sandbox,
)
xcconfig = Xcodeproj::Config.new
@sut.add_settings_for_file_accessors_of_target(nil, pod_target, xcconfig, true, false)
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-l"StaticLibrary" -l"VendoredDyld" -framework "StaticFramework" -framework "VendoredFramework"'
test_xcconfig = Xcodeproj::Config.new
@sut.add_settings_for_file_accessors_of_target(nil, pod_target, test_xcconfig, true, true)
test_xcconfig.to_hash['OTHER_LDFLAGS'].should == '-l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "StaticFramework" -framework "VendoredFramework" -framework "XCTest"'
end
it 'does propagate framework or libraries from a non test specification to an aggregate target' do
spec = stub('spec', :test_specification? => false)
consumer = stub('consumer',
:libraries => ['xml2'],
:frameworks => ['XCTest'],
:weak_frameworks => [],
:spec => spec,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
pod_target = stub('pod_target',
:file_accessors => [file_accessor],
:requires_frameworks? => true,
:dependent_targets => [],
:sandbox => config.sandbox,
)
target_definition = stub('target_definition', :inheritance => 'complete')
aggregate_target = stub('aggregate_target', :target_definition => target_definition)
xcconfig = Xcodeproj::Config.new
@sut.add_settings_for_file_accessors_of_target(aggregate_target, pod_target, xcconfig)
xcconfig.to_hash['OTHER_LDFLAGS'].should.be == '-l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "StaticFramework" -framework "VendoredFramework" -framework "XCTest"'
end
it 'does propagate framework or libraries to a nil aggregate target' do
spec = stub('spec', :test_specification? => false)
consumer = stub('consumer',
:libraries => ['xml2'],
:frameworks => ['XCTest'],
:weak_frameworks => [],
:spec => spec,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
pod_target = stub('pod_target',
:file_accessors => [file_accessor],
:requires_frameworks? => true,
:dependent_targets => [],
:sandbox => config.sandbox,
)
xcconfig = Xcodeproj::Config.new
@sut.add_settings_for_file_accessors_of_target(nil, pod_target, xcconfig)
xcconfig.to_hash['OTHER_LDFLAGS'].should.be == '-l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "StaticFramework" -framework "VendoredFramework" -framework "XCTest"'
end
end
describe 'for proper other ld flags' do
def stub_aggregate_target(pod_targets, target_definition = nil, search_paths_aggregate_targets: [])
target_definition.stubs(:abstract? => false) unless target_definition.respond_to?(:abstract?)
fixture_aggregate_target(pod_targets, false, {}, [], Platform.ios, target_definition).tap do |aggregate_target|
aggregate_target.search_paths_aggregate_targets.concat(search_paths_aggregate_targets).freeze
end
end
before do
@root = fixture('banana-lib')
@path_list = Sandbox::PathList.new(@root)
@spec = fixture_spec('banana-lib/BananaLib.podspec')
@spec_consumer = @spec.consumer(:ios)
@accessor = Pod::Sandbox::FileAccessor.new(@path_list, @spec_consumer)
end
it 'should not include static framework other ld flags when inheriting search paths' do
target_definition = stub('target_definition', :inheritance => 'search_paths')
aggregate_target = stub_aggregate_target([], target_definition)
pod_target = stub('pod_target', :sandbox => config.sandbox)
xcconfig = Xcodeproj::Config.new
@sut.add_static_dependency_build_settings(aggregate_target, pod_target, xcconfig, @accessor, true)
xcconfig.to_hash['LIBRARY_SEARCH_PATHS'].should == '"${PODS_ROOT}/../../spec/fixtures/banana-lib"'
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '"${PODS_ROOT}/../../spec/fixtures/banana-lib"'
xcconfig.to_hash['OTHER_LDFLAGS'].should.be.nil
end
it 'should include static framework other ld flags when inheriting search paths but explicitly declared' do
target_definition = stub('target_definition', :inheritance => 'search_paths')
pod_target = stub('pod_target', :name => 'BananaLib', :sandbox => config.sandbox)
aggregate_target = stub_aggregate_target([pod_target], target_definition)
xcconfig = Xcodeproj::Config.new
@sut.add_static_dependency_build_settings(aggregate_target, pod_target, xcconfig, @accessor, true)
xcconfig.to_hash['LIBRARY_SEARCH_PATHS'].should == '"${PODS_ROOT}/../../spec/fixtures/banana-lib"'
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '"${PODS_ROOT}/../../spec/fixtures/banana-lib"'
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-l"Bananalib" -framework "Bananalib"'
end
it 'should include static framework other ld flags when not inheriting search paths' do
target_definition = stub('target_definition', :inheritance => 'complete')
aggregate_target = stub_aggregate_target([], target_definition)
pod_target = stub('pod_target', :sandbox => config.sandbox)
xcconfig = Xcodeproj::Config.new
@sut.add_static_dependency_build_settings(aggregate_target, pod_target, xcconfig, @accessor, true)
xcconfig.to_hash['LIBRARY_SEARCH_PATHS'].should == '"${PODS_ROOT}/../../spec/fixtures/banana-lib"'
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '"${PODS_ROOT}/../../spec/fixtures/banana-lib"'
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-l"Bananalib" -framework "Bananalib"'
end
it 'should include static framework for pod targets' do
pod_target = stub('pod_target', :sandbox => config.sandbox)
xcconfig = Xcodeproj::Config.new
@sut.add_static_dependency_build_settings(nil, pod_target, xcconfig, @accessor, true)
xcconfig.to_hash['LIBRARY_SEARCH_PATHS'].should == '"${PODS_ROOT}/../../spec/fixtures/banana-lib"'
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '"${PODS_ROOT}/../../spec/fixtures/banana-lib"'
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-l"Bananalib" -framework "Bananalib"'
end
it 'should link static dependency for pod targets' do
pod_target = stub('pod_target', :name => 'BananaLib', :sandbox => config.sandbox)
@sut.links_dependency?(nil, pod_target).should.be.true
end
it 'should link static dependency when target explicitly specifies it' do
target_definition = stub('target_definition', :inheritance => 'complete')
pod_target = stub('pod_target', :name => 'BananaLib', :sandbox => config.sandbox)
aggregate_target = stub_aggregate_target([pod_target], target_definition)
@sut.links_dependency?(aggregate_target, pod_target).should.be.true
end
it 'should link static dependency when target explicitly specifies it even with search paths' do
target_definition = stub('target_definition', :inheritance => 'search_paths')
pod_target = stub('pod_target', :name => 'BananaLib', :sandbox => config.sandbox)
aggregate_target = stub_aggregate_target([pod_target], target_definition)
@sut.links_dependency?(aggregate_target, pod_target).should.be.true
end
it 'should not link static dependency when inheriting search paths and parent includes dependency' do
parent_target_definition = stub
child_target_definition = stub('child_target_definition', :inheritance => 'search_paths')
pod_target = stub('pod_target', :name => 'BananaLib', :sandbox => config.sandbox)
parent_aggregate_target = stub_aggregate_target([pod_target], parent_target_definition)
child_aggregate_target = stub_aggregate_target([], child_target_definition, :search_paths_aggregate_targets => [parent_aggregate_target])
@sut.links_dependency?(child_aggregate_target, pod_target).should.be.false
end
it 'should link static transitive dependencies if the parent does not link them' do
child_pod_target = stub('child_pod_target', :name => 'ChildPod', :sandbox => config.sandbox)
parent_pod_target = stub('parent_pod_target', :name => 'ParentPod', :sandbox => config.sandbox, :dependent_targets => [child_pod_target])
parent_target_definition = stub
child_target_definition = stub('child_target_definition', :inheritance => 'search_paths')
parent_aggregate_target = stub_aggregate_target([], parent_target_definition)
child_aggregate_target = stub_aggregate_target([parent_pod_target, child_pod_target], child_target_definition, :search_paths_aggregate_targets => [parent_aggregate_target])
@sut.links_dependency?(child_aggregate_target, child_pod_target).should.be.true
@sut.links_dependency?(child_aggregate_target, parent_pod_target).should.be.true
end
it 'should link static only transitive dependencies that the parent does not link' do
child_pod_target = stub('child_pod_target', :name => 'ChildPod', :sandbox => config.sandbox)
parent_pod_target = stub('parent_pod_target', :name => 'ParentPod', :sandbox => config.sandbox, :dependent_targets => [child_pod_target])
parent_target_definition = stub
child_target_definition = stub('child_target_definition', :inheritance => 'search_paths')
parent_aggregate_target = stub('parent_aggregate_target', :target_definition => parent_target_definition, :pod_targets => [child_pod_target], :search_paths_aggregate_targets => [], :pod_targets_to_link => [child_pod_target])
child_aggregate_target = stub('child_aggregate_target', :target_definition => child_target_definition, :pod_targets => [parent_pod_target, child_pod_target], :search_paths_aggregate_targets => [parent_aggregate_target], :pod_targets_to_link => [parent_pod_target])
@sut.links_dependency?(child_aggregate_target, child_pod_target).should.be.false
@sut.links_dependency?(child_aggregate_target, parent_pod_target).should.be.true
end
end
#---------------------------------------------------------------------#
end
end
end
end
require File.expand_path('../../../spec_helper', __FILE__)
module Pod
describe Generator::XCConfig do
end
end
......@@ -90,12 +90,8 @@ module Pod
framework_subdir_header = headers_root + 'BananaLib/Bananalib/SubDir/SubBananalib.h'
public_headers.each { |public_header| public_header.should.exist }
private_header.should.not.exist
framework_header.should.exist
framework_subdir_header.should.exist
config.sandbox.public_headers.search_paths(@pod_target.platform).should == %w(
${PODS_ROOT}/Headers/Public
${PODS_ROOT}/Headers/Public/BananaLib
)
framework_header.should.not.exist
framework_subdir_header.should.not.exist
end
it 'links the public headers meant for the user for a vendored framework' do
......
......@@ -322,8 +322,9 @@ module Pod
user_target = stub('SampleApp-iOS-User-Target', :symbol_type => :application)
user_target.expects(:common_resolved_build_setting).with('APPLICATION_EXTENSION_API_ONLY').returns('NO')
target = AggregateTarget.new(config.sandbox, false, {}, [],
Platform.new(:ios, '6.0'), fixture_target_definition,
target = AggregateTarget.new(config.sandbox, false,
{ 'App Store' => :release, 'Debug' => :debug, 'Release' => :release, 'Test' => :debug },
[], Platform.new(:ios, '6.0'), fixture_target_definition,
config.sandbox.root.dirname, proj, nil, [])
target.stubs(:user_targets).returns([user_target])
......
require File.expand_path('../../../../spec_helper', __FILE__)
module Pod
module Generator
module XCConfig
describe AggregateXCConfig do
class Target
class BuildSettings
describe AggregateTargetSettings do
def specs
[fixture_spec('banana-lib/BananaLib.podspec')]
end
......@@ -18,14 +18,14 @@ module Pod
@specs.first.user_target_xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' } unless @specs.empty?
@specs.first.pod_target_xcconfig = { 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11' } unless @specs.empty?
@pod_targets = @specs.map { |spec| pod_target(spec, @target_definition) }
@target = fixture_aggregate_target(@pod_targets, false, {}, [], Platform.new(:ios, '6.0'), @target_definition)
@target = fixture_aggregate_target(@pod_targets, false, { 'Release' => :release }, [], Platform.new(:ios, '6.0'), @target_definition)
unless @specs.empty?
@target.target_definition.whitelist_pod_for_configuration(@specs.first.name, 'Release')
end
@generator = AggregateXCConfig.new(@target, 'Release')
@generator = AggregateTargetSettings.new(@target, 'Release')
end
shared 'AggregateXCConfig' do
shared 'Aggregate' do
it 'returns the path of the pods root relative to the user project' do
@generator.target.relative_pods_root.should == '${SRCROOT}/Pods'
end
......@@ -135,7 +135,7 @@ module Pod
[fixture_spec('banana-lib/BananaLib.podspec')]
end
behaves_like 'AggregateXCConfig'
behaves_like 'Aggregate'
it 'configures the project to load all members that implement Objective-c classes or categories' do
@xcconfig.to_hash['OTHER_LDFLAGS'].should.include '-ObjC'
......@@ -158,6 +158,13 @@ module Pod
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end
it 'adds the dependent pods module map file to OTHER_SWIFT_FLAGS' do
@pod_targets.each { |pt| pt.stubs(:defines_module? => true) }
@xcconfig = @generator.generate
expected = '$(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_ROOT}/Headers/Private/BananaLib/BananaLib.modulemap"'
@xcconfig.to_hash['OTHER_SWIFT_FLAGS'].should == expected
end
describe 'with a scoped pod target' do
def pod_target(spec, target_definition)
fixture_pod_target(spec, false, {}, [], Platform.new(:ios, '6.0'), [target_definition]).scoped.first
......@@ -175,10 +182,50 @@ module Pod
end
it 'does not links the pod targets with the aggregate target for non-whitelisted configuration' do
@generator = AggregateXCConfig.new(@target, 'Debug')
@generator = AggregateTargetSettings.new(@target, 'Debug')
@xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_LDFLAGS'].should.not.include '-l"Pods-BananaLib"'
end
it 'does propagate framework or libraries from a non test specification to an aggregate target' do
target_definition = stub('target_definition', :inheritance => 'complete', :abstract? => false, :podfile => Podfile.new, :platform => Platform.ios)
spec = stub('spec', :test_specification? => false)
consumer = stub('consumer',
:libraries => ['xml2'],
:frameworks => ['XCTest'],
:weak_frameworks => [],
:spec => spec,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
file_accessor.stubs(:vendored_frameworks => file_accessor.vendored_static_frameworks + file_accessor.vendored_dynamic_frameworks,
:vendored_dynamic_artifacts => file_accessor.vendored_dynamic_frameworks + file_accessor.vendored_dynamic_libraries)
pod_target = stub('pod_target',
:file_accessors => [file_accessor],
:spec_consumers => [consumer],
:requires_frameworks? => false,
:dependent_targets => [],
:recursive_dependent_targets => [],
:sandbox => config.sandbox,
:should_build? => true,
:configuration_build_dir => 'CBD',
:include_in_build_config? => true,
:uses_swift? => false,
:build_product_path => 'BPP',
:product_basename => 'PodTarget',
:target_definitions => [target_definition],
)
pod_target.stubs(:build_settings => PodTargetSettings.new(pod_target, false))
aggregate_target = fixture_aggregate_target([pod_target])
@generator = AggregateTargetSettings.new(aggregate_target, 'Debug')
@generator.other_ldflags.should == %w(-ObjC -l"PodTarget" -l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "StaticFramework" -framework "VendoredFramework" -framework "XCTest")
end
end
describe 'with framework' do
......@@ -190,7 +237,7 @@ module Pod
Target.any_instance.stubs(:requires_frameworks?).returns(true)
end
behaves_like 'AggregateXCConfig'
behaves_like 'Aggregate'
it "doesn't configure the project to load all members that implement Objective-c classes or categories" do
@xcconfig.to_hash['OTHER_LDFLAGS'].should.not.include '-ObjC'
......@@ -220,7 +267,7 @@ module Pod
end
it 'includes the public header paths as system headers' do
expected = '$(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/OrangeFramework/OrangeFramework.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public/monkey"'
expected = '$(inherited) -isystem "${PODS_ROOT}/Headers/Public/monkey" -iquote "${PODS_CONFIGURATION_BUILD_DIR}/OrangeFramework/OrangeFramework.framework/Headers"'
@generator.stubs(:pod_targets).returns([@pod_targets.first, pod_target(fixture_spec('orange-framework/OrangeFramework.podspec'), @target_definition)])
@xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected
......@@ -259,7 +306,7 @@ module Pod
end
it 'adds the framework build path to the xcconfig, with quotes, as framework search paths' do
@xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BananaLib-iOS" "${PODS_CONFIGURATION_BUILD_DIR}/OrangeFramework-iOS"'
@xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BananaLib-iOS" "${PODS_CONFIGURATION_BUILD_DIR}/OrangeFramework-iOS" "${PODS_ROOT}/../../spec/fixtures/banana-lib"'
end
it 'adds the framework header paths to the xcconfig, with quotes, as local headers' do
......@@ -284,7 +331,7 @@ module Pod
end
it 'adds the COCOAPODS macro definition' do
@xcconfig.to_hash['OTHER_SWIFT_FLAGS'].should.include '$(inherited) "-D" "COCOAPODS"'
@xcconfig.to_hash['OTHER_SWIFT_FLAGS'].should.include '$(inherited) -D COCOAPODS'
end
it 'includes default runpath search path list for a non host target' do
......@@ -313,58 +360,143 @@ module Pod
it 'uses the target definition swift version' do
@target_definition.stubs(:swift_version).returns('0.1')
@generator.send(:target_swift_version).should == '0.1'
@generator.send :__clear__
@generator.send(:target_swift_version).should == Version.new('0.1')
end
it 'sets EMBEDDED_CONTENT_CONTAINS_SWIFT when the target_swift_version is < 2.3' do
@generator.send(:pod_targets).first.stubs(:uses_swift?).returns(true)
@generator.stubs(:target_swift_version).returns('2.2')
@target_definition.stubs(:swift_version).returns('2.2')
@generator.generate.to_hash['EMBEDDED_CONTENT_CONTAINS_SWIFT'].should == 'YES'
end
it 'does not set EMBEDDED_CONTENT_CONTAINS_SWIFT when there is no swift' do
@generator.send(:pod_targets).each { |pt| pt.stubs(:uses_swift?).returns(false) }
@generator.stubs(:target_swift_version).returns('2.2')
@target_definition.stubs(:swift_version).returns('2.2')
@generator.generate.to_hash['EMBEDDED_CONTENT_CONTAINS_SWIFT'].should.be.nil
end
it 'does not set EMBEDDED_CONTENT_CONTAINS_SWIFT when there is swift, but the target is an extension' do
@target.stubs(:requires_host_target?).returns(true)
@generator.stubs(:target_swift_version).returns('2.2')
@target_definition.stubs(:swift_version).returns('2.2')
@generator.send(:pod_targets).first.stubs(:uses_swift?).returns(true)
@generator.generate.to_hash['EMBEDDED_CONTENT_CONTAINS_SWIFT'].should.be.nil
end
it 'sets EMBEDDED_CONTENT_CONTAINS_SWIFT when the target_swift_version is nil' do
@generator.send(:pod_targets).first.stubs(:uses_swift?).returns(true)
@generator.stubs(:target_swift_version).returns(nil)
@target_definition.stubs(:swift_version).returns(nil)
@generator.generate.to_hash['EMBEDDED_CONTENT_CONTAINS_SWIFT'].should == 'YES'
end
it 'sets ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES to YES when there is swift >= 2.3' do
@generator.send(:pod_targets).first.stubs(:uses_swift?).returns(true)
@generator.stubs(:target_swift_version).returns('2.3')
@target_definition.stubs(:swift_version).returns('2.3')
@generator.generate.to_hash['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'].should == 'YES'
end
it 'does not set ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES when there is no swift' do
@generator.send(:pod_targets).first.stubs(:uses_swift?).returns(false)
@generator.stubs(:target_swift_version).returns(nil)
@target_definition.stubs(:swift_version).returns(nil)
@generator.generate.to_hash['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'].nil?.should == true
end
it 'does not set ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES when there is swift, but the target is an extension' do
@target.stubs(:requires_host_target?).returns(true)
@generator.stubs(:target_swift_version).returns('2.3')
@target_definition.stubs(:swift_version).returns('2.3')
@generator.send(:pod_targets).first.stubs(:uses_swift?).returns(true)
@generator.generate.to_hash['ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES'].nil?.should == true
end
it 'does not set EMBEDDED_CONTENT_CONTAINS_SWIFT when there is swift 2.3 or higher' do
@generator.send(:pod_targets).first.stubs(:uses_swift?).returns(true)
@generator.stubs(:target_swift_version).returns('2.3')
@target_definition.stubs(:swift_version).returns('2.3')
@generator.generate.to_hash.key?('EMBEDDED_CONTENT_CONTAINS_SWIFT').should == false
end
it 'does propagate framework or libraries from a non test specification to an aggregate target' do
target_definition = stub('target_definition', :inheritance => 'complete', :abstract? => false, :podfile => Podfile.new, :platform => Platform.ios)
spec = stub('spec', :test_specification? => false)
consumer = stub('consumer',
:libraries => ['xml2'],
:frameworks => ['XCTest'],
:weak_frameworks => [],
:spec => spec,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
file_accessor.stubs(:vendored_frameworks => file_accessor.vendored_static_frameworks + file_accessor.vendored_dynamic_frameworks,
:vendored_dynamic_artifacts => file_accessor.vendored_dynamic_frameworks + file_accessor.vendored_dynamic_libraries,
:vendored_static_artifacts => file_accessor.vendored_static_frameworks + file_accessor.vendored_static_libraries)
pod_target = stub('pod_target',
:file_accessors => [file_accessor],
:spec_consumers => [consumer],
:requires_frameworks? => true,
:static_framework? => false,
:dependent_targets => [],
:recursive_dependent_targets => [],
:sandbox => config.sandbox,
:should_build? => true,
:configuration_build_dir => 'CBD',
:include_in_build_config? => true,
:uses_swift? => false,
:build_product_path => 'BPP',
:product_basename => 'PodTarget',
:target_definitions => [target_definition],
)
pod_target.stubs(:build_settings => PodTargetSettings.new(pod_target, false))
aggregate_target = fixture_aggregate_target([pod_target])
@generator = AggregateTargetSettings.new(aggregate_target, 'Debug')
@generator.other_ldflags.should == %w(-ObjC -l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "PodTarget" -framework "VendoredFramework" -framework "XCTest")
end
it 'does propagate framework or libraries from a non test specification static framework to an aggregate target' do
target_definition = stub('target_definition', :inheritance => 'complete', :abstract? => false, :podfile => Podfile.new, :platform => Platform.ios)
spec = stub('spec', :test_specification? => false)
consumer = stub('consumer',
:libraries => ['xml2'],
:frameworks => ['XCTest'],
:weak_frameworks => [],
:spec => spec,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
file_accessor.stubs(:vendored_frameworks => file_accessor.vendored_static_frameworks + file_accessor.vendored_dynamic_frameworks,
:vendored_dynamic_artifacts => file_accessor.vendored_dynamic_frameworks + file_accessor.vendored_dynamic_libraries,
:vendored_static_artifacts => file_accessor.vendored_static_frameworks + file_accessor.vendored_static_libraries)
pod_target = stub('pod_target',
:file_accessors => [file_accessor],
:spec_consumers => [consumer],
:requires_frameworks? => true,
:static_framework? => true,
:dependent_targets => [],
:recursive_dependent_targets => [],
:sandbox => config.sandbox,
:should_build? => true,
:configuration_build_dir => 'CBD',
:include_in_build_config? => true,
:uses_swift? => false,
:build_product_path => 'BPP',
:product_basename => 'PodTarget',
:target_definitions => [target_definition],
)
pod_target.stubs(:build_settings => PodTargetSettings.new(pod_target, false))
aggregate_target = fixture_aggregate_target([pod_target])
@generator = AggregateTargetSettings.new(aggregate_target, 'Debug')
@generator.other_ldflags.should == %w(-ObjC -l"StaticLibrary" -l"VendoredDyld" -l"xml2" -framework "PodTarget" -framework "StaticFramework" -framework "VendoredFramework" -framework "XCTest")
end
end
#-----------------------------------------------------------------------#
......@@ -455,7 +587,7 @@ module Pod
it 'adds values from all subspecs' do
@consumer_b.stubs(:user_target_xcconfig).returns('OTHER_CPLUSPLUSFLAGS' => '-std=c++1y')
consumer_c = mock(:user_target_xcconfig => { 'OTHER_CPLUSPLUSFLAGS' => '-stdlib=libc++' }, :script_phases => [])
consumer_c = mock('consumer_c', :user_target_xcconfig => { 'OTHER_CPLUSPLUSFLAGS' => '-stdlib=libc++' }, :script_phases => [], :spec => mock(:test_specification? => false), :frameworks => [], :libraries => [])
@pod_targets[1].stubs(:spec_consumers).returns([@consumer_b, consumer_c])
@xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_CPLUSPLUSFLAGS'].should == '-std=c++1y -stdlib=libc++'
......@@ -484,7 +616,7 @@ module Pod
describe 'an empty pod target' do
before do
@blank_target = fixture_aggregate_target
@generator = AggregateXCConfig.new(@blank_target, 'Release')
@generator = AggregateTargetSettings.new(@blank_target, 'Release')
end
it 'it should not have any framework search paths' do
......@@ -493,12 +625,32 @@ module Pod
end
describe 'with inherited targets' do
it 'should include inherited search paths' do
before do
# It's the responsibility of the analyzer to
# populate this when the file is loaded.
@blank_target.search_paths_aggregate_targets.replace [@target]
end
it 'should include inherited search paths' do
@xcconfig = @generator.generate
@xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.not.be.nil
@xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/../../spec/fixtures/banana-lib"'
end
it 'should include OTHER_LDFLAGS to link against dynamic libraries' do
@target.pod_targets.each { |pt| pt.spec_consumers.each { |sc| sc.stubs(:frameworks => %w(UIKit), :libraries => %w(z c++)) } }
@xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_LDFLAGS'].should == '$(inherited) -ObjC -l"c++" -l"z" -framework "UIKit"'
end
it 'should not doubly link static libraries' do
@specs.each { |s| s.user_target_xcconfig = nil }
@target.pod_targets.each { |pt| pt.spec_consumers.each { |sc| sc.stubs(:frameworks => %w(UIKit), :libraries => %w(z), :vendored_libraries => %w()) } }
@blank_target.pod_targets.replace @target.pod_targets
@xcconfig = @generator.generate
# -lBananaLib is not added
@xcconfig.to_hash['OTHER_LDFLAGS'].should == '$(inherited) -ObjC -l"z" -framework "UIKit"'
end
end
end
......
require File.expand_path('../../../../spec_helper', __FILE__)
module Pod
module Generator
module XCConfig
describe PodXCConfig do
class Target
class BuildSettings
describe PodTargetSettings do
describe 'in general' do
before do
@monkey_spec = fixture_spec('monkey/monkey.podspec')
......@@ -12,6 +12,7 @@ module Pod
vspec = stub(:test_specification? => false)
consumer = stub(
"Spec Consumer (#{vspec} iOS)",
:spec => vspec,
:pod_target_xcconfig => {},
:libraries => ['xml2'],
:frameworks => [],
......@@ -27,6 +28,8 @@ module Pod
:vendored_dynamic_frameworks => [config.sandbox.root + 'CCC/VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'DDD/VendoredDyld.dyld'],
)
file_accessor.stubs(:vendored_libraries => file_accessor.vendored_static_libraries + file_accessor.vendored_dynamic_libraries,
:vendored_frameworks => file_accessor.vendored_static_frameworks + file_accessor.vendored_dynamic_frameworks)
vendored_dep_target = stub(
'Vendored Dependent Target',
:name => 'BananaLib',
......@@ -36,9 +39,14 @@ module Pod
:requires_frameworks? => true,
:static_framework? => false,
:dependent_targets => [],
:recursive_dependent_targets => [],
:file_accessors => [file_accessor],
:spec_consumers => [consumer],
:uses_modular_headers? => false,
:uses_swift? => false,
:specs => [vspec],
)
vendored_dep_target.stubs(:build_settings => PodTargetSettings.new(vendored_dep_target, false))
@spec = fixture_spec('banana-lib/BananaLib.podspec')
@pod_target = fixture_pod_target(@spec, true)
......@@ -46,7 +54,7 @@ module Pod
@consumer = @pod_target.spec_consumers.first
@podfile = @pod_target.podfile
@generator = PodXCConfig.new(@pod_target)
@generator = PodTargetSettings.new(@pod_target, false)
@spec.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' }
@spec.user_target_xcconfig = { 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11' }
......@@ -169,12 +177,51 @@ module Pod
@xcconfig.to_hash['PRODUCT_BUNDLE_IDENTIFIER'].should == 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}'
end
it 'does not have a module map to import if it is not built' do
@pod_target.stubs(:should_build? => false, :requires_frameworks? => false, :defines_module? => true)
@generator.generate
@generator.module_map_file_to_import.should.be.nil
end
it 'saves the xcconfig' do
path = temporary_directory + 'sample.xcconfig'
@generator.save_as(path)
generated = Xcodeproj::Config.new(path)
generated.class.should == Xcodeproj::Config
end
it 'does propagate framework or libraries' do
spec = stub('spec', :test_specification? => false)
consumer = stub('consumer',
:libraries => ['xml2'],
:frameworks => ['XCTest'],
:weak_frameworks => [],
:spec => spec,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
pod_target = stub('pod_target',
:file_accessors => [file_accessor],
:spec_consumers => [consumer],
:requires_frameworks? => true,
:static_framework? => true,
:dependent_targets => [],
:recursive_dependent_targets => [],
:sandbox => config.sandbox,
:should_build? => true,
)
pod_target.stubs(:build_settings => PodTargetSettings.new(pod_target, false))
@generator.spec_consumers.each { |sc| sc.stubs(:frameworks => []) }
@generator.stubs(:dependent_targets => [pod_target])
@generator.send :__clear__
@generator.other_ldflags.should.be == %w(-l"VendoredDyld" -l"xml2" -framework "Bananalib" -framework "VendoredFramework" -framework "XCTest" -weak_framework "iAd")
end
end
describe 'test xcconfig generation' do
......@@ -201,7 +248,7 @@ module Pod
it 'does not merge pod target xcconfig of test specifications for a non test xcconfig' 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 = PodXCConfig.new(@coconut_pod_target, false)
generator = PodTargetSettings.new(@coconut_pod_target, false)
xcconfig = generator.generate
xcconfig.to_hash['GCC_PREPROCESSOR_DEFINITIONS'].should == '$(inherited) COCOAPODS=1 NON_TEST_FLAG=1'
end
......@@ -209,41 +256,41 @@ module Pod
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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
xcconfig = generator.generate
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-ObjC -l"CoconutLib"'
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(:requires_frameworks?).returns(true)
generator = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
xcconfig = generator.generate
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-ObjC -framework "CoconutLib"'
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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
xcconfig = generator.generate
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-ObjC -l"CoconutLib" -l"monkey" -framework "dynamic-monkey"'
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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
xcconfig = generator.generate
xcconfig.to_hash['OTHER_LDFLAGS'].should == '-ObjC -l"CoconutLib" -l"monkey" -framework "dynamic-monkey"'
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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
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"'
......@@ -252,10 +299,23 @@ module Pod
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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
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_ROOT}/../../spec/fixtures/banana-lib" "${PODS_CONFIGURATION_BUILD_DIR}/CoconutLib"'
xcconfig.to_hash['LIBRARY_SEARCH_PATHS'].should == '$(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/BananaLib" "${PODS_CONFIGURATION_BUILD_DIR}/CoconutLib" "${PODS_ROOT}/../../spec/fixtures/banana-lib"'
end
it 'adds the developer frameworks dir when XCTest is used but not linked' do
@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, false)
xcconfig = generator.generate
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"'
generator = PodTargetSettings.new(@banana_pod_target, false)
xcconfig = generator.generate
xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "$(PLATFORM_DIR)/Developer/Library/Frameworks"'
end
it 'adds correct header search paths for dependent and test targets without modular headers' do
......@@ -269,7 +329,7 @@ module Pod
@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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
xcconfig = generator.generate
xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/Headers/Private"' \
' "${PODS_ROOT}/Headers/Private/CoconutLib"' \
......@@ -291,7 +351,7 @@ module Pod
@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 = PodXCConfig.new(@coconut_pod_target, false)
generator = PodTargetSettings.new(@coconut_pod_target, false)
xcconfig = generator.generate
xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/Headers/Private"' \
' "${PODS_ROOT}/Headers/Private/CoconutLib"' \
......@@ -311,7 +371,7 @@ module Pod
@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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
xcconfig = generator.generate
xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/Headers/Private"' \
' "${PODS_ROOT}/Headers/Private/CoconutLib"' \
......@@ -329,7 +389,7 @@ module Pod
@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 = PodXCConfig.new(@coconut_pod_target, false)
generator = PodTargetSettings.new(@coconut_pod_target, false)
xcconfig = generator.generate
xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '$(inherited) "${PODS_ROOT}/Headers/Private"' \
' "${PODS_ROOT}/Headers/Private/CoconutLib"' \
......@@ -338,27 +398,27 @@ module Pod
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 = PodXCConfig.new(@coconut_pod_target)
generator = PodTargetSettings.new(@coconut_pod_target, false)
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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
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 = PodXCConfig.new(@coconut_pod_target, true)
generator = PodTargetSettings.new(@coconut_pod_target, true)
xcconfig = generator.generate
xcconfig.to_hash['CONFIGURATION_BUILD_DIR'].should.be.nil
end
......
require File.expand_path('../../../spec_helper', __FILE__)
module Pod
class Target
describe BuildSettings do
def pod(pod_target, test_xcconfig = false)
BuildSettings::PodTargetSettings.new(pod_target, test_xcconfig)
end
def aggregate(aggregate_target, configuration_name = 'Release')
BuildSettings::AggregateTargetSettings.new(aggregate_target, configuration_name)
end
describe 'memoization' do
it 'memoizes methods when requested' do
cls = Class.new(BuildSettings) do
define_build_settings_method :foobar, :memoized => true do
Object.new
end
end
settings = cls.new(stub('Target'))
object = settings.foobar
object.should.be.frozen
object.should.equal?(settings.foobar)
end
it 'memoizes array methods when requested' do
cls = Class.new(BuildSettings) do
define_build_settings_method :foobar, :memoized => true, :sorted => true, :uniqued => true do
%w(b a c a)
end
end
settings = cls.new(stub('Target'))
object = settings.foobar
object.should.be.frozen
object.should == %w(a b c)
object.should.equal?(settings.foobar)
end
end
#---------------------------------------------------------------------#
describe '::add_developers_frameworks_if_needed' do
it 'adds the developer frameworks search paths to the xcconfig if SenTestingKit has been detected' do
xcconfig = BuildSettings.new(stub('Target'))
xcconfig.stubs(:frameworks => %w(SenTestingKit))
frameworks_search_paths = xcconfig.framework_search_paths
frameworks_search_paths.should == %w($(PLATFORM_DIR)/Developer/Library/Frameworks)
end
it 'adds the developer frameworks search paths to the xcconfig if XCTest has been detected' do
xcconfig = BuildSettings.new(stub('Target'))
xcconfig.stubs(:frameworks => %w(XCTest))
frameworks_search_paths = xcconfig.framework_search_paths
frameworks_search_paths.should == %w($(PLATFORM_DIR)/Developer/Library/Frameworks)
end
end
#---------------------------------------------------------------------#
describe '::add_language_specific_settings' do
it 'does not add OTHER_SWIFT_FLAGS to the xcconfig if the target does not use swift' do
target = fixture_pod_target('integration/Reachability/Reachability.podspec')
build_settings = pod(target)
other_swift_flags = build_settings.xcconfig.to_hash['OTHER_SWIFT_FLAGS']
other_swift_flags.should.be.nil
end
it 'does not add the -suppress-warnings flag to the xcconfig if the target uses swift, but does not inhibit warnings' do
target = fixture_pod_target('integration/Reachability/Reachability.podspec')
target.stubs(:uses_swift? => true, :inhibit_warnings? => false)
build_settings = pod(target)
other_swift_flags = build_settings.xcconfig.to_hash['OTHER_SWIFT_FLAGS']
other_swift_flags.should.not.include '-suppress-warnings'
end
it 'adds the -suppress-warnings flag to the xcconfig if the target uses swift and inhibits warnings' do
target = fixture_pod_target('integration/Reachability/Reachability.podspec')
target.stubs(:uses_swift? => true, :inhibit_warnings? => true)
build_settings = pod(target)
other_swift_flags = build_settings.xcconfig.to_hash['OTHER_SWIFT_FLAGS']
other_swift_flags.should.include '-suppress-warnings'
end
end
#---------------------------------------------------------------------#
describe 'concerning settings for file accessors' do
it 'does not propagate framework or libraries from a test specification to an aggregate target' do
target_definition = stub('target_definition', :inheritance => 'complete', :abstract? => false, :podfile => Podfile.new)
spec = stub('spec', :test_specification? => true)
consumer = stub('consumer',
:libraries => ['xml2'],
:frameworks => ['XCTest'],
:weak_frameworks => [],
:spec => spec,
)
file_accessor = stub('file_accessor',
:spec => spec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'StaticFramework.framework'],
:vendored_static_libraries => [config.sandbox.root + 'StaticLibrary.a'],
:vendored_dynamic_frameworks => [config.sandbox.root + 'VendoredFramework.framework'],
:vendored_dynamic_libraries => [config.sandbox.root + 'VendoredDyld.dyld'],
)
pod_target = stub('pod_target',
:file_accessors => [file_accessor],
:requires_frameworks? => true,
:dependent_targets => [],
:recursive_dependent_targets => [],
:sandbox => config.sandbox,
:include_in_build_config? => true,
:should_build? => false,
:spec_consumers => [consumer],
:static_framework? => false,
:product_basename => 'PodTarget',
:target_definitions => [target_definition],
)
pod_target.stubs(:build_settings => pod(pod_target))
aggregate_target = fixture_aggregate_target([pod_target])
aggregate(aggregate_target).other_ldflags.should.not.include '-framework'
end
end
#---------------------------------------------------------------------#
end
end
end
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment