Commit 8c2d9d13 authored by Samuel Giddins's avatar Samuel Giddins

Refactor XCConfig / Build Settings generation

This refactor makes this part of `pod install` scale much better,
as we avoid exponential explosion when generating "recursive" build
settings by moving to an architecture that allows memoizing settings
on a per-target basis

Move XCConfig specs over to build settings

rm old xcconfig generators
parent c109b144
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
......@@ -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
......
......@@ -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::Pod.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.
#
......@@ -33,6 +35,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 +53,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 +236,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).
#
......@@ -309,5 +319,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::Aggregate.new(self, configuration_name)
end
settings
end
end
end
# frozen_string_literal: true
module Pod
class Target
class BuildSettings
PLURAL_SETTINGS = Set.new %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
)
CONFIGURATION_BUILD_DIR_VARIABLE = '${PODS_CONFIGURATION_BUILD_DIR}'.freeze
# Creates a method that calculates a part of the build settings for the #target.
#
# @macro [attach]
# @!method $1
#
def self.define_build_settings_method(method_name, build_setting: false,
memoized: false, sorted: false, uniqued: false, frozen: true,
from_search_paths_aggregate_targets: false, from_pod_targets: 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 || from_search_paths_aggregate_targets || uniqued || sorted)
define_method(method_name) do
retval =
if memoized
@__memoized ||= {}
@__memoized.fetch(memoized_key) { @__memoized[memoized_key] = send(raw_method_name) }
else
send(raw_method_name)
end
return if retval.nil?
retval = retval.dup if dup_before_freeze && retval.frozen?
retval.concat(pod_targets.flat_map { |pod_target| pod_target.build_settings.public_send("#{method_name}_to_import") }) if from_pod_targets
retval.concat(target.search_paths_aggregate_targets.flat_map do |aggregate_target|
unless build_settings = aggregate_target.build_settings(configuration_name)
raise("#{aggregate_target.inspect} has no build settings for configuration #{configuration_name.inspect}")
end
build_settings.public_send(method_name)
end) if from_search_paths_aggregate_targets
retval.uniq! if uniqued
retval.sort! if sorted
retval.freeze if frozen
retval
end
end
def __clear__
@__memoized = nil
end
class << self
attr_reader :build_settings_names
end
attr_reader :target
def initialize(target)
@target = target
end
define_build_settings_method :gcc_preprocessor_definitions, :build_setting => true do
%w( COCOAPODS=1 )
end
define_build_settings_method :framework_search_paths, :build_setting => true, :memoized => true do
if frameworks.include?('XCTest') || frameworks.include?('SenTestingKit')
%w[ $(PLATFORM_DIR)/Developer/Library/Frameworks ]
else
[]
end
end
define_build_settings_method :other_cflags, :build_setting => true, :memoized => true do
module_map_files.map { |f| "-fmodule-map-file=#{f}" }
end
define_build_settings_method :module_map_files do
[]
end
define_build_settings_method :frameworks do
[]
end
define_build_settings_method :weak_frameworks do
[]
end
define_build_settings_method :libraries do
[]
end
define_build_settings_method :requires_objc_linker_flag? do
false
end
define_build_settings_method :requires_fobjc_arc? do
false
end
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
define_build_settings_method :other_swift_flags, :build_setting => true, :memoized => true do
return unless target.uses_swift?
flags = %w(-D COCOAPODS)
flags.concat module_map_files.flat_map { |f| ['-Xcc', "-fmodule-map-file=#{f}"] }
end
define_build_settings_method :pods_build_dir, :build_setting => true do
'${BUILD_DIR}'
end
define_build_settings_method :code_sign_identity, :build_setting => true do
return unless target.requires_frameworks?
return unless target.platform.to_sym == :osx
''
end
define_build_settings_method :pods_configuration_build_dir, :build_setting => true do
'${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)'
end
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
define_build_settings_method :xcconfig, :memoized => true do
settings = add_inherited_to_plural(to_h)
Xcodeproj::Config.new(settings)
end
def generate
__clear__
xcconfig
end
def save_as(path)
xcconfig.save_as(path)
end
def to_h
hash = {}
self.class.build_settings_names.sort.each do |setting|
hash[setting] = public_send(setting.downcase)
end
hash
end
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
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
class Pod < BuildSettings
def self.build_settings_names
@build_settings_names | BuildSettings.build_settings_names
end
attr_reader :test_xcconfig
alias test_xcconfig? test_xcconfig
def initialize(target, test_xcconfig)
super(target)
@test_xcconfig = test_xcconfig
end
def __clear__
super
dependent_targets.each { |pt| pt.build_settings.__clear__ }
end
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 spec_consumers.flat_map(&: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.tap(&:uniq!).tap(&:sort!)
end
define_build_settings_method :static_frameworks_to_import, :memoized => true do
static_frameworks_to_import = vendored_static_frameworks.map { |f| File.basename(f, '.framework') }
static_frameworks_to_import << target.product_basename if target.should_build? && target.requires_frameworks? && target.static_framework?
static_frameworks_to_import
end
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 spec_consumers.flat_map(&:frameworks)
dynamic_frameworks_to_import
end
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.tap(&:uniq!).tap(&:sort!)
end
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.tap(&:uniq!).tap(&:sort!)
end
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
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
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
define_build_settings_method :module_map_file_to_import, :memoized => true do
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
define_build_settings_method :spec_consumers, :memoized => true do
target.spec_consumers.select { |c| c.spec.test_specification? == test_xcconfig? }
end
define_build_settings_method :pods_root, :build_setting => true do
'${SRCROOT}'
end
define_build_settings_method :libraries_to_import, :memoized => true, :sorted => true, :uniqued => true do
static_libraries_to_import + dynamic_libraries_to_import
end
define_build_settings_method :frameworks_to_import, :memoized => true, :sorted => true, :uniqued => true do
static_frameworks_to_import + dynamic_frameworks_to_import
end
define_build_settings_method :weak_frameworks_to_import, :memoized => true, :sorted => true, :uniqued => true do
[]
end
define_build_settings_method :header_search_paths, :build_setting => true, :memoized => true, :sorted => true do
target.header_search_paths(test_xcconfig?)
end
define_build_settings_method :xcconfig, :memoized => true do
xcconfig = super()
xcconfig.merge(pod_target_xcconfig)
end
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
define_build_settings_method :vendored_static_libraries, :memoized => true do
file_accessors.flat_map(&:vendored_static_libraries)
end
define_build_settings_method :vendored_dynamic_libraries, :memoized => true do
file_accessors.flat_map(&:vendored_dynamic_libraries)
end
define_build_settings_method :vendored_static_frameworks, :memoized => true do
file_accessors.flat_map(&:vendored_static_frameworks)
end
define_build_settings_method :vendored_dynamic_frameworks, :memoized => true do
file_accessors.flat_map(&:vendored_dynamic_frameworks)
end
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
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
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
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 }
if test_xcconfig?
paths.concat framework_search_paths_to_import
else
paths.concat vendored_framework_search_paths
paths.delete(target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE))
end
paths
end
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
define_build_settings_method :framework_search_paths_to_import, :memoized => true do
return vendored_framework_search_paths unless target.requires_frameworks? && target.should_build?
vendored_framework_search_paths + [target.configuration_build_dir(CONFIGURATION_BUILD_DIR_VARIABLE)]
end
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
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
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
define_build_settings_method :pods_target_srcroot, :build_setting => true do
target.pod_target_srcroot
end
define_build_settings_method :skip_install, :build_setting => true do
'YES'
end
def requires_objc_linker_flag?
test_xcconfig?
end
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
define_build_settings_method :product_bundle_identifier, :build_setting => true do
'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}'
end
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
define_build_settings_method :dependent_targets, :memoized => true do
if test_xcconfig?
target.all_dependent_targets
else
target.recursive_dependent_targets
end
end
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
define_build_settings_method :file_accessors, :memoized => true do
target.file_accessors.select { |fa| fa.spec.test_specification? == test_xcconfig? }
end
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
end
class Aggregate < BuildSettings
def self.build_settings_names
@build_settings_names | BuildSettings.build_settings_names
end
attr_reader :configuration_name
def initialize(target, configuration_name)
super(target)
@configuration_name = configuration_name
end
define_build_settings_method :xcconfig, :memoized => true do
xcconfig = super()
xcconfig.merge(merged_user_target_xcconfigs)
end
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
define_build_settings_method :libraries, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets => true do
[]
end
define_build_settings_method :library_search_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets => true do
[]
end
define_build_settings_method :frameworks, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets => true, :from_search_paths_aggregate_targets => true do
[]
end
define_build_settings_method :weak_frameworks, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets => true, :from_search_paths_aggregate_targets => true do
[]
end
define_build_settings_method :framework_search_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets => true, :from_search_paths_aggregate_targets => true do
[]
end
define_build_settings_method :swift_include_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true, :from_pod_targets => true, :from_search_paths_aggregate_targets => true do
[]
end
define_build_settings_method :header_search_paths, :build_setting => true, :memoized => true, :sorted => true, :uniqued => true, :from_search_paths_aggregate_targets => true do
if target.requires_frameworks? && pod_targets.all?(&:should_build?)
[]
else
target.sandbox.public_headers.search_paths(target.platform).dup
end
end
define_build_settings_method :pods_podfile_dir_path, :build_setting => true, :memoized => true do
target.podfile_dir_relative_path
end
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
define_build_settings_method :framework_header_paths_for_iquote, :memoized => true, :sorted => true, :uniqued => true, :from_search_paths_aggregate_targets => true do
pod_targets.
select { |pt| pt.should_build? && pt.requires_frameworks? }.
map { |pt| "#{pt.build_product_path}/Headers" }
end
define_build_settings_method :pods_root, :build_setting => true, :memoized => true do
target.relative_pods_root
end
define_build_settings_method :ld_runpath_search_paths, :build_setting => true, :memoized => true, :uniqued => true do
return unless target.requires_frameworks? || vendored_dynamic_artifacts.any?
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
define_build_settings_method :vendored_dynamic_artifacts, :memoized => true do
pod_targets.flat_map(&:file_accessors).flat_map(&:vendored_dynamic_artifacts)
end
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
define_build_settings_method :requires_fobjc_arc?, :memoized => true do
target.podfile.set_arc_compatibility_flag? &&
target.spec_consumers.any?(&:requires_arc?)
end
define_build_settings_method :module_map_files, :memoized => true, :sorted => true, :uniqued => true, :from_search_paths_aggregate_targets => true do
pod_targets.map { |t| t.build_settings.module_map_file_to_import }.compact.sort
end
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
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
define_build_settings_method :must_embed_swift?, :memoized => true do
!target.requires_host_target? && pod_targets.any?(&:uses_swift?)
end
# !@group Private Helpers
# @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')
# 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
# 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}]
#
define_build_settings_method :merged_user_target_xcconfigs, :memoized => true do
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 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 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
......@@ -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::Pod.new(self, false)
end
end
end
......@@ -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 = { 'Release' => :release },
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
......@@ -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 Aggregate 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 = Aggregate.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'
......@@ -175,10 +175,51 @@ 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 = Aggregate.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? => 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 => Pod.new(pod_target, false))
aggregate_target = fixture_aggregate_target([pod_target])
@generator = Aggregate.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
describe 'with framework' do
......@@ -190,7 +231,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 +261,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 +300,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 +325,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,56 +354,57 @@ 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.__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
end
......@@ -455,7 +497,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 +526,7 @@ module Pod
describe 'an empty pod target' do
before do
@blank_target = fixture_aggregate_target
@generator = AggregateXCConfig.new(@blank_target, 'Release')
@generator = Aggregate.new(@blank_target, 'Release')
end
it 'it should not have any framework search paths' do
......
require File.expand_path('../../../../spec_helper', __FILE__)
module Pod
module Generator
module XCConfig
describe PodXCConfig do
class Target
class BuildSettings
describe Pod 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,13 @@ 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,
)
vendored_dep_target.stubs(:build_settings => Pod.new(vendored_dep_target, false))
@spec = fixture_spec('banana-lib/BananaLib.podspec')
@pod_target = fixture_pod_target(@spec, true)
......@@ -46,7 +53,7 @@ module Pod
@consumer = @pod_target.spec_consumers.first
@podfile = @pod_target.podfile
@generator = PodXCConfig.new(@pod_target)
@generator = Pod.new(@pod_target, false)
@spec.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' }
@spec.user_target_xcconfig = { 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11' }
......@@ -175,6 +182,39 @@ module Pod
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 => Pod.new(pod_target, false))
@generator.spec_consumers.each { |sc| sc.stubs(:frameworks => []) }
@generator.stubs(:dependent_targets => [pod_target])
@generator.__clear__
@generator.other_ldflags.should.be == %w(-l"VendoredDyld" -l"xml2" -framework "VendoredFramework" -framework "XCTest" -weak_framework "iAd")
end
end
describe 'test xcconfig generation' do
......@@ -201,7 +241,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 = Pod.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 +249,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 = Pod.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 = Pod.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 = Pod.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 = Pod.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 = Pod.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 = Pod.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 +292,10 @@ 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 = Pod.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 correct header search paths for dependent and test targets without modular headers' do
......@@ -269,7 +309,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 = Pod.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 +331,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 = Pod.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 +351,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 = Pod.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 +369,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 = Pod.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 +378,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 = Pod.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 = Pod.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 = Pod.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 = Pod.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::Pod.new(pod_target, test_xcconfig)
end
def aggregate(aggregate_target, configuration_name = 'Release')
BuildSettings::Aggregate.new(aggregate_target, configuration_name)
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