Commit 4c1f4a86 authored by Marius Rackwitz's avatar Marius Rackwitz

Merge pull request #3550 from CocoaPods/mr-deduplicate-frameworks

Deduplicate pod targets
parents ef5f9a4f a52d6b3b
...@@ -6,6 +6,25 @@ To install release candidates run `[sudo] gem install cocoapods --pre` ...@@ -6,6 +6,25 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
## Master ## Master
##### Highlighted Enhancement That Needs Testing
* De-duplicate Pod Targets: CocoaPods now recognizes when a dependency is used
multiple times across different user targets, but needs to be built only once.
The targets in `Pods.xcodeproj` need to be duplicated when one of the following
applies:
* They are used on different platforms.
* They are used with differents sets of subspecs.
* They have any dependency which needs to be duplicated.
You can opt-out of this behavior installation-wise, by setting the following
option in your ``~/.cocoapods/config.yaml`:
```yaml
deduplicate_targets: false
```
[Marius Rackwitz](https://github.com/mrackwitz)
[#3550](https://github.com/CocoaPods/CocoaPods/issues/3550)
##### Breaking ##### Breaking
* The CocoaPods environment header has been removed. * The CocoaPods environment header has been removed.
......
...@@ -19,6 +19,7 @@ module Pod ...@@ -19,6 +19,7 @@ module Pod
:clean => true, :clean => true,
:integrate_targets => true, :integrate_targets => true,
:deduplicate_targets => true,
:lock_pod_source => true, :lock_pod_source => true,
:new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?, :new_version_message => ENV['COCOAPODS_SKIP_UPDATE_MESSAGE'].nil?,
...@@ -89,6 +90,11 @@ module Pod ...@@ -89,6 +90,11 @@ module Pod
attr_accessor :integrate_targets attr_accessor :integrate_targets
alias_method :integrate_targets?, :integrate_targets alias_method :integrate_targets?, :integrate_targets
# @return [Bool] Whether CocoaPods should deduplicate pod targets.
#
attr_accessor :deduplicate_targets
alias_method :deduplicate_targets?, :deduplicate_targets
# @return [Bool] Whether the installer should skip the repos update. # @return [Bool] Whether the installer should skip the repos update.
# #
attr_accessor :skip_repo_update attr_accessor :skip_repo_update
......
module Pod module Pod
module Generator module Generator
class EmbedFrameworksScript class EmbedFrameworksScript
# @return [TargetDefinition] The target definition, whose label will be # @return [Hash{String => Array<String>}] Multiple lists of frameworks per
# used to locate the target-specific build products.
#
attr_reader :target_definition
# @return [Hash{String, Array{String}] Multiple lists of frameworks per
# configuration. # configuration.
# #
attr_reader :frameworks_by_config attr_reader :frameworks_by_config
# @param [TargetDefinition] target_definition # @param [Hash{String => Array<String>] frameworks_by_config
# @see #target_definition
#
# @param [Hash{String, Array{String}] frameworks_by_config
# @see #frameworks_by_config # @see #frameworks_by_config
# #
def initialize(target_definition, frameworks_by_config) def initialize(frameworks_by_config)
@target_definition = target_definition
@frameworks_by_config = frameworks_by_config @frameworks_by_config = frameworks_by_config
end end
...@@ -54,7 +45,7 @@ module Pod ...@@ -54,7 +45,7 @@ module Pod
install_framework() install_framework()
{ {
local source="${BUILT_PRODUCTS_DIR}/#{target_definition.label}/$1" local source="${BUILT_PRODUCTS_DIR}/$1"
local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -L "${source}" ]; then if [ -L "${source}" ]; then
...@@ -72,9 +63,9 @@ module Pod ...@@ -72,9 +63,9 @@ module Pod
# Embed linked Swift runtime libraries # Embed linked Swift runtime libraries
local basename local basename
basename=$(echo $1 | sed -E s/\\\\..+// && exit ${PIPESTATUS[0]}) basename=$(basename $1 | sed -E s/\\\\..+// && exit ${PIPESTATUS[0]})
local swift_runtime_libs local swift_runtime_libs
swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/$1/${basename}" | grep --color=never @rpath/libswift | sed -E s/@rpath\\\\/\\(.+dylib\\).*/\\\\1/g | uniq -u && exit ${PIPESTATUS[0]}) swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/${basename}.framework/${basename}" | grep --color=never @rpath/libswift | sed -E s/@rpath\\\\/\\(.+dylib\\).*/\\\\1/g | uniq -u && exit ${PIPESTATUS[0]})
for lib in $swift_runtime_libs; do for lib in $swift_runtime_libs; do
echo "rsync -auv \\"${SWIFT_STDLIB_PATH}/${lib}\\" \\"${destination}\\"" echo "rsync -auv \\"${SWIFT_STDLIB_PATH}/${lib}\\" \\"${destination}\\""
rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
......
...@@ -18,7 +18,7 @@ module Pod ...@@ -18,7 +18,7 @@ module Pod
# @see target # @see target
# #
def initialize(target) def initialize(target)
super(target.target_definition.platform) super(target.platform)
@target = target @target = target
end end
......
...@@ -54,19 +54,57 @@ module Pod ...@@ -54,19 +54,57 @@ module Pod
'PODS_ROOT' => target.relative_pods_root, 'PODS_ROOT' => target.relative_pods_root,
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1', 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
} }
@xcconfig = Xcodeproj::Config.new(config)
@xcconfig.merge!(merged_user_target_xcconfigs)
generate_settings_to_import_pod_targets
XCConfigHelper.add_target_specific_settings(target, @xcconfig)
generate_vendored_build_settings
generate_other_ld_flags
# 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')
generate_ld_runpath_search_paths if target.requires_frameworks?
@xcconfig
end
#---------------------------------------------------------------------#
private
# Add build settings, which ensure that the pod targets can be imported
# from the integrating target by all sort of imports, which are:
# - `#import <…>`
# - `#import "…"`
# - `@import …;` / `import …`
#
def generate_settings_to_import_pod_targets
if target.requires_frameworks? if target.requires_frameworks?
# Framework headers are automatically discoverable by `#import <…>`. # Framework headers are automatically discoverable by `#import <…>`.
header_search_paths = pod_targets.map { |target| "$PODS_FRAMEWORK_BUILD_PATH/#{target.product_name}/Headers" } header_search_paths = target.pod_targets.map do |target|
if target.scoped?
"$PODS_FRAMEWORK_BUILD_PATH/#{target.product_name}/Headers"
else
"$CONFIGURATION_BUILD_DIR/#{target.product_name}/Headers"
end
end
build_settings = { build_settings = {
'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir, 'PODS_FRAMEWORK_BUILD_PATH' => target.scoped_configuration_build_dir,
# Make headers discoverable by `import "…"` # Make headers discoverable by `import "…"`
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-iquote'), 'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-iquote'),
} }
if target.pod_targets.any?(&:should_build?) if target.pod_targets.any? { |t| t.should_build? && t.scoped? }
build_settings['FRAMEWORK_SEARCH_PATHS'] = '$(inherited) "$PODS_FRAMEWORK_BUILD_PATH"' build_settings['FRAMEWORK_SEARCH_PATHS'] = '$(inherited) "$PODS_FRAMEWORK_BUILD_PATH"'
end end
config.merge!(build_settings) @xcconfig.merge!(build_settings)
else else
# Make headers discoverable from $PODS_ROOT/Headers directory # Make headers discoverable from $PODS_ROOT/Headers directory
header_search_paths = target.sandbox.public_headers.search_paths(target.platform) header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
...@@ -76,46 +114,50 @@ module Pod ...@@ -76,46 +114,50 @@ module Pod
# by `#import <…>` # by `#import <…>`
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-isystem'), 'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-isystem'),
} }
config.merge!(build_settings) @xcconfig.merge!(build_settings)
end
end end
@xcconfig = Xcodeproj::Config.new(config) # Add custom build settings and required build settings to link to
# vendored libraries and frameworks.
XCConfigHelper.add_target_specific_settings(target, @xcconfig) #
# @note
pod_targets.each do |pod_target|
unless pod_target.should_build? && pod_target.requires_frameworks?
# In case of generated pod targets, which require frameworks, the # In case of generated pod targets, which require frameworks, the
# vendored frameworks and libraries are already linked statically # vendored frameworks and libraries are already linked statically
# into the framework binary and must not be linked again to the # into the framework binary and must not be linked again to the
# user target. # user target.
#
def generate_vendored_build_settings
target.pod_targets.each do |pod_target|
unless pod_target.should_build? && pod_target.requires_frameworks?
XCConfigHelper.add_settings_for_file_accessors_of_target(pod_target, @xcconfig) XCConfigHelper.add_settings_for_file_accessors_of_target(pod_target, @xcconfig)
end end
end
end
# Add pod target to list of frameworks / libraries that are # Add pod target to list of frameworks / libraries that are linked
# linked with the user’s project. # with the user’s project.
if pod_target.should_build? #
def generate_other_ld_flags
other_ld_flags = target.pod_targets.select(&:should_build?).map do |pod_target|
if pod_target.requires_frameworks? if pod_target.requires_frameworks?
@xcconfig.merge!('OTHER_LDFLAGS' => %(-framework "#{pod_target.product_basename}")) %(-framework "#{pod_target.product_basename}")
else else
@xcconfig.merge!('OTHER_LDFLAGS' => %(-l "#{pod_target.product_basename}")) %(-l "#{pod_target.product_basename}")
end
end end
end end
@xcconfig.merge!(merged_user_target_xcconfigs) @xcconfig.merge!('OTHER_LDFLAGS' => other_ld_flags.join(' '))
# 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')
generate_ld_runpath_search_paths if target.requires_frameworks?
@xcconfig
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.
#
def generate_ld_runpath_search_paths def generate_ld_runpath_search_paths
ld_runpath_search_paths = ['$(inherited)'] ld_runpath_search_paths = ['$(inherited)']
if target.platform.symbolic_name == :osx if target.platform.symbolic_name == :osx
......
...@@ -60,13 +60,13 @@ module Pod ...@@ -60,13 +60,13 @@ module Pod
# 'USE_HEADERMAP' => 'NO' # 'USE_HEADERMAP' => 'NO'
} }
if target.requires_frameworks? if target.requires_frameworks? && target.scoped?
# Only quote the FRAMEWORK_SEARCH_PATHS entry, because it’s a setting that takes multiple values. # Only quote the FRAMEWORK_SEARCH_PATHS entry, because it’s a setting that takes multiple values.
# In addition, quoting CONFIGURATION_BUILD_DIR would make it be interpreted as a relative path. # In addition, quoting CONFIGURATION_BUILD_DIR would make it be interpreted as a relative path.
build_settings = { build_settings = {
'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir, 'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir,
'CONFIGURATION_BUILD_DIR' => '$PODS_FRAMEWORK_BUILD_PATH',
'FRAMEWORK_SEARCH_PATHS' => '"$PODS_FRAMEWORK_BUILD_PATH"', 'FRAMEWORK_SEARCH_PATHS' => '"$PODS_FRAMEWORK_BUILD_PATH"',
'CONFIGURATION_BUILD_DIR' => '$PODS_FRAMEWORK_BUILD_PATH',
} }
config.merge!(build_settings) config.merge!(build_settings)
end end
......
...@@ -33,7 +33,7 @@ module Pod ...@@ -33,7 +33,7 @@ module Pod
# #
def self.default_ld_flags(target) def self.default_ld_flags(target)
ld_flags = '-ObjC' ld_flags = '-ObjC'
if target.target_definition.podfile.set_arc_compatibility_flag? && if target.podfile.set_arc_compatibility_flag? &&
target.spec_consumers.any?(&:requires_arc?) target.spec_consumers.any?(&:requires_arc?)
ld_flags << ' -fobjc-arc' ld_flags << ' -fobjc-arc'
end end
......
...@@ -179,7 +179,7 @@ module Pod ...@@ -179,7 +179,7 @@ module Pod
# generated as result of the analyzer. # generated as result of the analyzer.
# #
def pod_targets def pod_targets
aggregate_targets.map(&:pod_targets).flatten aggregate_targets.map(&:pod_targets).flatten.uniq
end end
# @return [Array<Specification>] The specifications that where installed. # @return [Array<Specification>] The specifications that where installed.
...@@ -212,9 +212,11 @@ module Pod ...@@ -212,9 +212,11 @@ module Pod
# @raise If an unknown user configuration is found. # @raise If an unknown user configuration is found.
# #
def validate_build_configurations def validate_build_configurations
whitelisted_configs = pod_targets.map do |target| whitelisted_configs = pod_targets.
target.target_definition.all_whitelisted_configurations.map(&:downcase) flat_map(&:target_definitions).
end.flatten.uniq flat_map(&:all_whitelisted_configurations).
map(&:downcase).
uniq
all_user_configurations = analysis_result.all_user_build_configurations.keys.map(&:downcase) all_user_configurations = analysis_result.all_user_build_configurations.keys.map(&:downcase)
remainder = whitelisted_configs - all_user_configurations remainder = whitelisted_configs - all_user_configurations
...@@ -260,8 +262,7 @@ module Pod ...@@ -260,8 +262,7 @@ module Pod
# created by the Pod source installer as well. # created by the Pod source installer as well.
# #
def create_file_accessors def create_file_accessors
aggregate_targets.each do |target| pod_targets.each do |pod_target|
target.pod_targets.each do |pod_target|
pod_root = sandbox.pod_dir(pod_target.root_spec.name) pod_root = sandbox.pod_dir(pod_target.root_spec.name)
path_list = Sandbox::PathList.new(pod_root) path_list = Sandbox::PathList.new(pod_root)
file_accessors = pod_target.specs.map do |spec| file_accessors = pod_target.specs.map do |spec|
...@@ -271,7 +272,6 @@ module Pod ...@@ -271,7 +272,6 @@ module Pod
pod_target.file_accessors.concat(file_accessors) pod_target.file_accessors.concat(file_accessors)
end end
end end
end
# Downloads, installs the documentation and cleans the sources of the Pods # Downloads, installs the documentation and cleans the sources of the Pods
# which need to be installed. # which need to be installed.
...@@ -351,7 +351,7 @@ module Pod ...@@ -351,7 +351,7 @@ module Pod
def determine_dependency_product_types def determine_dependency_product_types
aggregate_targets.each do |aggregate_target| aggregate_targets.each do |aggregate_target|
aggregate_target.pod_targets.each do |pod_target| aggregate_target.pod_targets.each do |pod_target|
pod_target.host_requires_frameworks = aggregate_target.requires_frameworks? pod_target.host_requires_frameworks ||= aggregate_target.requires_frameworks?
end end
end end
end end
...@@ -537,7 +537,7 @@ module Pod ...@@ -537,7 +537,7 @@ module Pod
def install_libraries def install_libraries
UI.message '- Installing targets' do UI.message '- Installing targets' do
pod_targets.sort_by(&:name).each do |pod_target| pod_targets.sort_by(&:name).each do |pod_target|
next if pod_target.target_definition.dependencies.empty? next if pod_target.target_definitions.flat_map(&:dependencies).empty?
target_installer = PodTargetInstaller.new(sandbox, pod_target) target_installer = PodTargetInstaller.new(sandbox, pod_target)
target_installer.install! target_installer.install!
end end
...@@ -628,12 +628,8 @@ module Pod ...@@ -628,12 +628,8 @@ module Pod
# @return [void] # @return [void]
# #
def share_development_pod_schemes def share_development_pod_schemes
development_pod_targets = sandbox.development_pods.keys.map do |pod| development_pod_targets.select(&:should_build?).each do |pod_target|
pods_project.targets.select { |target| target.name =~ /^Pods-.*-#{pod}$/ } Xcodeproj::XCScheme.share_scheme(pods_project.path, pod_target.label)
end.flatten
development_pod_targets.each do |pod_target|
Xcodeproj::XCScheme.share_scheme(pods_project.path, pod_target.name)
end end
end end
...@@ -740,6 +736,19 @@ module Pod ...@@ -740,6 +736,19 @@ module Pod
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
public
# @return [Array<Library>] The targets of the development pods generated by
# the installation process.
#
def development_pod_targets
pod_targets.select do |pod_target|
sandbox.development_pods.keys.include?(pod_target.pod_name)
end
end
#-------------------------------------------------------------------------#
private private
# @!group Private helpers # @!group Private helpers
......
This diff is collapsed.
module Pod
class Installer
class Analyzer
class AnalysisResult
# @return [SpecsState] the states of the Podfile specs.
#
attr_accessor :podfile_state
# @return [Hash{TargetDefinition => Array<Specification>}] the
# specifications grouped by target.
#
attr_accessor :specs_by_target
# @return [Array<Specification>] the specifications of the resolved
# version of Pods that should be installed.
#
attr_accessor :specifications
# @return [SpecsState] the states of the {Sandbox} respect the resolved
# specifications.
#
attr_accessor :sandbox_state
# @return [Array<Target>] The Podfile targets containing library
# dependencies.
#
attr_accessor :targets
# @return [Hash{TargetDefinition => Array<TargetInspectionResult>}] the
# results of inspecting the user targets
attr_accessor :target_inspections
# @return [Hash{String=>Symbol}] A hash representing all the user build
# configurations across all integration targets. Each key
# corresponds to the name of a configuration and its value to
# its type (`:debug` or `:release`).
#
def all_user_build_configurations
targets.reduce({}) do |result, target|
result.merge(target.user_build_configurations)
end
end
end
end
end
end
module Pod
class Installer
class Analyzer
# This class represents the state of a collection of Pods.
#
# @note The names of the pods stored by this class are always the **root**
# name of the specification.
#
# @note The motivation for this class is to ensure that the names of the
# subspecs are added instead of the name of the Pods.
#
class SpecsState
# Initialize a new instance
#
# @param [Hash{Symbol=>String}] pods_by_state
# The name of the pods grouped by their state
# (`:added`, `:removed`, `:changed` or `:unchanged`).
#
def initialize(pods_by_state = nil)
@added = []
@deleted = []
@changed = []
@unchanged = []
if pods_by_state
@added = pods_by_state[:added] || []
@deleted = pods_by_state[:removed] || []
@changed = pods_by_state[:changed] || []
@unchanged = pods_by_state[:unchanged] || []
end
end
# @return [Array<String>] the names of the pods that were added.
#
attr_accessor :added
# @return [Array<String>] the names of the pods that were changed.
#
attr_accessor :changed
# @return [Array<String>] the names of the pods that were deleted.
#
attr_accessor :deleted
# @return [Array<String>] the names of the pods that were unchanged.
#
attr_accessor :unchanged
# Displays the state of each pod.
#
# @return [void]
#
def print
added .sort.each { |pod| UI.message('A'.green + " #{pod}", '', 2) }
deleted .sort.each { |pod| UI.message('R'.red + " #{pod}", '', 2) }
changed .sort.each { |pod| UI.message('M'.yellow + " #{pod}", '', 2) }
unchanged.sort.each { |pod| UI.message('-' + " #{pod}", '', 2) }
end
# Adds the name of a Pod to the give state.
#
# @param [String] name
# the name of the Pod.
#
# @param [Symbol] state
# the state of the Pod.
#
# @return [void]
#
def add_name(name, state)
send(state) << name
end
end
end
end
end
module Pod
class Installer
class Analyzer
class TargetInspectionResult
# @return [TargetDefinition] the target definition, whose project was
# inspected
#
attr_accessor :target_definition
# @return [Pathname] the path of the user project that the
# #target_definition should integrate
#
attr_accessor :project_path
# @return [Array<String>] the uuid of the user's targets
#
attr_accessor :project_target_uuids
# @return [Hash{String=>Symbol}] A hash representing the user build
# configurations where each key corresponds to the name of a
# configuration and its value to its type (`:debug` or
# `:release`).
#
attr_accessor :build_configurations
# @return [Platform] the platform of the user targets
#
attr_accessor :platform
# @return [Array<String>] the architectures used by user's targets
#
attr_accessor :archs
# @return [Bool] whether frameworks are recommended for the integration
# due to the presence of Swift source in the user's targets
#
attr_accessor :recommends_frameworks
end
end
end
end
module Pod
class Installer
class Analyzer
class TargetInspector
# @return [TargetDefinition] the target definition to inspect
#
attr_accessor :target_definition
# @return [Pathname] the root of the CocoaPods installation where the
# Podfile is located
attr_accessor :installation_root
# Initialize a new instance
#
# @param [TargetDefinition] target_definition
# @see #target_definition
#
# @param [Pathname] installation_root
# @see #installation_root
#
def initialize(target_definition, installation_root)
@target_definition = target_definition
@installation_root = installation_root
end
# Inspect the #target_definition
#
# @return [TargetInspectionResult]
#
def compute_results
project_path = compute_project_path
user_project = Xcodeproj::Project.open(project_path)
targets = compute_targets(user_project)
result = TargetInspectionResult.new
result.target_definition = target_definition
result.project_path = project_path
result.project_target_uuids = targets.map(&:uuid)
result.build_configurations = compute_build_configurations(targets)
result.platform = compute_platform(targets)
result.archs = compute_archs(targets)
result
end
#-----------------------------------------------------------------------#
private
# Returns the path of the user project that the #target_definition
# should integrate.
#
# @raise If the project is implicit and there are multiple projects.
#
# @raise If the path doesn't exits.
#
# @return [Pathname] the path of the user project.
#
def compute_project_path
if target_definition.user_project_path
path = installation_root + target_definition.user_project_path
path = "#{path}.xcodeproj" unless File.extname(path) == '.xcodeproj'
path = Pathname.new(path)
unless path.exist?
raise Informative, 'Unable to find the Xcode project ' \
"`#{path}` for the target `#{target_definition.label}`."
end
else
xcodeprojs = installation_root.children.select { |e| e.fnmatch('*.xcodeproj') }
if xcodeprojs.size == 1
path = xcodeprojs.first
else
raise Informative, 'Could not automatically select an Xcode project. ' \
"Specify one in your Podfile like so:\n\n" \
" xcodeproj 'path/to/Project.xcodeproj'\n"
end
end
path
end
# Returns a list of the targets from the project of #target_definition
# that needs to be integrated.
#
# @note The method first looks if there is a target specified with
# the `link_with` option of the {TargetDefinition}. Otherwise
# it looks for the target that has the same name of the target
# definition. Finally if no target was found the first
# encountered target is returned (it is assumed to be the one
# to integrate in simple projects).
#
# @param [Xcodeproj::Project] user_project
# the user project
#
# @return [Array<PBXNativeTarget>]
#
def compute_targets(user_project)
native_targets = user_project.native_targets
if link_with = target_definition.link_with
targets = native_targets.select { |t| link_with.include?(t.name) }
raise Informative, "Unable to find the targets named #{link_with.map { |x| "`#{x}`" }.to_sentence}" \
"to link with target definition `#{target_definition.name}`" if targets.empty?
elsif target_definition.link_with_first_target?
targets = [native_targets.first].compact
raise Informative, 'Unable to find a target' if targets.empty?
else
target = native_targets.find { |t| t.name == target_definition.name.to_s }
targets = [target].compact
raise Informative, "Unable to find a target named `#{target_definition.name}`" if targets.empty?
end
targets
end
# @param [Array<PBXNativeTarget] the user's targets of the project of
# #target_definition which needs to be integrated
#
# @return [Hash{String=>Symbol}] A hash representing the user build
# configurations where each key corresponds to the name of a
# configuration and its value to its type (`:debug` or `:release`).
#
def compute_build_configurations(user_targets)
if user_targets
user_targets.flat_map { |t| t.build_configurations.map(&:name) }.each_with_object({}) do |name, hash|
hash[name] = name == 'Debug' ? :debug : :release
end.merge(target_definition.build_configurations || {})
else
target_definition.build_configurations || {}
end
end
# @param [Array<PBXNativeTarget] the user's targets of the project of
# #target_definition which needs to be integrated
#
# @return [Platform] The platform of the user's targets
#
# @note This resolves to the lowest deployment target across the user
# targets.
#
# @todo Is assigning the platform to the target definition the best way
# to go?
#
def compute_platform(user_targets)
return target_definition.platform if target_definition.platform
name = nil
deployment_target = nil
user_targets.each do |target|
name ||= target.platform_name
raise Informative, 'Targets with different platforms' unless name == target.platform_name
if !deployment_target || deployment_target > Version.new(target.deployment_target)
deployment_target = Version.new(target.deployment_target)
end
end
target_definition.set_platform(name, deployment_target)
Platform.new(name, deployment_target)
end
# Computes the architectures relevant for the user's targets.
#
# @param [Array<PBXNativeTarget] the user's targets of the project of
# #target_definition which needs to be integrated
#
# @return [Array<String>]
#
def compute_archs(user_targets)
user_targets.flat_map do |target|
Array(target.common_resolved_build_setting('ARCHS'))
end.compact.uniq.sort
end
# Checks if any of the targets for the {TargetDefinition} computed before
# by #compute_user_project_targets is recommended to be build as a framework
# due the presence of Swift source code in any of the source build phases.
#
# @param [TargetDefinition] target_definition
# the target definition
#
# @param [Array<PBXNativeTarget>] native_targets
# the targets which are checked for presence of Swift source code
#
# @return [Boolean] Whether the user project targets to integrate into
# uses Swift
#
def compute_recommends_frameworks(target_definition, native_targets)
file_predicate = nil
file_predicate = proc do |file_ref|
if file_ref.respond_to?(:last_known_file_type)
file_ref.last_known_file_type == 'sourcecode.swift'
elsif file_ref.respond_to?(:files)
file_ref.files.any?(&file_predicate)
else
false
end
end
target_definition.platform.supports_dynamic_frameworks? || native_targets.any? do |target|
target.source_build_phase.files.any? do |build_file|
file_predicate.call(build_file.file_ref)
end
end
end
end
end
end
end
...@@ -8,9 +8,9 @@ module Pod ...@@ -8,9 +8,9 @@ module Pod
# #
attr_reader :sandbox attr_reader :sandbox
# @return [Array<PodTarget>] The libraries of the installation. # @return [Array<PodTarget>] The pod targets of the installation.
# #
attr_reader :libraries attr_reader :pod_targets
# @return [Project] The Pods project. # @return [Project] The Pods project.
# #
...@@ -19,12 +19,12 @@ module Pod ...@@ -19,12 +19,12 @@ module Pod
# Initialize a new instance # Initialize a new instance
# #
# @param [Sandbox] sandbox @see sandbox # @param [Sandbox] sandbox @see sandbox
# @param [Array<PodTarget>] libraries @see libraries # @param [Array<PodTarget>] pod_targets @see pod_targets
# @param [Project] libraries @see libraries # @param [Project] pods_project @see pod_project
# #
def initialize(sandbox, libraries, pods_project) def initialize(sandbox, pod_targets, pods_project)
@sandbox = sandbox @sandbox = sandbox
@libraries = libraries @pod_targets = pod_targets
@pods_project = pods_project @pods_project = pods_project
end end
...@@ -113,23 +113,23 @@ module Pod ...@@ -113,23 +113,23 @@ module Pod
# #
def link_headers def link_headers
UI.message '- Linking headers' do UI.message '- Linking headers' do
libraries.each do |library| pod_targets.each do |pod_target|
library.file_accessors.each do |file_accessor| pod_target.file_accessors.each do |file_accessor|
framework_exp = /.framework\// framework_exp = /.framework\//
headers_sandbox = Pathname.new(file_accessor.spec.root.name) headers_sandbox = Pathname.new(file_accessor.spec.root.name)
library.build_headers.add_search_path(headers_sandbox, library.platform) pod_target.build_headers.add_search_path(headers_sandbox, pod_target.platform)
sandbox.public_headers.add_search_path(headers_sandbox, library.platform) sandbox.public_headers.add_search_path(headers_sandbox, pod_target.platform)
header_mappings(headers_sandbox, file_accessor, file_accessor.headers).each do |namespaced_path, files| header_mappings(headers_sandbox, file_accessor, file_accessor.headers).each do |namespaced_path, files|
library.build_headers.add_files(namespaced_path, files.reject { |f| f.to_path =~ framework_exp }, library.platform) pod_target.build_headers.add_files(namespaced_path, files.reject { |f| f.to_path =~ framework_exp }, pod_target.platform)
end end
header_mappings(headers_sandbox, file_accessor, file_accessor.public_headers).each do |namespaced_path, files| header_mappings(headers_sandbox, file_accessor, file_accessor.public_headers).each do |namespaced_path, files|
sandbox.public_headers.add_files(namespaced_path, files.reject { |f| f.to_path =~ framework_exp }, library.platform) sandbox.public_headers.add_files(namespaced_path, files.reject { |f| f.to_path =~ framework_exp }, pod_target.platform)
end end
vendored_frameworks_header_mappings(headers_sandbox, file_accessor).each do |namespaced_path, files| vendored_frameworks_header_mappings(headers_sandbox, file_accessor).each do |namespaced_path, files|
sandbox.public_headers.add_files(namespaced_path, files, library.platform) sandbox.public_headers.add_files(namespaced_path, files, pod_target.platform)
end end
end end
end end
...@@ -146,7 +146,7 @@ module Pod ...@@ -146,7 +146,7 @@ module Pod
# specs platform combinations. # specs platform combinations.
# #
def file_accessors def file_accessors
@file_accessors ||= libraries.map(&:file_accessors).flatten.compact @file_accessors ||= pod_targets.map(&:file_accessors).flatten.compact
end end
# Adds file references to the list of the paths returned by the file # Adds file references to the list of the paths returned by the file
......
...@@ -67,7 +67,7 @@ module Pod ...@@ -67,7 +67,7 @@ module Pod
def custom_build_settings def custom_build_settings
settings = {} settings = {}
if target.archs unless target.archs.empty?
settings['ARCHS'] = target.archs settings['ARCHS'] = target.archs
end end
...@@ -184,12 +184,6 @@ module Pod ...@@ -184,12 +184,6 @@ module Pod
sandbox.project sandbox.project
end end
# @return [TargetDefinition] the target definition of the library.
#
def target_definition
target.target_definition
end
# @return [PBXGroup] the group where the file references to the support # @return [PBXGroup] the group where the file references to the support
# files should be stored. # files should be stored.
# #
......
...@@ -31,6 +31,12 @@ module Pod ...@@ -31,6 +31,12 @@ module Pod
private private
# @return [TargetDefinition] the target definition of the library.
#
def target_definition
target.target_definition
end
# Ensure that vendored static frameworks and libraries are not linked # Ensure that vendored static frameworks and libraries are not linked
# twice to the aggregate target, which shares the xcconfig of the user # twice to the aggregate target, which shares the xcconfig of the user
# target. # target.
...@@ -81,7 +87,7 @@ module Pod ...@@ -81,7 +87,7 @@ module Pod
# @return [void] # @return [void]
# #
def create_bridge_support_file def create_bridge_support_file
if target_definition.podfile.generate_bridge_support? if target.podfile.generate_bridge_support?
path = target.bridge_support_path path = target.bridge_support_path
headers = native_target.headers_build_phase.files.map { |bf| sandbox.root + bf.file_ref.path } headers = native_target.headers_build_phase.files.map { |bf| sandbox.root + bf.file_ref.path }
generator = Generator::BridgeSupport.new(headers) generator = Generator::BridgeSupport.new(headers)
...@@ -101,7 +107,7 @@ module Pod ...@@ -101,7 +107,7 @@ module Pod
end end
resources_by_config = {} resources_by_config = {}
target.user_build_configurations.keys.each do |config| target.user_build_configurations.keys.each do |config|
file_accessors = library_targets.select { |t| t.include_in_build_config?(config) }.flat_map(&:file_accessors) file_accessors = library_targets.select { |t| t.include_in_build_config?(target_definition, config) }.flat_map(&:file_accessors)
resource_paths = file_accessors.flat_map { |accessor| accessor.resources.flat_map { |res| res.relative_path_from(project.path.dirname) } } resource_paths = file_accessors.flat_map { |accessor| accessor.resources.flat_map { |res| res.relative_path_from(project.path.dirname) } }
resource_bundles = file_accessors.flat_map { |accessor| accessor.resource_bundles.keys.map { |name| "${BUILT_PRODUCTS_DIR}/#{name.shellescape}.bundle" } } resource_bundles = file_accessors.flat_map { |accessor| accessor.resource_bundles.keys.map { |name| "${BUILT_PRODUCTS_DIR}/#{name.shellescape}.bundle" } }
resources_by_config[config] = (resource_paths + resource_bundles).uniq resources_by_config[config] = (resource_paths + resource_bundles).uniq
...@@ -138,11 +144,14 @@ module Pod ...@@ -138,11 +144,14 @@ module Pod
path = target.embed_frameworks_script_path path = target.embed_frameworks_script_path
frameworks_by_config = {} frameworks_by_config = {}
target.user_build_configurations.keys.each do |config| target.user_build_configurations.keys.each do |config|
frameworks_by_config[config] = target.pod_targets.select do |pod_target| relevant_pod_targets = target.pod_targets.select do |pod_target|
pod_target.include_in_build_config?(config) && pod_target.should_build? pod_target.include_in_build_config?(target_definition, config) && pod_target.should_build?
end.map(&:product_name) end
frameworks_by_config[config] = relevant_pod_targets.map do |pod_target|
"#{target_definition.label}/#{pod_target.product_name}"
end
end end
generator = Generator::EmbedFrameworksScript.new(target_definition, frameworks_by_config) generator = Generator::EmbedFrameworksScript.new(frameworks_by_config)
generator.save_as(path) generator.save_as(path)
add_file_to_support_group(path) add_file_to_support_group(path)
end end
......
...@@ -130,7 +130,7 @@ module Pod ...@@ -130,7 +130,7 @@ module Pod
bundle_target.build_configurations.each do |c| bundle_target.build_configurations.each do |c|
c.build_settings['PRODUCT_NAME'] = bundle_name c.build_settings['PRODUCT_NAME'] = bundle_name
if target.requires_frameworks? if target.requires_frameworks? && target.scoped?
c.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir c.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir
end end
end end
...@@ -234,7 +234,7 @@ module Pod ...@@ -234,7 +234,7 @@ module Pod
flags << '-DOS_OBJECT_USE_OBJC=0' flags << '-DOS_OBJECT_USE_OBJC=0'
end end
end end
if target_definition.inhibits_warnings_for_pod?(consumer.spec.root.name) if target.inhibit_warnings?
flags << '-w -Xanalyzer -analyzer-disable-all-checks' flags << '-w -Xanalyzer -analyzer-disable-all-checks'
end end
flags * ' ' flags * ' '
......
...@@ -6,11 +6,6 @@ module Pod ...@@ -6,11 +6,6 @@ module Pod
# This class is used to represent both the targets and their libraries. # This class is used to represent both the targets and their libraries.
# #
class Target class Target
# @return [TargetDefinition] the target definition of the Podfile that
# generated this target.
#
attr_reader :target_definition
# @return [Sandbox] The sandbox where the Pods should be installed. # @return [Sandbox] The sandbox where the Pods should be installed.
# #
attr_reader :sandbox attr_reader :sandbox
...@@ -21,6 +16,12 @@ module Pod ...@@ -21,6 +16,12 @@ module Pod
attr_accessor :host_requires_frameworks attr_accessor :host_requires_frameworks
alias_method :host_requires_frameworks?, :host_requires_frameworks alias_method :host_requires_frameworks?, :host_requires_frameworks
# Initialize a new target
#
def initialize
@archs = []
end
# @return [String] the name of the library. # @return [String] the name of the library.
# #
def name def name
...@@ -110,13 +111,7 @@ module Pod ...@@ -110,13 +111,7 @@ module Pod
# #
attr_accessor :native_target attr_accessor :native_target
# @return [Platform] the platform for this library. # @return [Array<String>] The value for the ARCHS build setting.
#
def platform
@platform ||= target_definition.platform
end
# @return [String] The value for the ARCHS build setting.
# #
attr_accessor :archs attr_accessor :archs
...@@ -191,23 +186,6 @@ module Pod ...@@ -191,23 +186,6 @@ module Pod
support_files_dir + "#{label}-dummy.m" support_files_dir + "#{label}-dummy.m"
end end
# @return [String] The configuration build dir, if the target is integrated
# as framework.
#
# @note Namespace the pod target product with its target definition name.
# Pod target products are named after their specs. The namespacing
# cannot directly happen in the product name itself, because this
# must be equal to the module name and this will be used in source
# code, which should stay agnostic over the dependency manager.
# We need namespacing at all because multiple targets can exist for
# the same podspec and their products should not collide. This
# happens when multiple user targets require the same pod, because
# they could require different sets of subspecs.
#
def configuration_build_dir
"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/#{target_definition.label}"
end
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
private private
......
...@@ -3,12 +3,17 @@ module Pod ...@@ -3,12 +3,17 @@ module Pod
# of the single Pods. The client targets will then depend on this one. # of the single Pods. The client targets will then depend on this one.
# #
class AggregateTarget < Target class AggregateTarget < Target
# @return [TargetDefinition] the target definition of the Podfile that
# generated this target.
attr_reader :target_definition
# Initialize a new instance # Initialize a new instance
# #
# @param [TargetDefinition] target_definition @see target_definition # @param [TargetDefinition] target_definition @see target_definition
# @param [Sandbox] sandbox @see sandbox # @param [Sandbox] sandbox @see sandbox
# #
def initialize(target_definition, sandbox) def initialize(target_definition, sandbox)
super()
@target_definition = target_definition @target_definition = target_definition
@sandbox = sandbox @sandbox = sandbox
@pod_targets = [] @pod_targets = []
...@@ -30,6 +35,18 @@ module Pod ...@@ -30,6 +35,18 @@ module Pod
c99ext_identifier(label) c99ext_identifier(label)
end end
# @return [Platform] the platform for this target.
#
def platform
@platform ||= target_definition.platform
end
# @return [Podfile] The podfile which declares the dependency
#
def podfile
target_definition.podfile
end
# @return [Pathname] the folder where the client is stored used for # @return [Pathname] the folder where the client is stored used for
# computing the relative paths. If integrating it should be the # computing the relative paths. If integrating it should be the
# folder where the user project is stored, otherwise it should # folder where the user project is stored, otherwise it should
...@@ -94,7 +111,7 @@ module Pod ...@@ -94,7 +111,7 @@ module Pod
# #
def pod_targets_for_build_configuration(build_configuration) def pod_targets_for_build_configuration(build_configuration)
pod_targets.select do |pod_target| pod_targets.select do |pod_target|
pod_target.include_in_build_config?(build_configuration) pod_target.include_in_build_config?(target_definition, build_configuration)
end end
end end
...@@ -182,6 +199,13 @@ module Pod ...@@ -182,6 +199,13 @@ module Pod
"${SRCROOT}/#{relative_to_srcroot(embed_frameworks_script_path)}" "${SRCROOT}/#{relative_to_srcroot(embed_frameworks_script_path)}"
end end
# @return [String] The scoped configuration build dir, relevant if the
# target is integrated as framework.
#
def scoped_configuration_build_dir
"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/#{target_definition.label}"
end
private private
# @!group Private Helpers # @!group Private Helpers
......
...@@ -3,31 +3,87 @@ module Pod ...@@ -3,31 +3,87 @@ module Pod
# A pod can have one or more activated spec/subspecs. # A pod can have one or more activated spec/subspecs.
# #
class PodTarget < Target class PodTarget < Target
# @return [Specification] the spec for the target. # @return [Array<Specification>] the spec and subspecs for the target.
# #
attr_reader :specs attr_reader :specs
# @return [Array<PBXNativeTarget>] the target definitions of the Podfile
# that generated this target.
#
attr_reader :target_definitions
# @return [HeadersStore] the header directory for the target. # @return [HeadersStore] the header directory for the target.
# #
attr_reader :build_headers attr_reader :build_headers
# @param [Specification] spec @see spec # @return [Bool] whether the target needs to be scoped by target definition,
# @param [TargetDefinition] target_definition @see target_definition # because the spec is used with different subspec sets across them.
#
# @note For frameworks the target products of {PodTarget}s are named
# after their specs. The namespacing cannot directly happen in
# the product name itself, because this must be equal to the module
# name and this will be used in source code, which should stay
# agnostic over the dependency manager.
# We need namespacing because multiple targets can exist for the
# same podspec and their products should not collide. This
# duplication is needed when multiple user targets have the same
# dependency, but they require different sets of subspecs or they
# are on different platforms.
#
attr_reader :scoped
alias_method :scoped?, :scoped
# @param [Array<Specification>] @spec #see spec
# @param [Array<TargetDefinition>] target_definitions @see target_definitions
# @param [Sandbox] sandbox @see sandbox # @param [Sandbox] sandbox @see sandbox
# @param [Bool] scoped @see scoped
# #
def initialize(specs, target_definition, sandbox) def initialize(specs, target_definitions, sandbox, scoped = false)
raise "Can't initialize a PodTarget without specs!" if specs.nil? || specs.empty?
raise "Can't initialize a PodTarget without TargetDefinition!" if target_definitions.nil? || target_definitions.empty?
super()
@specs = specs @specs = specs
@target_definition = target_definition @target_definitions = target_definitions
@sandbox = sandbox @sandbox = sandbox
@scoped = scoped
@build_headers = Sandbox::HeadersStore.new(sandbox, 'Private') @build_headers = Sandbox::HeadersStore.new(sandbox, 'Private')
@file_accessors = [] @file_accessors = []
@resource_bundle_targets = [] @resource_bundle_targets = []
end end
# @return [Array<PodTarget>] a scoped copy for each target definition.
#
def scoped
target_definitions.map do |target_definition|
PodTarget.new(specs, [target_definition], sandbox, true).tap do |target|
target.file_accessors = file_accessors
target.user_build_configurations = user_build_configurations
target.native_target = native_target
target.archs = archs
end
end
end
# @return [String] the label for the target. # @return [String] the label for the target.
# #
def label def label
"#{target_definition.label}-#{root_spec.name}" if scoped?
"#{target_definitions.first.label}-#{root_spec.name}"
else
root_spec.name
end
end
# @return [Platform] the platform for this target.
#
def platform
@platform ||= target_definitions.first.platform
end
# @return [Podfile] The podfile which declares the dependency.
#
def podfile
target_definitions.first.podfile
end end
# @return [String] The name to use for the source code module constructed # @return [String] The name to use for the source code module constructed
...@@ -103,13 +159,16 @@ module Pod ...@@ -103,13 +159,16 @@ module Pod
end end
# Checks if the target should be included in the build configuration with # Checks if the target should be included in the build configuration with
# the given name. # the given name of a given target definition.
#
# @param [TargetDefinition] target_definition
# The target definition to check.
# #
# @param [String] configuration_name # @param [String] configuration_name
# The name of the build configuration. # The name of the build configuration.
# #
def include_in_build_config?(configuration_name) def include_in_build_config?(target_definition, configuration_name)
whitelists = target_definition_dependencies.map do |dependency| whitelists = target_definition_dependencies(target_definition).map do |dependency|
target_definition.pod_whitelisted_for_configuration?(dependency.name, configuration_name) target_definition.pod_whitelisted_for_configuration?(dependency.name, configuration_name)
end.uniq end.uniq
...@@ -125,14 +184,51 @@ module Pod ...@@ -125,14 +184,51 @@ module Pod
end end
end end
# Checks if warnings should be inhibited for this pod.
#
# @return [Bool]
#
def inhibit_warnings?
whitelists = target_definitions.map do |target_definition|
target_definition.inhibits_warnings_for_pod?(root_spec.name)
end.uniq
if whitelists.empty?
return false
elsif whitelists.count == 1
whitelists.first
else
UI.warn "The pod `#{pod_name}` is linked to different targets " \
"(#{target_definitions.map(&:label)}), which contain different " \
'settings to inhibit warnings. CocoaPods does not currently ' \
'support different settings and will fall back to your preference ' \
'set in the root target definition.'
return podfile.root_target_definitions.first.inhibits_warnings_for_pod?(root_spec.name)
end
end
# @return [String] The configuration build dir, relevant if the target is
# integrated as framework.
#
def configuration_build_dir
if scoped?
"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/#{target_definitions.first.label}"
else
'$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)'
end
end
private private
# @param [TargetDefinition] target_definition
# The target definition to check.
#
# @return [Array<Dependency>] The dependency of the target definition for # @return [Array<Dependency>] The dependency of the target definition for
# this Pod. Return an empty array if the Pod is not a direct # this Pod. Return an empty array if the Pod is not a direct
# dependency of the target definition but the dependency of one or # dependency of the target definition but the dependency of one or
# more Pods. # more Pods.
# #
def target_definition_dependencies def target_definition_dependencies(target_definition)
target_definition.dependencies.select do |dependency| target_definition.dependencies.select do |dependency|
Specification.root_name(dependency.name) == pod_name Specification.root_name(dependency.name) == pod_name
end end
......
Subproject commit 0ce7a32ea385cf641ef76bd7f5a8166c554086d3 Subproject commit 9793ea0fa86ceb9656ed768e58fa3d6db1407dd7
//
// main.swift
// CLITool
//
// Created by Marius Rackwitz on 3.6.15.
// Copyright (c) 2015 LJR Software Limited. All rights reserved.
//
import Foundation
println("Hello, World!")
...@@ -114,7 +114,7 @@ ...@@ -114,7 +114,7 @@
51E94E06164472080035348C /* Project object */ = { 51E94E06164472080035348C /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0450; LastUpgradeCheck = 0630;
ORGANIZATIONNAME = CocoaPods; ORGANIZATIONNAME = CocoaPods;
}; };
buildConfigurationList = 51E94E09164472080035348C /* Build configuration list for PBXProject "Sample Lib" */; buildConfigurationList = 51E94E09164472080035348C /* Build configuration list for PBXProject "Sample Lib" */;
...@@ -168,6 +168,7 @@ ...@@ -168,6 +168,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 6.0; IPHONEOS_DEPLOYMENT_TARGET = 6.0;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
}; };
name = Debug; name = Debug;
...@@ -235,6 +236,7 @@ ...@@ -235,6 +236,7 @@
51E94E1F164472090035348C /* Release */, 51E94E1F164472090035348C /* Release */,
); );
defaultConfigurationIsVisible = 0; defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
}; };
/* End XCConfigurationList section */ /* End XCConfigurationList section */
}; };
......
...@@ -109,36 +109,31 @@ def fixture_spec(name) ...@@ -109,36 +109,31 @@ def fixture_spec(name)
Pod::Specification.from_file(file) Pod::Specification.from_file(file)
end end
def fixture_file_accessor(name, platform = :ios) def fixture_file_accessor(spec_or_name, platform = Pod::Platform.ios)
file = SpecHelper::Fixture.fixture(name) spec = spec_or_name.is_a?(Pod::Specification) ? spec_or_name : fixture_spec(spec_or_name)
spec = Pod::Specification.from_file(file) path_list = Pod::Sandbox::PathList.new(spec.defined_in_file.dirname)
path_list = Pod::Sandbox::PathList.new(file.dirname)
Pod::Sandbox::FileAccessor.new(path_list, spec.consumer(platform)) Pod::Sandbox::FileAccessor.new(path_list, spec.consumer(platform))
end end
def fixture_target_definition(podfile = nil, &block) def fixture_target_definition(name = 'Pods', platform = Pod::Platform.ios)
podfile ||= Pod::Podfile.new(&block) Pod::Podfile::TargetDefinition.new(name, Pod::Podfile.new, 'name' => name, 'platform' => platform)
Pod::Podfile::TargetDefinition.new('Pods', podfile)
end end
def fixture_pod_target(spec_or_name, platform = :ios, target_definition = nil) def fixture_pod_target(spec_or_name, target_definition = nil)
spec = spec_or_name.is_a?(Pod::Specification) ? spec_or_name : fixture_spec(spec_or_name) spec = spec_or_name.is_a?(Pod::Specification) ? spec_or_name : fixture_spec(spec_or_name)
target_definition ||= fixture_target_definition target_definition ||= fixture_target_definition
target_definition.store_pod(spec.name) target_definition.store_pod(spec.name)
Pod::PodTarget.new([spec], target_definition, config.sandbox).tap do |pod_target| Pod::PodTarget.new([spec], [target_definition], config.sandbox).tap do |pod_target|
pod_target.stubs(:platform).returns(platform) pod_target.file_accessors << fixture_file_accessor(spec, pod_target.platform)
pod_target.file_accessors << fixture_file_accessor(spec.defined_in_file, platform) consumer = spec.consumer(pod_target.platform)
consumer = spec.consumer(platform)
pod_target.spec_consumers << consumer pod_target.spec_consumers << consumer
end end
end end
def fixture_aggregate_target(pod_targets = [], platform = :ios, target_definition = nil) def fixture_aggregate_target(pod_targets = [], target_definition = nil)
target_definition ||= pod_targets.map(&:target_definition).first || fixture_target_definition target_definition ||= pod_targets.flat_map(&:target_definitions).first || fixture_target_definition
target = Pod::AggregateTarget.new(target_definition, config.sandbox) target = Pod::AggregateTarget.new(target_definition, config.sandbox)
target.client_root = config.sandbox.root.dirname target.client_root = config.sandbox.root.dirname
version ||= (platform == :ios ? '4.3' : '10.6')
target.stubs(:platform).returns(Pod::Platform.new(platform, version))
target.pod_targets = pod_targets target.pod_targets = pod_targets
target target
end end
......
...@@ -9,6 +9,10 @@ module SpecHelper ...@@ -9,6 +9,10 @@ module SpecHelper
fixture_copy_path + "#{fixture_name}.xcodeproj" fixture_copy_path + "#{fixture_name}.xcodeproj"
end end
def self.test_repo_url
'https://github.com/CocoaPods/test_repo.git'
end
module Fixture module Fixture
ROOT = ::ROOT + 'spec/fixtures' ROOT = ::ROOT + 'spec/fixtures'
......
...@@ -184,6 +184,14 @@ module Pod ...@@ -184,6 +184,14 @@ module Pod
@config.should.lock_pod_source @config.should.lock_pod_source
end end
it 'integrates a user target' do
@config.should.integrate_targets
end
it 'de-duplicates targets' do
@config.should.deduplicate_targets
end
it 'returns the cache root' do it 'returns the cache root' do
@config.cache_root.should == Pathname.new(File.join(ENV['HOME'], 'Library/Caches/CocoaPods')) @config.cache_root.should == Pathname.new(File.join(ENV['HOME'], 'Library/Caches/CocoaPods'))
end end
......
...@@ -3,15 +3,14 @@ require File.expand_path('../../../spec_helper', __FILE__) ...@@ -3,15 +3,14 @@ require File.expand_path('../../../spec_helper', __FILE__)
module Pod module Pod
describe Generator::EmbedFrameworksScript do describe Generator::EmbedFrameworksScript do
it 'returns the embed frameworks script' do it 'returns the embed frameworks script' do
target_definition = Podfile::TargetDefinition.new(:default, nil)
frameworks = { frameworks = {
'Debug' => %w(Loopback.framework Reveal.framework), 'Debug' => %w(Pods/Loopback.framework Reveal.framework),
'Release' => %w(CrashlyticsFramework.framework), 'Release' => %w(CrashlyticsFramework.framework),
} }
generator = Pod::Generator::EmbedFrameworksScript.new(target_definition, frameworks) generator = Pod::Generator::EmbedFrameworksScript.new(frameworks)
generator.send(:script).should.include <<-eos.strip_heredoc generator.send(:script).should.include <<-eos.strip_heredoc
if [[ "$CONFIGURATION" == "Debug" ]]; then if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework 'Loopback.framework' install_framework 'Pods/Loopback.framework'
install_framework 'Reveal.framework' install_framework 'Reveal.framework'
fi fi
eos eos
......
...@@ -5,7 +5,7 @@ module Pod ...@@ -5,7 +5,7 @@ module Pod
before do before do
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
target_definition = Podfile::TargetDefinition.new(:default, nil) target_definition = Podfile::TargetDefinition.new(:default, nil)
@pod_target = PodTarget.new([spec], target_definition, config.sandbox) @pod_target = PodTarget.new([spec], [target_definition], config.sandbox)
@gen = Generator::ModuleMap.new(@pod_target) @gen = Generator::ModuleMap.new(@pod_target)
end end
...@@ -14,7 +14,7 @@ module Pod ...@@ -14,7 +14,7 @@ module Pod
@gen.save_as(path) @gen.save_as(path)
path.read.should == <<-EOS.strip_heredoc path.read.should == <<-EOS.strip_heredoc
framework module BananaLib { framework module BananaLib {
umbrella header "Pods-default-BananaLib-umbrella.h" umbrella header "BananaLib-umbrella.h"
export * export *
module * { export * } module * { export * }
...@@ -26,7 +26,7 @@ module Pod ...@@ -26,7 +26,7 @@ module Pod
@gen.stubs(:private_headers).returns(['Private.h']) @gen.stubs(:private_headers).returns(['Private.h'])
@gen.generate.should == <<-EOS.strip_heredoc @gen.generate.should == <<-EOS.strip_heredoc
framework module BananaLib { framework module BananaLib {
umbrella header "Pods-default-BananaLib-umbrella.h" umbrella header "BananaLib-umbrella.h"
export * export *
module * { export * } module * { export * }
......
...@@ -8,12 +8,16 @@ module Pod ...@@ -8,12 +8,16 @@ module Pod
fixture_spec('banana-lib/BananaLib.podspec') fixture_spec('banana-lib/BananaLib.podspec')
end end
def pod_target(spec)
fixture_pod_target(spec)
end
before do before do
@spec = spec @spec = spec
@pod_target = fixture_pod_target(@spec) @pod_target = pod_target(@spec)
@consumer = @pod_target.spec_consumers.last @consumer = @pod_target.spec_consumers.last
@target = fixture_aggregate_target([@pod_target]) @target = fixture_aggregate_target([@pod_target])
@target.target_definition.should == @pod_target.target_definition @target.target_definition.should == @pod_target.target_definitions.first
@target.target_definition.whitelist_pod_for_configuration(@spec.name, 'Release') @target.target_definition.whitelist_pod_for_configuration(@spec.name, 'Release')
@podfile = @target.target_definition.podfile @podfile = @target.target_definition.podfile
@generator = AggregateXCConfig.new(@target, 'Release') @generator = AggregateXCConfig.new(@target, 'Release')
...@@ -103,9 +107,21 @@ module Pod ...@@ -103,9 +107,21 @@ module Pod
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected @xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end end
describe 'with a scoped pod target' do
def pod_target(spec)
fixture_pod_target(spec).scoped.first
end
it 'links the pod targets with the aggregate target' do it 'links the pod targets with the aggregate target' do
@xcconfig.to_hash['OTHER_LDFLAGS'].should.include '-l"Pods-BananaLib"' @xcconfig.to_hash['OTHER_LDFLAGS'].should.include '-l"Pods-BananaLib"'
end end
end
describe 'with an unscoped pod target' do
it 'links the pod targets with the aggregate target' do
@xcconfig.to_hash['OTHER_LDFLAGS'].should.include '-l"BananaLib"'
end
end
it 'does not links the pod targets with the aggregate target for non-whitelisted configuration' do it 'does not links the pod targets with the aggregate target for non-whitelisted configuration' do
@generator = AggregateXCConfig.new(@target, 'Debug') @generator = AggregateXCConfig.new(@target, 'Debug')
...@@ -139,6 +155,11 @@ module Pod ...@@ -139,6 +155,11 @@ module Pod
@xcconfig.to_hash['PODS_FRAMEWORK_BUILD_PATH'].should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods' @xcconfig.to_hash['PODS_FRAMEWORK_BUILD_PATH'].should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods'
end end
describe 'with a scoped pod target' do
def pod_target(spec)
fixture_pod_target(spec).scoped.first
end
it 'adds the framework build path to the xcconfig, with quotes, as framework search paths' do 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_FRAMEWORK_BUILD_PATH"' @xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "$PODS_FRAMEWORK_BUILD_PATH"'
end end
...@@ -147,6 +168,18 @@ module Pod ...@@ -147,6 +168,18 @@ module Pod
expected = '$(inherited) -iquote "$PODS_FRAMEWORK_BUILD_PATH/OrangeFramework.framework/Headers"' expected = '$(inherited) -iquote "$PODS_FRAMEWORK_BUILD_PATH/OrangeFramework.framework/Headers"'
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected @xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end end
end
describe 'with an unscoped pod target' do
it 'adds the framework build path to the xcconfig, with quotes, as framework search paths' do
@xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.be.nil
end
it 'adds the framework header paths to the xcconfig, with quotes, as local headers' do
expected = '$(inherited) -iquote "$CONFIGURATION_BUILD_DIR/OrangeFramework.framework/Headers"'
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end
end
it 'links the pod targets with the aggregate target' do it 'links the pod targets with the aggregate target' do
@xcconfig.to_hash['OTHER_LDFLAGS'].should.include '-framework "OrangeFramework"' @xcconfig.to_hash['OTHER_LDFLAGS'].should.include '-framework "OrangeFramework"'
...@@ -195,7 +228,7 @@ module Pod ...@@ -195,7 +228,7 @@ module Pod
@consumer_b.stubs(:user_target_xcconfig).returns('ENABLE_HEADER_DEPENDENCIES' => 'NO') @consumer_b.stubs(:user_target_xcconfig).returns('ENABLE_HEADER_DEPENDENCIES' => 'NO')
@xcconfig = @generator.generate @xcconfig = @generator.generate
UI.warnings.should.include 'Can\'t merge user_target_xcconfig for pod targets: ' \ UI.warnings.should.include 'Can\'t merge user_target_xcconfig for pod targets: ' \
'["Pods-BananaLib", "Pods-OrangeFramework"]. Boolean build setting '\ '["BananaLib", "OrangeFramework"]. Boolean build setting '\
'ENABLE_HEADER_DEPENDENCIES has different values.' 'ENABLE_HEADER_DEPENDENCIES has different values.'
end end
end end
...@@ -229,7 +262,7 @@ module Pod ...@@ -229,7 +262,7 @@ module Pod
@consumer_b.stubs(:user_target_xcconfig).returns('STRIP_STYLE' => 'all') @consumer_b.stubs(:user_target_xcconfig).returns('STRIP_STYLE' => 'all')
@xcconfig = @generator.generate @xcconfig = @generator.generate
UI.warnings.should.include 'Can\'t merge user_target_xcconfig for pod targets: ' \ UI.warnings.should.include 'Can\'t merge user_target_xcconfig for pod targets: ' \
'["Pods-BananaLib", "Pods-OrangeFramework"]. Singular build setting '\ '["BananaLib", "OrangeFramework"]. Singular build setting '\
'STRIP_STYLE has different values.' 'STRIP_STYLE has different values.'
end end
end end
......
...@@ -7,14 +7,11 @@ module Pod ...@@ -7,14 +7,11 @@ module Pod
describe 'in general' do describe 'in general' do
before do before do
@spec = fixture_spec('banana-lib/BananaLib.podspec') @spec = fixture_spec('banana-lib/BananaLib.podspec')
@consumer = @spec.consumer(:ios) @pod_target = fixture_pod_target(@spec)
target_definition = Podfile::TargetDefinition.new('Pods', nil) @consumer = @pod_target.spec_consumers.first
@pod_target = PodTarget.new([@spec], target_definition, config.sandbox) @podfile = @pod_target.podfile
@pod_target.stubs(:platform).returns(:ios)
public_xcconfig = Xcodeproj::Config.new('OTHER_LDFLAGS' => '-framework SystemConfiguration') public_xcconfig = Xcodeproj::Config.new('OTHER_LDFLAGS' => '-framework SystemConfiguration')
@generator = PrivatePodXCConfig.new(@pod_target, public_xcconfig) @generator = PrivatePodXCConfig.new(@pod_target, public_xcconfig)
@podfile = Podfile.new
@pod_target.target_definition.stubs(:podfile).returns(@podfile)
@xcconfig = @generator.generate @xcconfig = @generator.generate
end end
......
...@@ -6,23 +6,16 @@ module Pod ...@@ -6,23 +6,16 @@ module Pod
describe PublicPodXCConfig do describe PublicPodXCConfig do
before do before do
@spec = fixture_spec('banana-lib/BananaLib.podspec') @spec = fixture_spec('banana-lib/BananaLib.podspec')
@target_definition = Podfile::TargetDefinition.new('Pods', nil) @pod_target = fixture_pod_target(@spec)
@pod_target = PodTarget.new([@spec], @target_definition, config.sandbox)
@pod_target.stubs(:platform).returns(:ios)
@generator = PublicPodXCConfig.new(@pod_target) @generator = PublicPodXCConfig.new(@pod_target)
@podfile = Podfile.new
@spec.xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' } @spec.xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' }
@spec.frameworks = ['QuartzCore'] @spec.frameworks = ['QuartzCore']
@spec.weak_frameworks = ['iAd'] @spec.weak_frameworks = ['iAd']
@spec.libraries = ['xml2'] @spec.libraries = ['xml2']
file_accessors = [Sandbox::FileAccessor.new(fixture('banana-lib'), @spec.consumer(:ios))]
# vendored_framework_paths = [config.sandbox.root + 'BananaLib/BananaLib.framework'] # vendored_framework_paths = [config.sandbox.root + 'BananaLib/BananaLib.framework']
# Sandbox::FileAccessor.any_instance.stubs(:vendored_frameworks).returns(vendored_framework_paths) # Sandbox::FileAccessor.any_instance.stubs(:vendored_frameworks).returns(vendored_framework_paths)
@pod_target.target_definition.stubs(:podfile).returns(@podfile)
@pod_target.stubs(:file_accessors).returns(file_accessors)
@xcconfig = @generator.generate @xcconfig = @generator.generate
end end
......
...@@ -13,17 +13,15 @@ module Pod ...@@ -13,17 +13,15 @@ module Pod
describe '::default_ld_flags' do describe '::default_ld_flags' do
it 'returns the default linker flags' do it 'returns the default linker flags' do
podfile = stub(:set_arc_compatibility_flag? => false) podfile = stub(:set_arc_compatibility_flag? => false)
target_definition = stub(:podfile => podfile) target = stub(:podfile => podfile)
target = stub(:target_definition => target_definition)
result = @sut.default_ld_flags(target) result = @sut.default_ld_flags(target)
result.should == '-ObjC' result.should == '-ObjC'
end end
it 'includes the ARC compatibility flag if required by the Podfile' do it 'includes the ARC compatibility flag if required by the Podfile' do
podfile = stub(:set_arc_compatibility_flag? => true) podfile = stub(:set_arc_compatibility_flag? => true)
target_definition = stub(:podfile => podfile)
spec_consumer = stub(:requires_arc? => true) spec_consumer = stub(:requires_arc? => true)
target = stub(:target_definition => target_definition, :spec_consumers => [spec_consumer]) target = stub(:podfile => podfile, :spec_consumers => [spec_consumer])
result = @sut.default_ld_flags(target) result = @sut.default_ld_flags(target)
result.should == '-ObjC -fobjc-arc' result.should == '-ObjC -fobjc-arc'
end end
......
This diff is collapsed.
This diff is collapsed.
...@@ -3,10 +3,8 @@ require File.expand_path('../../../spec_helper', __FILE__) ...@@ -3,10 +3,8 @@ require File.expand_path('../../../spec_helper', __FILE__)
module Pod module Pod
describe Installer::FileReferencesInstaller do describe Installer::FileReferencesInstaller do
before do before do
@file_accessor = fixture_file_accessor('banana-lib/BananaLib.podspec') @pod_target = fixture_pod_target('banana-lib/BananaLib.podspec')
@pod_target = PodTarget.new([], nil, config.sandbox) @file_accessor = @pod_target.file_accessors.first
@pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@pod_target.file_accessors = [@file_accessor]
@project = Project.new(config.sandbox.project_path) @project = Project.new(config.sandbox.project_path)
@project.add_pod_group('BananaLib', fixture('banana-lib')) @project.add_pod_group('BananaLib', fixture('banana-lib'))
@installer = Installer::FileReferencesInstaller.new(config.sandbox, [@pod_target], @project) @installer = Installer::FileReferencesInstaller.new(config.sandbox, [@pod_target], @project)
...@@ -79,17 +77,17 @@ module Pod ...@@ -79,17 +77,17 @@ module Pod
describe 'Private Helpers' do describe 'Private Helpers' do
describe '#file_accessors' do describe '#file_accessors' do
it 'returns the file accessors' do it 'returns the file accessors' do
pod_target_1 = PodTarget.new([], nil, config.sandbox) pod_target_1 = PodTarget.new([stub('Spec')], [stub('TargetDefinition')], config.sandbox)
pod_target_1.file_accessors = [fixture_file_accessor('banana-lib/BananaLib.podspec')] pod_target_1.file_accessors = [fixture_file_accessor('banana-lib/BananaLib.podspec')]
pod_target_2 = PodTarget.new([], nil, config.sandbox) pod_target_2 = PodTarget.new([stub('Spec')], [stub('TargetDefinition')], config.sandbox)
pod_target_2.file_accessors = [fixture_file_accessor('banana-lib/BananaLib.podspec')] pod_target_2.file_accessors = [fixture_file_accessor('banana-lib/BananaLib.podspec')]
installer = Installer::FileReferencesInstaller.new(config.sandbox, [pod_target_1, pod_target_2], @project) installer = Installer::FileReferencesInstaller.new(config.sandbox, [pod_target_1, pod_target_2], @project)
roots = installer.send(:file_accessors).map { |fa| fa.path_list.root } roots = installer.send(:file_accessors).map { |fa| fa.path_list.root }
roots.should == [fixture('banana-lib'), fixture('banana-lib')] roots.should == [fixture('banana-lib'), fixture('banana-lib')]
end end
it 'handles libraries empty libraries without file accessors' do it 'handles pods without file accessors' do
pod_target_1 = PodTarget.new([], nil, config.sandbox) pod_target_1 = PodTarget.new([stub('Spec')], [stub('TargetDefinition')], config.sandbox)
pod_target_1.file_accessors = [] pod_target_1.file_accessors = []
installer = Installer::FileReferencesInstaller.new(config.sandbox, [pod_target_1], @project) installer = Installer::FileReferencesInstaller.new(config.sandbox, [pod_target_1], @project)
installer.send(:file_accessors).should == [] installer.send(:file_accessors).should == []
......
...@@ -8,7 +8,7 @@ module Pod ...@@ -8,7 +8,7 @@ module Pod
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
target_definition = Podfile::TargetDefinition.new('Pods', nil) target_definition = Podfile::TargetDefinition.new('Pods', nil)
pod_target = PodTarget.new([spec], target_definition, config.sandbox) pod_target = PodTarget.new([spec], [target_definition], config.sandbox)
umbrella = AggregateTarget.new(target_definition, config.sandbox) umbrella = AggregateTarget.new(target_definition, config.sandbox)
umbrella.user_project_path = '/path/project.xcodeproj' umbrella.user_project_path = '/path/project.xcodeproj'
umbrella.user_target_uuids = ['UUID'] umbrella.user_target_uuids = ['UUID']
......
...@@ -28,7 +28,7 @@ module Pod ...@@ -28,7 +28,7 @@ module Pod
@target.client_root = config.sandbox.root.dirname @target.client_root = config.sandbox.root.dirname
@target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug } @target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug }
@pod_target = PodTarget.new([@spec], @target_definition, config.sandbox) @pod_target = PodTarget.new([@spec], [@target_definition], config.sandbox)
@pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0')) @pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@pod_target.user_build_configurations = @target.user_build_configurations @pod_target.user_build_configurations = @target.user_build_configurations
@pod_target.file_accessors = [file_accessor] @pod_target.file_accessors = [file_accessor]
......
...@@ -6,7 +6,7 @@ module Pod ...@@ -6,7 +6,7 @@ module Pod
before do before do
config.sandbox.prepare config.sandbox.prepare
@podfile = Podfile.new do @podfile = Podfile.new do
platform :ios platform :ios, '6.0'
xcodeproj 'dummy' xcodeproj 'dummy'
end end
@target_definition = @podfile.target_definitions['Pods'] @target_definition = @podfile.target_definitions['Pods']
...@@ -25,8 +25,7 @@ module Pod ...@@ -25,8 +25,7 @@ module Pod
@project.add_file_reference(resource, group) @project.add_file_reference(resource, group)
end end
@pod_target = PodTarget.new([@spec], @target_definition, config.sandbox) @pod_target = PodTarget.new([@spec], [@target_definition], config.sandbox)
@pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@pod_target.file_accessors = [file_accessor] @pod_target.file_accessors = [file_accessor]
@pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release } @pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release }
@installer = Installer::PodTargetInstaller.new(config.sandbox, @pod_target) @installer = Installer::PodTargetInstaller.new(config.sandbox, @pod_target)
...@@ -34,26 +33,6 @@ module Pod ...@@ -34,26 +33,6 @@ module Pod
@spec.prefix_header_contents = '#import "BlocksKit.h"' @spec.prefix_header_contents = '#import "BlocksKit.h"'
end end
it 'adds file references for the support files of the target' do
@installer.install!
@project.support_files_group
group = @project['Pods/BananaLib/Support Files']
group.children.map(&:display_name).sort.should == [
'Pods-BananaLib-Private.xcconfig',
'Pods-BananaLib-dummy.m',
'Pods-BananaLib-prefix.pch',
'Pods-BananaLib.xcconfig',
]
end
#--------------------------------------#
it 'adds the target for the static library to the project' do
@installer.install!
@project.targets.count.should == 1
@project.targets.first.name.should == 'Pods-BananaLib'
end
it 'sets the platform and the deployment target for iOS targets' do it 'sets the platform and the deployment target for iOS targets' do
@installer.install! @installer.install!
target = @project.targets.first target = @project.targets.first
...@@ -100,6 +79,40 @@ module Pod ...@@ -100,6 +79,40 @@ module Pod
#--------------------------------------# #--------------------------------------#
it 'adds framework resources to the framework target' do
@pod_target.stubs(:requires_frameworks? => true)
@installer.install!
resources = @project.targets.first.resources_build_phase.files
resources.count.should > 0
resource = resources.find { |res| res.file_ref.path.include?('logo-sidebar.png') }
resource.should.be.not.nil
end
#--------------------------------------#
describe 'with a scoped pod target' do
before do
@pod_target = @pod_target.scoped.first
@installer = Installer::PodTargetInstaller.new(config.sandbox, @pod_target)
end
it 'adds file references for the support files of the target' do
@installer.install!
group = @project['Pods/BananaLib/Support Files']
group.children.map(&:display_name).sort.should == [
'Pods-BananaLib-Private.xcconfig',
'Pods-BananaLib-dummy.m',
'Pods-BananaLib-prefix.pch',
'Pods-BananaLib.xcconfig',
]
end
it 'adds the target for the static library to the project' do
@installer.install!
@project.targets.count.should == 1
@project.targets.first.name.should == 'Pods-BananaLib'
end
it 'adds the resource bundle targets' do it 'adds the resource bundle targets' do
@pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => []) @pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => [])
@installer.install! @installer.install!
...@@ -109,25 +122,59 @@ module Pod ...@@ -109,25 +122,59 @@ module Pod
bundle_target.product_reference.path.should == 'banana_bundle.bundle' bundle_target.product_reference.path.should == 'banana_bundle.bundle'
end end
it 'adds framework resources to the framework target' do it 'adds the build configurations to the resources bundle targets' do
@pod_target.stubs(:requires_frameworks? => true) @pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => [])
@installer.install! @installer.install!
resources = @project.targets.first.resources_build_phase.files bundle_target = @project.targets.find { |t| t.name == 'Pods-BananaLib-banana_bundle' }
resources.count.should > 0
resource = resources.find { |res| res.file_ref.path.include?('logo-sidebar.png') } file = config.sandbox.root + @pod_target.xcconfig_private_path
resource.should.be.not.nil bundle_target.build_configurations.each do |bc|
bc.base_configuration_reference.real_path.should == file
end
end
end
#--------------------------------------#
describe 'with an unscoped pod target' do
it 'adds file references for the support files of the target' do
@installer.install!
@project.support_files_group
group = @project['Pods/BananaLib/Support Files']
group.children.map(&:display_name).sort.should == [
'BananaLib-Private.xcconfig',
'BananaLib-dummy.m',
'BananaLib-prefix.pch',
'BananaLib.xcconfig',
]
end
it 'adds the target for the static library to the project' do
@installer.install!
@project.targets.count.should == 1
@project.targets.first.name.should == 'BananaLib'
end
it 'adds the resource bundle targets' do
@pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => [])
@installer.install!
bundle_target = @project.targets.find { |t| t.name == 'BananaLib-banana_bundle' }
bundle_target.should.be.an.instance_of Xcodeproj::Project::Object::PBXNativeTarget
bundle_target.product_reference.name.should == 'banana_bundle.bundle'
bundle_target.product_reference.path.should == 'banana_bundle.bundle'
end end
it 'adds the build configurations to the resources bundle targets' do it 'adds the build configurations to the resources bundle targets' do
@pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => []) @pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => [])
@installer.install! @installer.install!
bundle_target = @project.targets.find { |t| t.name == 'Pods-BananaLib-banana_bundle' } bundle_target = @project.targets.find { |t| t.name == 'BananaLib-banana_bundle' }
file = config.sandbox.root + @pod_target.xcconfig_private_path file = config.sandbox.root + @pod_target.xcconfig_private_path
bundle_target.build_configurations.each do |bc| bundle_target.build_configurations.each do |bc|
bc.base_configuration_reference.real_path.should == file bc.base_configuration_reference.real_path.should == file
end end
end end
end
#--------------------------------------# #--------------------------------------#
...@@ -141,9 +188,7 @@ module Pod ...@@ -141,9 +188,7 @@ module Pod
it "creates a prefix header, including the contents of the specification's prefix header" do it "creates a prefix header, including the contents of the specification's prefix header" do
@spec.prefix_header_contents = '#import "BlocksKit.h"' @spec.prefix_header_contents = '#import "BlocksKit.h"'
@installer.install! @installer.install!
support_files_dir = config.sandbox.target_support_files_dir('Pods-BananaLib') generated = @pod_target.prefix_header_path.read
prefix_header = support_files_dir + 'Pods-BananaLib-prefix.pch'
generated = prefix_header.read
expected = <<-EOS.strip_heredoc expected = <<-EOS.strip_heredoc
#ifdef __OBJC__ #ifdef __OBJC__
#import <UIKit/UIKit.h> #import <UIKit/UIKit.h>
...@@ -157,13 +202,12 @@ module Pod ...@@ -157,13 +202,12 @@ module Pod
it 'creates a dummy source to ensure the compilation of libraries with only categories' do it 'creates a dummy source to ensure the compilation of libraries with only categories' do
@installer.install! @installer.install!
dummy_source_basename = @pod_target.dummy_source_path.basename.to_s
build_files = @installer.target.native_target.source_build_phase.files build_files = @installer.target.native_target.source_build_phase.files
build_file = build_files.find { |bf| bf.file_ref.display_name == 'Pods-BananaLib-dummy.m' } build_file = build_files.find { |bf| bf.file_ref.display_name == dummy_source_basename }
build_file.should.be.not.nil build_file.should.be.not.nil
build_file.file_ref.path.should == 'Pods-BananaLib-dummy.m' build_file.file_ref.path.should == dummy_source_basename
support_files_dir = config.sandbox.target_support_files_dir('Pods-BananaLib') @pod_target.dummy_source_path.read.should.include?('@interface PodsDummy_BananaLib')
dummy = support_files_dir + 'Pods-BananaLib-dummy.m'
dummy.read.should.include?('@interface PodsDummy_Pods')
end end
#--------------------------------------------------------------------------------# #--------------------------------------------------------------------------------#
...@@ -181,7 +225,7 @@ module Pod ...@@ -181,7 +225,7 @@ module Pod
end end
it 'flags should not be added to dtrace files' do it 'flags should not be added to dtrace files' do
@installer.target.target_definition.stubs(:inhibits_warnings_for_pod?).returns(true) @installer.target.target_definitions.first.stubs(:inhibits_warnings_for_pod?).returns(true)
@installer.install! @installer.install!
dtrace_files = @installer.target.native_target.source_build_phase.files.select do |sf| dtrace_files = @installer.target.native_target.source_build_phase.files.select do |sf|
...@@ -193,7 +237,7 @@ module Pod ...@@ -193,7 +237,7 @@ module Pod
end end
it 'adds -w per pod if target definition inhibits warnings for that pod' do it 'adds -w per pod if target definition inhibits warnings for that pod' do
@installer.target.target_definition.stubs(:inhibits_warnings_for_pod?).returns(true) @installer.target.target_definitions.first.stubs(:inhibits_warnings_for_pod?).returns(true)
flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios), true) flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios), true)
flags.should.include?('-w') flags.should.include?('-w')
...@@ -205,7 +249,7 @@ module Pod ...@@ -205,7 +249,7 @@ module Pod
end end
it 'adds -Xanalyzer -analyzer-disable-checker per pod' do it 'adds -Xanalyzer -analyzer-disable-checker per pod' do
@installer.target.target_definition.stubs(:inhibits_warnings_for_pod?).returns(true) @installer.target.target_definitions.first.stubs(:inhibits_warnings_for_pod?).returns(true)
flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios), true) flags = @installer.send(:compiler_flags_for_consumer, @spec.consumer(:ios), true)
flags.should.include?('-Xanalyzer -analyzer-disable-all-checks') flags.should.include?('-Xanalyzer -analyzer-disable-all-checks')
......
...@@ -20,7 +20,7 @@ module Pod ...@@ -20,7 +20,7 @@ module Pod
@project.add_file_reference(file, group) @project.add_file_reference(file, group)
end end
@pod_target = PodTarget.new([@spec], @target_definition, config.sandbox) @pod_target = PodTarget.new([@spec], [@target_definition], config.sandbox)
@pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0')) @pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug } @pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug }
@pod_target.file_accessors = [file_accessor] @pod_target.file_accessors = [file_accessor]
......
...@@ -130,6 +130,10 @@ module Pod ...@@ -130,6 +130,10 @@ module Pod
pod 'BananaLib', :path => (fixture_path + 'banana-lib').to_s pod 'BananaLib', :path => (fixture_path + 'banana-lib').to_s
pod 'OrangeFramework', :path => (fixture_path + 'orange-framework').to_s pod 'OrangeFramework', :path => (fixture_path + 'orange-framework').to_s
pod 'monkey', :path => (fixture_path + 'monkey').to_s pod 'monkey', :path => (fixture_path + 'monkey').to_s
target 'TestRunner', :exclusive => true do
pod 'monkey', :path => (fixture_path + 'monkey').to_s
end
end end
lockfile = generate_lockfile lockfile = generate_lockfile
config.integrate_targets = false config.integrate_targets = false
...@@ -139,11 +143,11 @@ module Pod ...@@ -139,11 +143,11 @@ module Pod
target = @installer.aggregate_targets.first target = @installer.aggregate_targets.first
target.requires_frameworks?.should == true target.requires_frameworks?.should == true
target.pod_targets.select(&:requires_frameworks?).map(&:name).sort.should == [ target.pod_targets.select(&:requires_frameworks?).map(&:name).sort.should == %w(
'Pods-BananaLib', BananaLib
'Pods-OrangeFramework', OrangeFramework
'Pods-monkey', monkey
] )
end end
end end
...@@ -261,7 +265,7 @@ module Pod ...@@ -261,7 +265,7 @@ module Pod
it 'stores the targets created by the analyzer' do it 'stores the targets created by the analyzer' do
@installer.send(:analyze) @installer.send(:analyze)
@installer.aggregate_targets.map(&:name).sort.should == ['Pods'] @installer.aggregate_targets.map(&:name).sort.should == ['Pods']
@installer.pod_targets.map(&:name).sort.should == ['Pods-JSONKit'] @installer.pod_targets.map(&:name).sort.should == ['JSONKit']
end end
it 'configures the analyzer to use update mode if appropriate' do it 'configures the analyzer to use update mode if appropriate' do
...@@ -269,7 +273,7 @@ module Pod ...@@ -269,7 +273,7 @@ module Pod
Installer::Analyzer.any_instance.expects(:update=).with(true) Installer::Analyzer.any_instance.expects(:update=).with(true)
@installer.send(:analyze) @installer.send(:analyze)
@installer.aggregate_targets.map(&:name).sort.should == ['Pods'] @installer.aggregate_targets.map(&:name).sort.should == ['Pods']
@installer.pod_targets.map(&:name).sort.should == ['Pods-JSONKit'] @installer.pod_targets.map(&:name).sort.should == ['JSONKit']
end end
end end
...@@ -302,7 +306,7 @@ module Pod ...@@ -302,7 +306,7 @@ module Pod
@analysis_result = Installer::Analyzer::AnalysisResult.new @analysis_result = Installer::Analyzer::AnalysisResult.new
@analysis_result.specifications = [] @analysis_result.specifications = []
@analysis_result.sandbox_state = Installer::Analyzer::SpecsState.new @analysis_result.sandbox_state = Installer::Analyzer::SpecsState.new
@pod_targets = [PodTarget.new([], nil, config.sandbox)] @pod_targets = [PodTarget.new([stub('Spec')], [stub('TargetDefinition')], config.sandbox)]
@installer.stubs(:analysis_result).returns(@analysis_result) @installer.stubs(:analysis_result).returns(@analysis_result)
@installer.stubs(:pod_targets).returns(@pod_targets) @installer.stubs(:pod_targets).returns(@pod_targets)
end end
...@@ -360,7 +364,7 @@ module Pod ...@@ -360,7 +364,7 @@ module Pod
it 'correctly configures the Pod source installer' do it 'correctly configures the Pod source installer' do
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
pod_target = PodTarget.new([spec], nil, config.sandbox) pod_target = PodTarget.new([spec], [stub('TargetDefinition')], config.sandbox)
pod_target.stubs(:platform).returns(:ios) pod_target.stubs(:platform).returns(:ios)
@installer.stubs(:pod_targets).returns([pod_target]) @installer.stubs(:pod_targets).returns([pod_target])
@installer.instance_variable_set(:@installed_specs, []) @installer.instance_variable_set(:@installed_specs, [])
...@@ -370,7 +374,7 @@ module Pod ...@@ -370,7 +374,7 @@ module Pod
it 'maintains the list of the installed specs' do it 'maintains the list of the installed specs' do
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
pod_target = PodTarget.new([spec], nil, config.sandbox) pod_target = PodTarget.new([spec], [stub('TargetDefinition')], config.sandbox)
pod_target.stubs(:platform).returns(:ios) pod_target.stubs(:platform).returns(:ios)
@installer.stubs(:pod_targets).returns([pod_target, pod_target]) @installer.stubs(:pod_targets).returns([pod_target, pod_target])
@installer.instance_variable_set(:@installed_specs, []) @installer.instance_variable_set(:@installed_specs, [])
...@@ -459,8 +463,8 @@ module Pod ...@@ -459,8 +463,8 @@ module Pod
end end
it 'sets the deployment target for the whole project' do it 'sets the deployment target for the whole project' do
pod_target_ios = PodTarget.new([], nil, config.sandbox) pod_target_ios = PodTarget.new([stub('Spec')], [stub('TargetDefinition')], config.sandbox)
pod_target_osx = PodTarget.new([], nil, config.sandbox) pod_target_osx = PodTarget.new([stub('Spec')], [stub('TargetDefinition')], config.sandbox)
pod_target_ios.stubs(:platform).returns(Platform.new(:ios, '6.0')) pod_target_ios.stubs(:platform).returns(Platform.new(:ios, '6.0'))
pod_target_osx.stubs(:platform).returns(Platform.new(:osx, '10.8')) pod_target_osx.stubs(:platform).returns(Platform.new(:osx, '10.8'))
aggregate_target_ios = AggregateTarget.new(nil, config.sandbox) aggregate_target_ios = AggregateTarget.new(nil, config.sandbox)
...@@ -495,7 +499,7 @@ module Pod ...@@ -495,7 +499,7 @@ module Pod
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
target_definition = Podfile::TargetDefinition.new(:default, nil) target_definition = Podfile::TargetDefinition.new(:default, nil)
target_definition.store_pod('BananaLib') target_definition.store_pod('BananaLib')
pod_target = PodTarget.new([spec], target_definition, config.sandbox) pod_target = PodTarget.new([spec], [target_definition], config.sandbox)
@installer.stubs(:aggregate_targets).returns([]) @installer.stubs(:aggregate_targets).returns([])
@installer.stubs(:pod_targets).returns([pod_target]) @installer.stubs(:pod_targets).returns([pod_target])
Installer::PodTargetInstaller.any_instance.expects(:install!) Installer::PodTargetInstaller.any_instance.expects(:install!)
...@@ -505,7 +509,7 @@ module Pod ...@@ -505,7 +509,7 @@ module Pod
it 'skips empty pod targets' do it 'skips empty pod targets' do
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
target_definition = Podfile::TargetDefinition.new(:default, nil) target_definition = Podfile::TargetDefinition.new(:default, nil)
pod_target = PodTarget.new([spec], target_definition, config.sandbox) pod_target = PodTarget.new([spec], [target_definition], config.sandbox)
@installer.stubs(:aggregate_targets).returns([]) @installer.stubs(:aggregate_targets).returns([])
@installer.stubs(:pod_targets).returns([pod_target]) @installer.stubs(:pod_targets).returns([pod_target])
Installer::PodTargetInstaller.any_instance.expects(:install!).never Installer::PodTargetInstaller.any_instance.expects(:install!).never
...@@ -540,7 +544,7 @@ module Pod ...@@ -540,7 +544,7 @@ module Pod
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
target_definition = Podfile::TargetDefinition.new(:default, @installer.podfile) target_definition = Podfile::TargetDefinition.new(:default, @installer.podfile)
@pod_target = PodTarget.new([spec], target_definition, config.sandbox) @pod_target = PodTarget.new([spec], [target_definition], config.sandbox)
@target = AggregateTarget.new(target_definition, config.sandbox) @target = AggregateTarget.new(target_definition, config.sandbox)
@mock_target = mock('PodNativeTarget') @mock_target = mock('PodNativeTarget')
...@@ -615,15 +619,14 @@ module Pod ...@@ -615,15 +619,14 @@ module Pod
it 'shares schemes of development pods' do it 'shares schemes of development pods' do
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
target_definition = Podfile::TargetDefinition.new(:default, @installer.podfile) pod_target = fixture_pod_target(spec)
pod_target = PodTarget.new([spec], target_definition, config.sandbox)
@installer.pods_project.stubs(:targets).returns([pod_target]) @installer.stubs(:pod_targets).returns([pod_target])
@installer.sandbox.stubs(:development_pods).returns('BananaLib' => nil) @installer.sandbox.stubs(:development_pods).returns('BananaLib' => nil)
Xcodeproj::XCScheme.expects(:share_scheme).with( Xcodeproj::XCScheme.expects(:share_scheme).with(
@installer.pods_project.path, @installer.pods_project.path,
'Pods-default-BananaLib') 'BananaLib')
@installer.send(:share_development_pod_schemes) @installer.send(:share_development_pod_schemes)
end end
......
...@@ -13,6 +13,10 @@ module Pod ...@@ -13,6 +13,10 @@ module Pod
@target.target_definition.should == @target_definition @target.target_definition.should == @target_definition
end end
it 'is initialized with empty archs' do
@target.archs.should == []
end
it 'returns the label of the target definition' do it 'returns the label of the target definition' do
@target.label.should == 'Pods' @target.label.should == 'Pods'
end end
...@@ -80,7 +84,7 @@ module Pod ...@@ -80,7 +84,7 @@ module Pod
end end
it 'returns the path for the CONFIGURATION_BUILD_DIR build setting' do it 'returns the path for the CONFIGURATION_BUILD_DIR build setting' do
@target.configuration_build_dir.should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods' @target.scoped_configuration_build_dir.should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods'
end end
end end
...@@ -88,7 +92,7 @@ module Pod ...@@ -88,7 +92,7 @@ module Pod
before do before do
@spec = fixture_spec('banana-lib/BananaLib.podspec') @spec = fixture_spec('banana-lib/BananaLib.podspec')
@target_definition = Podfile::TargetDefinition.new('Pods', nil) @target_definition = Podfile::TargetDefinition.new('Pods', nil)
@pod_target = PodTarget.new([@spec], @target_definition, config.sandbox) @pod_target = PodTarget.new([@spec], [@target_definition], config.sandbox)
@target = AggregateTarget.new(@target_definition, config.sandbox) @target = AggregateTarget.new(@target_definition, config.sandbox)
@target.stubs(:platform).returns(:ios) @target.stubs(:platform).returns(:ios)
@target.pod_targets = [@pod_target] @target.pod_targets = [@pod_target]
...@@ -96,9 +100,9 @@ module Pod ...@@ -96,9 +100,9 @@ module Pod
describe 'with configuration dependent pod targets' do describe 'with configuration dependent pod targets' do
before do before do
@pod_target_release = PodTarget.new([@spec], @target_definition, config.sandbox) @pod_target_release = PodTarget.new([@spec], [@target_definition], config.sandbox)
@pod_target_release.expects(:include_in_build_config?).with('Debug').returns(false) @pod_target_release.expects(:include_in_build_config?).with(@target_definition, 'Debug').returns(false)
@pod_target_release.expects(:include_in_build_config?).with('Release').returns(true) @pod_target_release.expects(:include_in_build_config?).with(@target_definition, 'Release').returns(true)
@target.pod_targets = [@pod_target, @pod_target_release] @target.pod_targets = [@pod_target, @pod_target_release]
@target.user_build_configurations = { @target.user_build_configurations = {
'Debug' => :debug, 'Debug' => :debug,
...@@ -137,7 +141,7 @@ module Pod ...@@ -137,7 +141,7 @@ module Pod
describe 'With libraries' do describe 'With libraries' do
before do before do
@pod_target = fixture_pod_target('banana-lib/BananaLib.podspec') @pod_target = fixture_pod_target('banana-lib/BananaLib.podspec')
@target = AggregateTarget.new(@pod_target.target_definition, config.sandbox) @target = AggregateTarget.new(@pod_target.target_definitions.first, config.sandbox)
@target.pod_targets = [@pod_target] @target.pod_targets = [@pod_target]
end end
...@@ -196,8 +200,8 @@ module Pod ...@@ -196,8 +200,8 @@ module Pod
describe 'With frameworks' do describe 'With frameworks' do
before do before do
@pod_target = fixture_pod_target('orange-framework/OrangeFramework.podspec', :ios, Podfile::TargetDefinition.new('iOS Example', nil)) @pod_target = fixture_pod_target('orange-framework/OrangeFramework.podspec', fixture_target_definition('iOS Example'))
@target = AggregateTarget.new(@pod_target.target_definition, config.sandbox) @target = AggregateTarget.new(@pod_target.target_definitions.first, config.sandbox)
@target.stubs(:requires_frameworks?).returns(true) @target.stubs(:requires_frameworks?).returns(true)
@target.pod_targets = [@pod_target] @target.pod_targets = [@pod_target]
end end
......
...@@ -5,21 +5,42 @@ module Pod ...@@ -5,21 +5,42 @@ module Pod
before do before do
spec = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
@target_definition = Podfile::TargetDefinition.new('Pods', nil) @target_definition = Podfile::TargetDefinition.new('Pods', nil)
@pod_target = PodTarget.new([spec], @target_definition, config.sandbox) @pod_target = PodTarget.new([spec], [@target_definition], config.sandbox)
@pod_target.stubs(:platform).returns(:ios) @pod_target.stubs(:platform).returns(:ios)
end end
describe 'Meta' do
describe '#scoped' do
it 'returns target copies per target definition, which are scoped' do
@pod_target.should.not.be.scoped
@pod_target.scoped.first.should.be.scoped
@pod_target.should.not.be.scoped
end
end
end
describe 'In general' do describe 'In general' do
it 'returns the target_definition that generated it' do it 'returns the target definitions' do
@pod_target.target_definition.should == @target_definition @pod_target.target_definitions.should == [@target_definition]
end
it 'is initialized with empty archs' do
@pod_target.archs.should == []
end end
it 'returns its name' do it 'returns its name' do
@pod_target.name.should == 'Pods-BananaLib' @pod_target.name.should == 'BananaLib'
@pod_target.scoped.first.name.should == 'Pods-BananaLib'
end
it 'returns its label' do
@pod_target.label.should == 'BananaLib'
@pod_target.scoped.first.label.should == 'Pods-BananaLib'
end end
it 'returns the name of its product' do it 'returns the name of its product' do
@pod_target.product_name.should == 'libPods-BananaLib.a' @pod_target.product_name.should == 'libBananaLib.a'
@pod_target.scoped.first.product_name.should == 'libPods-BananaLib.a'
end end
it 'returns the spec consumers for the pod targets' do it 'returns the spec consumers for the pod targets' do
...@@ -35,7 +56,8 @@ module Pod ...@@ -35,7 +56,8 @@ module Pod
end end
it 'returns the name of the resources bundle target' do it 'returns the name of the resources bundle target' do
@pod_target.resources_bundle_target_label('Fruits').should == 'Pods-BananaLib-Fruits' @pod_target.resources_bundle_target_label('Fruits').should == 'BananaLib-Fruits'
@pod_target.scoped.first.resources_bundle_target_label('Fruits').should == 'Pods-BananaLib-Fruits'
end end
it 'returns the name of the Pods on which this target depends' do it 'returns the name of the Pods on which this target depends' do
...@@ -45,13 +67,13 @@ module Pod ...@@ -45,13 +67,13 @@ module Pod
it 'returns whether it is whitelisted in a build configuration' do it 'returns whether it is whitelisted in a build configuration' do
@target_definition.store_pod('BananaLib') @target_definition.store_pod('BananaLib')
@target_definition.whitelist_pod_for_configuration('BananaLib', 'debug') @target_definition.whitelist_pod_for_configuration('BananaLib', 'debug')
@pod_target.include_in_build_config?('Debug').should.be.true @pod_target.include_in_build_config?(@target_definition, 'Debug').should.be.true
@pod_target.include_in_build_config?('Release').should.be.false @pod_target.include_in_build_config?(@target_definition, 'Release').should.be.false
end end
it 'is whitelisted on all build configurations of it is a dependency of other Pods' do it 'is whitelisted on all build configurations of it is a dependency of other Pods' do
@pod_target.include_in_build_config?('Debug').should.be.true @pod_target.include_in_build_config?(@target_definition, 'Debug').should.be.true
@pod_target.include_in_build_config?('Release').should.be.true @pod_target.include_in_build_config?(@target_definition, 'Release').should.be.true
end end
it 'raises if a Pod is whitelisted for different build configurations' do it 'raises if a Pod is whitelisted for different build configurations' do
...@@ -59,7 +81,7 @@ module Pod ...@@ -59,7 +81,7 @@ module Pod
@target_definition.store_pod('BananaLib/Subspec') @target_definition.store_pod('BananaLib/Subspec')
@target_definition.whitelist_pod_for_configuration('BananaLib', 'debug') @target_definition.whitelist_pod_for_configuration('BananaLib', 'debug')
message = should.raise Informative do message = should.raise Informative do
@pod_target.include_in_build_config?('release').should.be.true @pod_target.include_in_build_config?(@target_definition, 'release').should.be.true
end.message end.message
message.should.match /subspecs across different build configurations/ message.should.match /subspecs across different build configurations/
end end
...@@ -84,45 +106,67 @@ module Pod ...@@ -84,45 +106,67 @@ module Pod
describe 'Support files' do describe 'Support files' do
it 'returns the absolute path of the xcconfig file' do it 'returns the absolute path of the xcconfig file' do
@pod_target.xcconfig_path('Release').to_s.should.include?( @pod_target.xcconfig_path('Release').to_s.should.include?(
'Pods/Target Support Files/BananaLib/BananaLib.release.xcconfig',
)
@pod_target.scoped.first.xcconfig_path('Release').to_s.should.include?(
'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib.release.xcconfig', 'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib.release.xcconfig',
) )
end end
it 'escapes the file separators in variant build configuration name in the xcconfig file' do it 'escapes the file separators in variant build configuration name in the xcconfig file' do
@pod_target.xcconfig_path("Release#{File::SEPARATOR}1").to_s.should.include?( @pod_target.xcconfig_path("Release#{File::SEPARATOR}1").to_s.should.include?(
'Pods/Target Support Files/BananaLib/BananaLib.release-1.xcconfig',
)
@pod_target.scoped.first.xcconfig_path("Release#{File::SEPARATOR}1").to_s.should.include?(
'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib.release-1.xcconfig', 'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib.release-1.xcconfig',
) )
end end
it 'returns the absolute path of the prefix header file' do it 'returns the absolute path of the prefix header file' do
@pod_target.prefix_header_path.to_s.should.include?( @pod_target.prefix_header_path.to_s.should.include?(
'Pods/Target Support Files/BananaLib/BananaLib-prefix.pch',
)
@pod_target.scoped.first.prefix_header_path.to_s.should.include?(
'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib-prefix.pch', 'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib-prefix.pch',
) )
end end
it 'returns the absolute path of the bridge support file' do it 'returns the absolute path of the bridge support file' do
@pod_target.bridge_support_path.to_s.should.include?( @pod_target.bridge_support_path.to_s.should.include?(
'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib.bridgesupport', 'Pods/Target Support Files/BananaLib/BananaLib.bridgesupport',
) )
end end
it 'returns the absolute path of the info plist file' do it 'returns the absolute path of the info plist file' do
@pod_target.info_plist_path.to_s.should.include?( @pod_target.info_plist_path.to_s.should.include?(
'Pods/Target Support Files/BananaLib/Info.plist',
)
@pod_target.scoped.first.info_plist_path.to_s.should.include?(
'Pods/Target Support Files/Pods-BananaLib/Info.plist', 'Pods/Target Support Files/Pods-BananaLib/Info.plist',
) )
end end
it 'returns the absolute path of the dummy source file' do
@pod_target.dummy_source_path.to_s.should.include?(
'Pods/Target Support Files/BananaLib/BananaLib-dummy.m',
)
@pod_target.scoped.first.dummy_source_path.to_s.should.include?(
'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib-dummy.m',
)
end
it 'returns the absolute path of the public and private xcconfig files' do it 'returns the absolute path of the public and private xcconfig files' do
@pod_target.xcconfig_path.to_s.should.include?( @pod_target.xcconfig_path.to_s.should.include?(
'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib.xcconfig', 'Pods/Target Support Files/BananaLib/BananaLib.xcconfig',
) )
@pod_target.xcconfig_private_path.to_s.should.include( @pod_target.xcconfig_private_path.to_s.should.include(
'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib-Private.xcconfig', 'Pods/Target Support Files/BananaLib/BananaLib-Private.xcconfig',
) )
end end
it 'returns the path for the CONFIGURATION_BUILD_DIR build setting' do it 'returns the path for the CONFIGURATION_BUILD_DIR build setting' do
@pod_target.configuration_build_dir.should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods' @pod_target.configuration_build_dir.should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)'
@pod_target.scoped.first.configuration_build_dir.should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods'
end end
end end
...@@ -150,7 +194,8 @@ module Pod ...@@ -150,7 +194,8 @@ module Pod
end end
it 'returns the library name' do it 'returns the library name' do
@pod_target.static_library_name.should == 'libPods-BananaLib.a' @pod_target.static_library_name.should == 'libBananaLib.a'
@pod_target.scoped.first.static_library_name.should == 'libPods-BananaLib.a'
end end
it 'returns :framework as product type' do it 'returns :framework as product type' do
...@@ -164,7 +209,8 @@ module Pod ...@@ -164,7 +209,8 @@ module Pod
describe 'Host does not requires frameworks' do describe 'Host does not requires frameworks' do
it 'returns the product name' do it 'returns the product name' do
@pod_target.product_name.should == 'libPods-BananaLib.a' @pod_target.product_name.should == 'libBananaLib.a'
@pod_target.scoped.first.product_name.should == 'libPods-BananaLib.a'
end end
it 'returns the framework name' do it 'returns the framework name' do
...@@ -172,7 +218,8 @@ module Pod ...@@ -172,7 +218,8 @@ module Pod
end end
it 'returns the library name' do it 'returns the library name' do
@pod_target.static_library_name.should == 'libPods-BananaLib.a' @pod_target.static_library_name.should == 'libBananaLib.a'
@pod_target.scoped.first.static_library_name.should == 'libPods-BananaLib.a'
end end
it 'returns :static_library as product type' do it 'returns :static_library as product type' do
...@@ -208,7 +255,8 @@ module Pod ...@@ -208,7 +255,8 @@ module Pod
end end
it 'returns the library name' do it 'returns the library name' do
@pod_target.static_library_name.should == 'libPods-OrangeFramework.a' @pod_target.static_library_name.should == 'libOrangeFramework.a'
@pod_target.scoped.first.static_library_name.should == 'libPods-OrangeFramework.a'
end end
it 'returns :framework as product type' do it 'returns :framework as product type' do
......
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