Commit d504d84c authored by Marius Rackwitz's avatar Marius Rackwitz

Merge pull request #4146 from CocoaPods/mr-fix-scoping

Improve de-duplication for non-trivial cases
parents c1334d75 43332122
...@@ -8,12 +8,26 @@ To install release candidates run `[sudo] gem install cocoapods --pre` ...@@ -8,12 +8,26 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
##### Enhancements ##### Enhancements
* None. * Allow deduplication to take effect even when the same pod is used with
different sets of subspecs across different platforms.
This changes the general naming scheme scoped pod targets. They are
suffixed now on base of what makes them different among others for the
same root spec instead of being prefixed by the dependant target.
[Marius Rackwitz](https://github.com/mrackwitz)
[#4146](https://github.com/CocoaPods/CocoaPods/pull/4146)
##### Bug Fixes ##### Bug Fixes
* None. * Pods are built by default in another scoping level of the build products
directory identified by their name to prevent name clashes among
dependencies.
[Marius Rackwitz](https://github.com/mrackwitz)
[#4146](https://github.com/CocoaPods/CocoaPods/pull/4146)
* Fix mixed integrations where static libraries are used along frameworks
from different target definitions in one Podfile.
[Marius Rackwitz](https://github.com/mrackwitz)
[#4146](https://github.com/CocoaPods/CocoaPods/pull/4146)
## 1.0.0.beta.3 (2016-02-03) ## 1.0.0.beta.3 (2016-02-03)
......
...@@ -152,19 +152,22 @@ begin ...@@ -152,19 +152,22 @@ begin
namespace :fixture_tarballs do namespace :fixture_tarballs do
task :default => :unpack task :default => :unpack
tarballs = FileList['spec/fixtures/**/*.tar.gz']
desc 'Check fixture tarballs for pending changes' desc 'Check fixture tarballs for pending changes'
task :check_for_pending_changes do task :check_for_pending_changes do
repo_dir = 'spec/fixtures/banana-lib' tarballs.each do |tarball|
if Dir.exist?(repo_dir) && !Dir.chdir(repo_dir) { `git status --porcelain`.empty? } repo_dir = "#{File.dirname(tarball)}/#{File.basename(tarball, '.tar.gz')}"
puts red("[!] There are unsaved changes in '#{repo_dir}'. " \ if Dir.exist?(repo_dir) && Dir.exist?("#{repo_dir}/.git") && !Dir.chdir(repo_dir) { `git status --porcelain`.empty? }
'Please commit everything and run `rake spec:fixture_tarballs:rebuild`.') puts red("[!] There are unsaved changes in '#{repo_dir}'. " \
exit 1 'Please commit everything and run `rake spec:fixture_tarballs:rebuild`.')
exit 1
end
end end
end end
desc 'Rebuild all the fixture tarballs' desc 'Rebuild all the fixture tarballs'
task :rebuild => :check_for_pending_changes do task :rebuild => :check_for_pending_changes do
tarballs = FileList['spec/fixtures/**/*.tar.gz']
tarballs.each do |tarball| tarballs.each do |tarball|
basename = File.basename(tarball) basename = File.basename(tarball)
sh "cd #{File.dirname(tarball)} && rm #{basename} && env COPYFILE_DISABLE=1 tar -zcf #{basename} #{basename[0..-8]}" sh "cd #{File.dirname(tarball)} && rm #{basename} && env COPYFILE_DISABLE=1 tar -zcf #{basename} #{basename[0..-8]}"
...@@ -179,7 +182,6 @@ begin ...@@ -179,7 +182,6 @@ begin
exit 1 unless args[:force] exit 1 unless args[:force]
puts 'Continue anyway because `force` was applied.' puts 'Continue anyway because `force` was applied.'
end end
tarballs = FileList['spec/fixtures/**/*.tar.gz']
tarballs.each do |tarball| tarballs.each do |tarball|
basename = File.basename(tarball) basename = File.basename(tarball)
Dir.chdir(File.dirname(tarball)) do Dir.chdir(File.dirname(tarball)) do
......
...@@ -59,6 +59,7 @@ module Pod ...@@ -59,6 +59,7 @@ 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',
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ', 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
'LIBRARY_SEARCH_PATHS' => '$(inherited) ',
} }
if pod_targets.any?(&:uses_swift?) if pod_targets.any?(&:uses_swift?)
config['EMBEDDED_CONTENT_CONTAINS_SWIFT'] = 'YES' config['EMBEDDED_CONTENT_CONTAINS_SWIFT'] = 'YES'
...@@ -94,15 +95,11 @@ module Pod ...@@ -94,15 +95,11 @@ module Pod
# #
def settings_to_import_pod_targets def settings_to_import_pod_targets
if target.requires_frameworks? if target.requires_frameworks?
framework_header_search_paths = pod_targets.select(&:should_build?).map do |target| build_pod_targets = pod_targets.select(&:should_build?)
if target.scoped? framework_header_search_paths = build_pod_targets.map do |target|
"$PODS_FRAMEWORK_BUILD_PATH/#{target.product_name}/Headers" "#{target.build_product_path}/Headers"
else
"$CONFIGURATION_BUILD_DIR/#{target.product_name}/Headers"
end
end end
build_settings = { build_settings = {
'PODS_FRAMEWORK_BUILD_PATH' => XCConfigHelper.quote([target.scoped_configuration_build_dir]),
# Make framework headers discoverable by `import "…"` # Make framework headers discoverable by `import "…"`
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(framework_header_search_paths, '-iquote'), 'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(framework_header_search_paths, '-iquote'),
} }
...@@ -112,9 +109,6 @@ module Pod ...@@ -112,9 +109,6 @@ module Pod
build_settings['HEADER_SEARCH_PATHS'] = '$(inherited) ' + XCConfigHelper.quote(library_header_search_paths) build_settings['HEADER_SEARCH_PATHS'] = '$(inherited) ' + XCConfigHelper.quote(library_header_search_paths)
build_settings['OTHER_CFLAGS'] += ' ' + XCConfigHelper.quote(library_header_search_paths, '-isystem') build_settings['OTHER_CFLAGS'] += ' ' + XCConfigHelper.quote(library_header_search_paths, '-isystem')
end end
if pod_targets.any? { |t| t.should_build? && t.scoped? }
build_settings['FRAMEWORK_SEARCH_PATHS'] = '$PODS_FRAMEWORK_BUILD_PATH'
end
build_settings build_settings
else else
# Make headers discoverable from $PODS_ROOT/Headers directory # Make headers discoverable from $PODS_ROOT/Headers directory
...@@ -137,9 +131,11 @@ module Pod ...@@ -137,9 +131,11 @@ module Pod
# - `@import …;` / `import …` # - `@import …;` / `import …`
# #
def generate_settings_to_import_pod_targets def generate_settings_to_import_pod_targets
@xcconfig.merge! XCConfigHelper.settings_for_dependent_targets(target, pod_targets)
@xcconfig.merge!(settings_to_import_pod_targets) @xcconfig.merge!(settings_to_import_pod_targets)
target.search_paths_aggregate_targets.each do |search_paths_target| target.search_paths_aggregate_targets.each do |search_paths_target|
generator = AggregateXCConfig.new(search_paths_target, configuration_name) generator = AggregateXCConfig.new(search_paths_target, configuration_name)
@xcconfig.merge! XCConfigHelper.settings_for_dependent_targets(nil, search_paths_target.pod_targets)
@xcconfig.merge!(generator.settings_to_import_pod_targets) @xcconfig.merge!(generator.settings_to_import_pod_targets)
end end
end end
......
...@@ -45,32 +45,25 @@ module Pod ...@@ -45,32 +45,25 @@ module Pod
search_paths = target_search_paths.concat(sandbox_search_paths).uniq search_paths = target_search_paths.concat(sandbox_search_paths).uniq
config = { config = {
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(search_paths),
'LIBRARY_SEARCH_PATHS' => '$(inherited) ',
'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target), 'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target),
'PODS_ROOT' => '${SRCROOT}', 'PODS_ROOT' => '${SRCROOT}',
'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(search_paths),
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
'SKIP_INSTALL' => 'YES',
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
'PRODUCT_BUNDLE_IDENTIFIER' => 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}', 'PRODUCT_BUNDLE_IDENTIFIER' => 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}',
'SKIP_INSTALL' => 'YES',
# 'USE_HEADERMAP' => 'NO' # 'USE_HEADERMAP' => 'NO'
} }
@xcconfig = Xcodeproj::Config.new(config) @xcconfig = Xcodeproj::Config.new(config)
if target.requires_frameworks? && target.scoped?
build_settings = {
'PODS_FRAMEWORK_BUILD_PATH' => XCConfigHelper.quote([target.configuration_build_dir]),
'FRAMEWORK_SEARCH_PATHS' => '$PODS_FRAMEWORK_BUILD_PATH',
'CONFIGURATION_BUILD_DIR' => '$PODS_FRAMEWORK_BUILD_PATH',
}
@xcconfig.merge!(build_settings)
end
XCConfigHelper.add_settings_for_file_accessors_of_target(target, @xcconfig) XCConfigHelper.add_settings_for_file_accessors_of_target(target, @xcconfig)
target.file_accessors.each do |file_accessor| target.file_accessors.each do |file_accessor|
@xcconfig.merge!(file_accessor.spec_consumer.pod_target_xcconfig) @xcconfig.merge!(file_accessor.spec_consumer.pod_target_xcconfig)
end end
XCConfigHelper.add_target_specific_settings(target, @xcconfig) XCConfigHelper.add_target_specific_settings(target, @xcconfig)
@xcconfig.merge! XCConfigHelper.settings_for_dependent_targets(target, target.dependent_targets)
@xcconfig @xcconfig
end end
......
...@@ -4,6 +4,13 @@ module Pod ...@@ -4,6 +4,13 @@ module Pod
# Stores the shared logic of the classes of the XCConfig module. # Stores the shared logic of the classes of the XCConfig module.
# #
module XCConfigHelper module XCConfigHelper
# @return [String] Defined to hold the default Xcode build path, so
# that when this is overridden per {PodTarget}, it is still
# possible to reference other build products relative to the
# original path.
#
SHARED_BUILD_DIR_VARIABLE = 'PODS_SHARED_BUILD_DIR'.freeze
# Converts an array of strings to a single string where the each string # Converts an array of strings to a single string where the each string
# is surrounded by double quotes and separated by a space. Used to # is surrounded by double quotes and separated by a space. Used to
# represent strings in a xcconfig file. # represent strings in a xcconfig file.
...@@ -49,6 +56,8 @@ module Pod ...@@ -49,6 +56,8 @@ module Pod
# @param [Xcodeproj::Config] xcconfig # @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit. # The xcconfig to edit.
# #
# @return [void]
#
def self.add_settings_for_file_accessors_of_target(target, xcconfig) def self.add_settings_for_file_accessors_of_target(target, xcconfig)
target.file_accessors.each do |file_accessor| target.file_accessors.each do |file_accessor|
XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, xcconfig) XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, xcconfig)
...@@ -73,6 +82,8 @@ module Pod ...@@ -73,6 +82,8 @@ module Pod
# @param [Spec::FileAccessor] file_accessor # @param [Spec::FileAccessor] file_accessor
# The file accessor, which holds the list of static frameworks. # The file accessor, which holds the list of static frameworks.
# #
# @return [void]
#
def self.add_static_dependency_build_settings(target, xcconfig, file_accessor) def self.add_static_dependency_build_settings(target, xcconfig, file_accessor)
file_accessor.vendored_static_frameworks.each do |vendored_static_framework| file_accessor.vendored_static_frameworks.each do |vendored_static_framework|
XCConfigHelper.add_framework_build_settings(vendored_static_framework, xcconfig, target.sandbox.root) XCConfigHelper.add_framework_build_settings(vendored_static_framework, xcconfig, target.sandbox.root)
...@@ -90,6 +101,8 @@ module Pod ...@@ -90,6 +101,8 @@ module Pod
# @param [Xcodeproj::Config] xcconfig # @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit. # The xcconfig to edit.
# #
# @return [void]
#
def self.add_dynamic_dependency_build_settings(target, xcconfig) def self.add_dynamic_dependency_build_settings(target, xcconfig)
target.file_accessors.each do |file_accessor| target.file_accessors.each do |file_accessor|
file_accessor.vendored_dynamic_frameworks.each do |vendored_dynamic_framework| file_accessor.vendored_dynamic_frameworks.each do |vendored_dynamic_framework|
...@@ -110,6 +123,8 @@ module Pod ...@@ -110,6 +123,8 @@ module Pod
# @param [Xcodeproj::Config] xcconfig # @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit. # The xcconfig to edit.
# #
# @return [void]
#
def self.add_spec_build_settings_to_xcconfig(consumer, xcconfig) def self.add_spec_build_settings_to_xcconfig(consumer, xcconfig)
xcconfig.libraries.merge(consumer.libraries) xcconfig.libraries.merge(consumer.libraries)
xcconfig.frameworks.merge(consumer.frameworks) xcconfig.frameworks.merge(consumer.frameworks)
...@@ -129,6 +144,8 @@ module Pod ...@@ -129,6 +144,8 @@ module Pod
# @param [Pathname] sandbox_root # @param [Pathname] sandbox_root
# The path retrieved from Sandbox#root. # The path retrieved from Sandbox#root.
# #
# @return [void]
#
def self.add_framework_build_settings(framework_path, xcconfig, sandbox_root) def self.add_framework_build_settings(framework_path, xcconfig, sandbox_root)
name = File.basename(framework_path, '.framework') name = File.basename(framework_path, '.framework')
dirname = '${PODS_ROOT}/' + framework_path.dirname.relative_path_from(sandbox_root).to_s dirname = '${PODS_ROOT}/' + framework_path.dirname.relative_path_from(sandbox_root).to_s
...@@ -151,6 +168,8 @@ module Pod ...@@ -151,6 +168,8 @@ module Pod
# @param [Pathname] sandbox_root # @param [Pathname] sandbox_root
# The path retrieved from Sandbox#root. # The path retrieved from Sandbox#root.
# #
# @return [void]
#
def self.add_library_build_settings(library_path, xcconfig, sandbox_root) def self.add_library_build_settings(library_path, xcconfig, sandbox_root)
extension = File.extname(library_path) extension = File.extname(library_path)
name = File.basename(library_path, extension).sub(/\Alib/, '') name = File.basename(library_path, extension).sub(/\Alib/, '')
...@@ -172,6 +191,8 @@ module Pod ...@@ -172,6 +191,8 @@ module Pod
# @param [Xcodeproj::Config] xcconfig # @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit. # The xcconfig to edit.
# #
# @return [void]
#
def self.add_code_signing_settings(target, xcconfig) def self.add_code_signing_settings(target, xcconfig)
build_settings = {} build_settings = {}
if target.platform.to_sym == :osx if target.platform.to_sym == :osx
...@@ -189,6 +210,8 @@ module Pod ...@@ -189,6 +210,8 @@ module Pod
# @param [Xcodeproj::Config] xcconfig # @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit. # The xcconfig to edit.
# #
# @return [void]
#
def self.add_target_specific_settings(target, xcconfig) def self.add_target_specific_settings(target, xcconfig)
if target.requires_frameworks? if target.requires_frameworks?
add_code_signing_settings(target, xcconfig) add_code_signing_settings(target, xcconfig)
...@@ -196,6 +219,46 @@ module Pod ...@@ -196,6 +219,46 @@ module Pod
add_language_specific_settings(target, xcconfig) add_language_specific_settings(target, xcconfig)
end end
# Returns the search paths for frameworks and libraries the given target
# depends on, so that it can be correctly built and linked.
#
# @param [Target] target
# The target.
#
# @param [Array<PodTarget>] dependent_targets
# The pod targets the given target depends on.
#
# @return [Hash<String, String>] the settings
#
def self.settings_for_dependent_targets(target, dependent_targets)
dependent_targets = dependent_targets.select(&:should_build?)
has_configuration_build_dir = target.respond_to?(:configuration_build_dir)
if has_configuration_build_dir
build_dir_var = "$#{SHARED_BUILD_DIR_VARIABLE}"
build_settings = {
'CONFIGURATION_BUILD_DIR' => target.configuration_build_dir(build_dir_var),
SHARED_BUILD_DIR_VARIABLE => '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)',
}
else
build_dir_var = '$CONFIGURATION_BUILD_DIR'
build_settings = {}
end
unless dependent_targets.empty?
framework_search_paths = []
library_search_paths = []
dependent_targets.each do |dependent_target|
if dependent_target.requires_frameworks?
framework_search_paths << dependent_target.configuration_build_dir(build_dir_var)
else
library_search_paths << dependent_target.configuration_build_dir(build_dir_var)
end
end
build_settings['FRAMEWORK_SEARCH_PATHS'] = XCConfigHelper.quote(framework_search_paths.uniq)
build_settings['LIBRARY_SEARCH_PATHS'] = XCConfigHelper.quote(library_search_paths.uniq)
end
build_settings
end
# Checks if the given target requires language specific settings and # Checks if the given target requires language specific settings and
# configures the given Xcconfig. # configures the given Xcconfig.
# #
...@@ -205,6 +268,8 @@ module Pod ...@@ -205,6 +268,8 @@ module Pod
# @param [Xcodeproj::Config] xcconfig # @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit. # The xcconfig to edit.
# #
# @return [void]
#
def self.add_language_specific_settings(target, xcconfig) def self.add_language_specific_settings(target, xcconfig)
if target.uses_swift? if target.uses_swift?
build_settings = { build_settings = {
......
...@@ -108,7 +108,6 @@ module Pod ...@@ -108,7 +108,6 @@ module Pod
prepare prepare
resolve_dependencies resolve_dependencies
download_dependencies download_dependencies
determine_dependency_product_types
verify_no_duplicate_framework_names verify_no_duplicate_framework_names
verify_no_static_framework_transitive_dependencies verify_no_static_framework_transitive_dependencies
verify_framework_usage verify_framework_usage
...@@ -376,22 +375,6 @@ module Pod ...@@ -376,22 +375,6 @@ module Pod
end end
end end
# Determines if the dependencies need to be built as dynamic frameworks or
# if they can be built as static libraries by checking for the Swift source
# presence. Therefore it is important that the file accessors of the
# #pod_targets are created.
#
# @return [void]
#
def determine_dependency_product_types
aggregate_targets.each do |aggregate_target|
aggregate_target.pod_targets.each do |pod_target|
pod_target.host_requires_frameworks ||= aggregate_target.requires_frameworks?
pod_target.platform = nil # needs to be recomputed
end
end
end
def verify_no_duplicate_framework_names def verify_no_duplicate_framework_names
aggregate_targets.each do |aggregate_target| aggregate_targets.each do |aggregate_target|
aggregate_target.user_build_configurations.keys.each do |config| aggregate_target.user_build_configurations.keys.each do |config|
...@@ -629,13 +612,11 @@ module Pod ...@@ -629,13 +612,11 @@ 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_definitions.all?(&:abstract?)
target_installer = PodTargetInstaller.new(sandbox, pod_target) target_installer = PodTargetInstaller.new(sandbox, pod_target)
target_installer.install! target_installer.install!
end end
aggregate_targets.sort_by(&:name).each do |target| aggregate_targets.sort_by(&:name).each do |target|
next if target.target_definition.abstract?
target_installer = AggregateTargetInstaller.new(sandbox, target) target_installer = AggregateTargetInstaller.new(sandbox, target)
target_installer.install! target_installer.install!
end end
...@@ -679,23 +660,15 @@ module Pod ...@@ -679,23 +660,15 @@ module Pod
aggregate_target.native_target.add_dependency(pod_target.native_target) aggregate_target.native_target.add_dependency(pod_target.native_target)
configure_app_extension_api_only_for_target(pod_target) if is_app_extension configure_app_extension_api_only_for_target(pod_target) if is_app_extension
pod_target.dependencies.each do |dep| pod_target.dependent_targets.each do |pod_dependency_target|
unless dep == pod_target.pod_name next unless pod_dependency_target.should_build?
pod_dependency_target = aggregate_target.pod_targets.find { |target| target.pod_name == dep } pod_target.native_target.add_dependency(pod_dependency_target.native_target)
# TODO: remove me configure_app_extension_api_only_for_target(pod_dependency_target) if is_app_extension
unless pod_dependency_target
puts "[BUG] DEP: #{dep}"
end
next unless pod_dependency_target.should_build?
pod_target.native_target.add_dependency(pod_dependency_target.native_target)
configure_app_extension_api_only_for_target(pod_dependency_target) if is_app_extension
if pod_target.requires_frameworks? if pod_target.requires_frameworks?
product_ref = frameworks_group.files.find { |f| f.path == pod_dependency_target.product_name } || product_ref = frameworks_group.files.find { |f| f.path == pod_dependency_target.product_name } ||
frameworks_group.new_product_ref_for_target(pod_dependency_target.product_basename, pod_dependency_target.product_type) frameworks_group.new_product_ref_for_target(pod_dependency_target.product_basename, pod_dependency_target.product_type)
pod_target.native_target.frameworks_build_phase.add_file_reference(product_ref, true) pod_target.native_target.frameworks_build_phase.add_file_reference(product_ref, true)
end
end end
end end
end end
......
...@@ -13,6 +13,8 @@ module Pod ...@@ -13,6 +13,8 @@ module Pod
autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer' autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer'
autoload :SpecsState, 'cocoapods/installer/analyzer/specs_state' autoload :SpecsState, 'cocoapods/installer/analyzer/specs_state'
autoload :LockingDependencyAnalyzer, 'cocoapods/installer/analyzer/locking_dependency_analyzer' autoload :LockingDependencyAnalyzer, 'cocoapods/installer/analyzer/locking_dependency_analyzer'
autoload :PodVariant, 'cocoapods/installer/analyzer/pod_variant'
autoload :PodVariantSet, 'cocoapods/installer/analyzer/pod_variant_set'
autoload :TargetInspectionResult, 'cocoapods/installer/analyzer/target_inspection_result' autoload :TargetInspectionResult, 'cocoapods/installer/analyzer/target_inspection_result'
autoload :TargetInspector, 'cocoapods/installer/analyzer/target_inspector' autoload :TargetInspector, 'cocoapods/installer/analyzer/target_inspector'
...@@ -228,8 +230,9 @@ module Pod ...@@ -228,8 +230,9 @@ module Pod
# @return [Array<AggregateTarget>] # @return [Array<AggregateTarget>]
# #
def generate_targets def generate_targets
pod_targets = generate_pod_targets(result.specs_by_target) specs_by_target = result.specs_by_target.reject { |td, _| td.abstract? }
aggregate_targets = result.specs_by_target.keys.reject(&:abstract?).map do |target_definition| pod_targets = generate_pod_targets(specs_by_target)
aggregate_targets = specs_by_target.keys.map do |target_definition|
generate_target(target_definition, pod_targets) generate_target(target_definition, pod_targets)
end end
aggregate_targets.each do |target| aggregate_targets.each do |target|
...@@ -286,85 +289,84 @@ module Pod ...@@ -286,85 +289,84 @@ module Pod
# @return [Array<PodTarget>] # @return [Array<PodTarget>]
# #
def generate_pod_targets(specs_by_target) def generate_pod_targets(specs_by_target)
dedupe_cache = {}
if installation_options.deduplicate_targets? if installation_options.deduplicate_targets?
all_specs = specs_by_target.flat_map do |target_definition, dependent_specs| distinct_targets = specs_by_target.each_with_object({}) do |dependency, hash|
dependent_specs.group_by(&:root).map do |root_spec, specs| target_definition, dependent_specs = *dependency
[root_spec, specs, target_definition] dependent_specs.group_by(&:root).each do |root_spec, specs|
pod_variant = PodVariant.new(specs, target_definition.platform, target_definition.uses_frameworks?)
hash[root_spec] ||= {}
(hash[root_spec][pod_variant] ||= []) << target_definition
end end
end end
distinct_targets = all_specs.each_with_object({}) do |dependency, hash| pod_targets = distinct_targets.flat_map do |_root, target_definitions_by_variant|
root_spec, specs, target_definition = *dependency suffixes = PodVariantSet.new(target_definitions_by_variant.keys).scope_suffixes
hash[root_spec] ||= {} target_definitions_by_variant.flat_map do |variant, target_definitions|
(hash[root_spec][[specs, target_definition.platform]] ||= []) << target_definition generate_pod_target(target_definitions, variant.specs, :scope_suffix => suffixes[variant])
end
pod_targets = distinct_targets.flat_map do |_, targets_by_distinctors|
if targets_by_distinctors.count > 1
# There are different sets of subspecs or the spec is used across different platforms
targets_by_distinctors.flat_map do |distinctor, target_definitions|
specs, = *distinctor
generate_pod_target(target_definitions, specs).scoped(dedupe_cache)
end
else
(specs, _), target_definitions = targets_by_distinctors.first
generate_pod_target(target_definitions, specs)
end end
end end
# A `PodTarget` can't be deduplicated if any of its all_specs = specs_by_target.values.flatten.uniq
# transitive dependencies can't be deduplicated. pod_targets_by_name = pod_targets.group_by(&:pod_name).each_with_object({}) do |(name, values), hash|
pod_targets.flat_map do |target| # Sort the target by the number of activated subspecs, so that
dependent_targets = transitive_dependencies_for_pod_target(target, pod_targets) # we prefer a minimal target as transitive dependency.
target.dependent_targets = dependent_targets hash[name] = values.sort_by { |pt| pt.specs.count }
if dependent_targets.any?(&:scoped?) end
target.scoped(dedupe_cache) pod_targets.each do |target|
else dependencies = transitive_dependencies_for_specs(target.specs, target.platform, all_specs).group_by(&:root)
target target.dependent_targets = dependencies.map do |root_spec, deps|
pod_targets_by_name[root_spec.name].find do |t|
next false if t.platform.symbolic_name != target.platform.symbolic_name ||
t.requires_frameworks? != target.requires_frameworks?
spec_names = t.specs.map(&:name)
deps.all? { |dep| spec_names.include?(dep.name) }
end
end end
end end
else else
pod_targets = specs_by_target.flat_map do |target_definition, specs| dedupe_cache = {}
grouped_specs = specs.group_by.group_by(&:root).values.uniq specs_by_target.flat_map do |target_definition, specs|
grouped_specs.flat_map do |pod_specs| grouped_specs = specs.group_by(&:root).values.uniq
pod_targets = grouped_specs.flat_map do |pod_specs|
generate_pod_target([target_definition], pod_specs).scoped(dedupe_cache) generate_pod_target([target_definition], pod_specs).scoped(dedupe_cache)
end end
end
pod_targets.each do |target| pod_targets.each do |target|
target.dependent_targets = transitive_dependencies_for_pod_target(target, pod_targets) dependencies = transitive_dependencies_for_specs(target.specs, target.platform, specs).group_by(&:root)
target.dependent_targets = pod_targets.reject { |t| dependencies[t.root_spec].nil? }
end
end end
end end
end end
# Finds the names of the Pods upon which the given target _transitively_ # Returns the specs upon which the given specs _transitively_ depend.
# depends.
# #
# @note: This is implemented in the analyzer, because we don't have to # @note: This is implemented in the analyzer, because we don't have to
# care about the requirements after dependency resolution. # care about the requirements after dependency resolution.
# #
# @param [PodTarget] pod_target # @param [Array<Specification>] specs
# The pod target, whose dependencies should be returned. # The specs, whose dependencies should be returned.
# #
# @param [Array<PodTarget>] targets # @param [Platform] platform
# All pod targets, which are integrated alongside. # The platform for which the dependencies should be returned.
# #
# @return [Array<PodTarget>] # @param [Array<Specification>] all_specs
# All specifications which are installed alongside.
# #
def transitive_dependencies_for_pod_target(pod_target, targets) # @return [Array<Specification>]
if targets.any? #
dependent_targets = pod_target.dependencies.flat_map do |dep| def transitive_dependencies_for_specs(specs, platform, all_specs)
next [] if pod_target.pod_name == dep return [] if specs.empty? || all_specs.empty?
targets.select { |t| t.pod_name == dep } dependent_specs = specs.flat_map do |spec|
end spec.consumer(platform).dependencies.flat_map do |dependency|
remaining_targets = targets - dependent_targets all_specs.find do |s|
dependent_targets += dependent_targets.flat_map do |target| next false if specs.include?(s)
transitive_dependencies_for_pod_target(target, remaining_targets) s.name == dependency.name
end end
dependent_targets.uniq end.compact
else end.uniq
[] remaining_specs = all_specs - dependent_specs
end dependent_specs + transitive_dependencies_for_specs(dependent_specs, platform, remaining_specs)
end end
# Create a target for each spec group # Create a target for each spec group
...@@ -372,13 +374,17 @@ module Pod ...@@ -372,13 +374,17 @@ module Pod
# @param [TargetDefinitions] target_definitions # @param [TargetDefinitions] target_definitions
# the aggregate target # the aggregate target
# #
# @param [Array<Specification>] specs # @param [Array<Specification>] pod_specs
# the specifications of an equal root. # the specifications of an equal root.
# #
# @param [String] scope_suffix
# @see PodTarget#scope_suffix
#
# @return [PodTarget] # @return [PodTarget]
# #
def generate_pod_target(target_definitions, pod_specs) def generate_pod_target(target_definitions, pod_specs, scope_suffix: nil)
pod_target = PodTarget.new(pod_specs, target_definitions, sandbox) pod_target = PodTarget.new(pod_specs, target_definitions, sandbox, scope_suffix)
pod_target.host_requires_frameworks = target_definitions.any?(&:uses_frameworks?)
if installation_options.integrate_targets? if installation_options.integrate_targets?
target_inspections = result.target_inspections.select { |t, _| target_definitions.include?(t) }.values target_inspections = result.target_inspections.select { |t, _| target_definitions.include?(t) }.values
......
...@@ -21,8 +21,8 @@ module Pod ...@@ -21,8 +21,8 @@ module Pod
# #
attr_accessor :sandbox_state attr_accessor :sandbox_state
# @return [Array<Target>] The Podfile targets containing library # @return [Array<AggregateTarget>] The aggregate targets created for each
# dependencies. # {TargetDefinition} from the {Podfile}.
# #
attr_accessor :targets attr_accessor :targets
......
module Pod
class Installer
class Analyzer
# Bundles the information needed to setup a {PodTarget}.
class PodVariant
# @return [Array<Specification>] the spec and subspecs for the target
#
attr_accessor :specs
# @return [Platform] the platform
#
attr_accessor :platform
# @return [Bool] whether this pod should be built as framework
#
attr_accessor :requires_frameworks
alias_method :requires_frameworks?, :requires_frameworks
# @return [Specification] the root specification
#
def root_spec
specs.first.root
end
# Initialize a new instance from its attributes.
#
# @param [Array<String>] specs @see #specs
# @param [Platform] platform @see #platform
# @param [Bool] requires_frameworks @see #requires_frameworks?
#
def initialize(specs, platform, requires_frameworks = false)
self.specs = specs
self.platform = platform
self.requires_frameworks = requires_frameworks
end
# @return [Bool] whether the {PodVariant} is equal to another taking all
# all their attributes into account
#
def ==(other)
self.class == other.class &&
specs == other.specs &&
platform == other.platform &&
requires_frameworks == other.requires_frameworks
end
alias_method :eql?, :==
# Hashes the instance by all its attributes.
#
# This adds support to make instances usable as Hash keys.
#
# @!visibility private
def hash
[specs, platform, requires_frameworks].hash
end
end
end
end
end
require 'set'
module Pod
class Installer
class Analyzer
# Collects all {PodVariant}.
class PodVariantSet
# @return [Array<PodVariant>] the different variants.
#
attr_accessor :variants
# Initialize a new instance.
#
# @param [Array<PodVariant>] variants @see #variants
#
def initialize(variants)
self.variants = variants
end
# Describes what makes each {PodVariant} distinct among the others.
#
# @return [Hash<PodVariant, String>]
#
def scope_suffixes
return { variants.first => nil } if variants.count == 1
scope_by_specs
end
# Groups the collection by result of the block.
#
# @param [Block<Variant, #hash>] block
# @return [Array<PodVariantSet>]
#
def group_by(&block)
variants.group_by(&block).map { |_, v| PodVariantSet.new(v) }
end
# @private
#
# Prepends the given scoped {PodVariant}s with another scoping label, if there
# was more than one group of {PodVariant}s given.
#
# @param [Array<Hash<PodVariant, String>>] scoped_variants
# {PodVariant}s, which where grouped on base of a criteria, which is used
# in the block argument to generate a descriptive label.
#
# @param [Block<PodVariant, String>] block
# takes a {PodVariant} and returns a scope suffix which is prepended, if
# necessary.
#
# @return [Hash<PodVariant, String>]
#
def scope_if_necessary(scoped_variants, &block)
if scoped_variants.count == 1
return scoped_variants.first
end
Hash[scoped_variants.flat_map do |variants|
variants.map do |variant, suffix|
prefix = block.call(variant)
scope = [prefix, suffix].compact.join('-')
[variant, !scope.empty? ? scope : nil]
end
end]
end
# @private
# @return [Hash<PodVariant, String>]
#
def scope_by_build_type
scope_if_necessary(group_by(&:requires_frameworks).map(&:scope_by_platform)) do |variant|
variant.requires_frameworks? ? 'framework' : 'library'
end
end
# @private
# @return [Hash<PodVariant, String>]
#
def scope_by_platform
grouped_variants = group_by { |v| v.platform.name }
if grouped_variants.all? { |set| set.variants.count == 1 }
# => Platform name
platform_name_proc = proc { |v| Platform.string_name(v.platform.symbolic_name).tr(' ', '') }
else
grouped_variants = group_by(&:platform)
# => Platform name + SDK version
platform_name_proc = proc { |v| v.platform.to_s.tr(' ', '') }
end
scope_if_necessary(grouped_variants.map(&:scope_without_suffix), &platform_name_proc)
end
# @private
# @return [Hash<PodVariant, String>]
#
def scope_by_specs
root_spec = variants.first.root_spec
specs = [root_spec]
if root_spec.default_subspecs.empty?
specs += root_spec.subspecs.compact
else
specs += root_spec.default_subspecs.map do |subspec_name|
root_spec.subspec_by_name("#{root_spec.name}/#{subspec_name}")
end
end
default_specs = Set.new(specs)
grouped_variants = group_by(&:specs)
all_spec_variants = grouped_variants.map { |set| set.variants.first.specs }
common_specs = all_spec_variants.map(&:to_set).flatten.inject(&:&)
omit_common_specs = common_specs.any? && common_specs.proper_superset?(default_specs)
scope_if_necessary(grouped_variants.map(&:scope_by_build_type)) do |variant|
specs = variant.specs.to_set
# The current variant contains all default specs
omit_default_specs = default_specs.any? && default_specs.subset?(specs)
if omit_default_specs
specs -= default_specs
end
# There are common specs, which are different from the default specs
if omit_common_specs
specs -= common_specs
end
spec_names = specs.map do |spec|
spec.root? ? '.root' : spec.name.split('/')[1..-1].join('_')
end.sort
if spec_names.empty?
omit_common_specs ? '.common' : nil
else
if omit_common_specs
spec_names.unshift('.common')
elsif omit_default_specs
spec_names.unshift('.default')
end
spec_names.reduce('') do |acc, name|
"#{acc}#{acc.empty? || name[0] == '.' ? '' : '-'}#{name}"
end
end
end
end
# @private
#
# Helps to define scope suffixes recursively.
#
# @return [Hash<PodVariant, String>]
#
def scope_without_suffix
Hash[variants.map { |v| [v, nil] }]
end
end
end
end
end
...@@ -151,7 +151,7 @@ module Pod ...@@ -151,7 +151,7 @@ module Pod
end end
frameworks_by_config[config] = relevant_pod_targets.flat_map do |pod_target| frameworks_by_config[config] = relevant_pod_targets.flat_map do |pod_target|
frameworks = pod_target.file_accessors.flat_map(&:vendored_dynamic_artifacts).map { |fw| "${PODS_ROOT}/#{fw.relative_path_from(sandbox.root)}" } frameworks = pod_target.file_accessors.flat_map(&:vendored_dynamic_artifacts).map { |fw| "${PODS_ROOT}/#{fw.relative_path_from(sandbox.root)}" }
frameworks << "#{target_definition.label}/#{pod_target.product_name}" if pod_target.should_build? && pod_target.requires_frameworks? frameworks << pod_target.build_product_path if pod_target.should_build? && pod_target.requires_frameworks?
frameworks frameworks
end end
end end
......
...@@ -216,7 +216,7 @@ module Pod ...@@ -216,7 +216,7 @@ module Pod
end end
def targets_to_integrate def targets_to_integrate
targets.reject { |target| target.target_definition.abstract? } targets
end end
# Prints a warning informing the user that a build configuration of # Prints a warning informing the user that a build configuration of
......
...@@ -13,6 +13,7 @@ module Pod ...@@ -13,6 +13,7 @@ module Pod
# @param [Sandbox] sandbox @see sandbox # @param [Sandbox] sandbox @see sandbox
# #
def initialize(target_definition, sandbox) def initialize(target_definition, sandbox)
raise "Can't initialize an AggregateTarget with an abstract TargetDefinition" if target_definition.abstract?
super() super()
@target_definition = target_definition @target_definition = target_definition
@sandbox = sandbox @sandbox = sandbox
...@@ -205,13 +206,6 @@ module Pod ...@@ -205,13 +206,6 @@ 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
......
...@@ -19,19 +19,25 @@ module Pod ...@@ -19,19 +19,25 @@ module Pod
# @return [Bool] whether the target needs to be scoped by target definition, # @return [Bool] whether the target needs to be scoped by target definition,
# because the spec is used with different subspec sets across them. # because the spec is used with different subspec sets across them.
# #
# @note For frameworks the target products of {PodTarget}s are named # @note The target products of {PodTarget}s are named after their specs.
# after their specs. The namespacing cannot directly happen in # The namespacing cannot directly happen in the product name itself,
# the product name itself, because this must be equal to the module # because this must be equal to the module name and this will be
# name and this will be used in source code, which should stay # used in source code, which should stay agnostic over the
# agnostic over the dependency manager. # dependency manager.
# We need namespacing because multiple targets can exist for the # We need namespacing because multiple targets can exist for the
# same podspec and their products should not collide. This # same podspec and their products should not collide. This
# duplication is needed when multiple user targets have the same # duplication is needed when multiple user targets have the same
# dependency, but they require different sets of subspecs or they # dependency, but they require different sets of subspecs or they
# are on different platforms. # are on different platforms.
# #
attr_reader :scoped def scoped?
alias_method :scoped?, :scoped !scope_suffix.nil?
end
# @return [String] used for the label and the directory name, which is used to
# scope the build product in the default configuration build dir.
#
attr_reader :scope_suffix
# @return [Array<PodTarget>] the targets that this target has a dependency # @return [Array<PodTarget>] the targets that this target has a dependency
# upon. # upon.
...@@ -41,16 +47,18 @@ module Pod ...@@ -41,16 +47,18 @@ module Pod
# @param [Array<Specification>] @spec #see spec # @param [Array<Specification>] @spec #see spec
# @param [Array<TargetDefinition>] target_definitions @see target_definitions # @param [Array<TargetDefinition>] target_definitions @see target_definitions
# @param [Sandbox] sandbox @see sandbox # @param [Sandbox] sandbox @see sandbox
# @param [Bool] scoped @see scoped # @param [String] scope_suffix @see scope_suffix
# #
def initialize(specs, target_definitions, sandbox, scoped = false) def initialize(specs, target_definitions, sandbox, scope_suffix = nil)
raise "Can't initialize a PodTarget without specs!" if specs.nil? || specs.empty? raise "Can't initialize a PodTarget without specs!" if specs.nil? || specs.empty?
raise "Can't initialize a PodTarget without TargetDefinition!" if target_definitions.nil? || target_definitions.empty? raise "Can't initialize a PodTarget without TargetDefinition!" if target_definitions.nil? || target_definitions.empty?
raise "Can't initialize a PodTarget with only abstract TargetDefinitions" if target_definitions.all?(&:abstract?)
raise "Can't initialize a PodTarget with an empty string scope suffix!" if scope_suffix == ''
super() super()
@specs = specs @specs = specs
@target_definitions = target_definitions @target_definitions = target_definitions
@sandbox = sandbox @sandbox = sandbox
@scoped = scoped @scope_suffix = scope_suffix
@build_headers = Sandbox::HeadersStore.new(sandbox, 'Private') @build_headers = Sandbox::HeadersStore.new(sandbox, 'Private')
@file_accessors = [] @file_accessors = []
@resource_bundle_targets = [] @resource_bundle_targets = []
...@@ -67,7 +75,7 @@ module Pod ...@@ -67,7 +75,7 @@ module Pod
if cache[cache_key] if cache[cache_key]
cache[cache_key] cache[cache_key]
else else
target = PodTarget.new(specs, [target_definition], sandbox, true) target = PodTarget.new(specs, [target_definition], sandbox, target_definition.label)
target.file_accessors = file_accessors target.file_accessors = file_accessors
target.user_build_configurations = user_build_configurations target.user_build_configurations = user_build_configurations
target.native_target = native_target target.native_target = native_target
...@@ -82,7 +90,11 @@ module Pod ...@@ -82,7 +90,11 @@ module Pod
# #
def label def label
if scoped? if scoped?
"#{target_definitions.first.label}-#{root_spec.name}" if scope_suffix[0] == '.'
"#{root_spec.name}#{scope_suffix}"
else
"#{root_spec.name}-#{scope_suffix}"
end
else else
root_spec.name root_spec.name
end end
...@@ -241,15 +253,24 @@ module Pod ...@@ -241,15 +253,24 @@ module Pod
end end
end end
# @return [String] The configuration build dir, relevant if the target is # @param [String] dir
# integrated as framework. # The directory (which might be a variable) relative to which
# the returned path should be. This must be used if the
# $CONFIGURATION_BUILD_DIR is modified.
# #
def configuration_build_dir # @return [String] The absolute path to the configuration build dir
if scoped? #
"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/#{target_definitions.first.label}" def configuration_build_dir(dir = '$CONFIGURATION_BUILD_DIR')
else "#{dir}/#{label}"
'$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)' end
end
# @param [String] dir
# @see #configuration_build_dir
#
# @return [String] The absolute path to the build product
#
def build_product_path(dir = '$CONFIGURATION_BUILD_DIR')
"#{configuration_build_dir(dir)}/#{product_name}"
end end
private private
......
...@@ -428,7 +428,7 @@ module Pod ...@@ -428,7 +428,7 @@ module Pod
# for all available platforms with xcodebuild. # for all available platforms with xcodebuild.
# #
def install_pod def install_pod
%i(determine_dependency_product_types verify_no_duplicate_framework_names %i(verify_no_duplicate_framework_names
verify_no_static_framework_transitive_dependencies verify_no_static_framework_transitive_dependencies
verify_framework_usage generate_pods_project integrate_user_project verify_framework_usage generate_pods_project integrate_user_project
perform_post_install_actions).each { |m| @installer.send(m) } perform_post_install_actions).each { |m| @installer.send(m) }
......
Subproject commit 05c3fc9beea098b5e1ce3aaa882d454511e6348c Subproject commit 1adc26822f4509232f6953e421d592753ac98c19
Pod::Spec.new do |s|
s.name = "matryoshka"
s.version = "1.0.0"
s.author = { "Matryona Malyutin" => "matryona@malyutin.local" }
s.summary = "👩‍👩‍👧"
s.description = "Four levels: outmost (root), outer, inner"
s.homepage = "http://httpbin.org/html"
s.source = { :git => "http://malyutin.local/matryoshka.git", :tag => s.version.to_s }
s.license = 'MIT'
s.source_files = 'Outmost.{h,m}'
s.default_subspecs = 'Outer'
s.subspec 'Outer' do |outer_subspec|
outer_subspec.source_files = 'Outer/Outer.{h,m}'
outer_subspec.subspec 'Inner' do |inner_subspec|
inner_subspec.source_files = 'Inner/Inner.{h,m}'
end
end
s.subspec 'Foo' do |ss|
ss.source_files = 'Foo/Foo.{h,m}'
end
s.subspec 'Bar' do |ss|
ss.source_files = 'Bar/Bar.{h,m}'
end
end
...@@ -13,4 +13,6 @@ Pod::Spec.new do |s| ...@@ -13,4 +13,6 @@ Pod::Spec.new do |s|
s.source_files = 'Source/Juicer.swift' s.source_files = 'Source/Juicer.swift'
s.frameworks = 'UIKit' s.frameworks = 'UIKit'
s.dependency 'matryoshka'
end end
...@@ -13,4 +13,6 @@ Pod::Spec.new do |s| ...@@ -13,4 +13,6 @@ Pod::Spec.new do |s|
s.source_files = 'Source/Juicer.swift' s.source_files = 'Source/Juicer.swift'
s.frameworks = 'UIKit' s.frameworks = 'UIKit'
s.dependency 'matryoshka'
end end
{
"name": "matryoshka",
"version": "1.0.0",
"authors": {
"Matryona Malyutin": "matryona@malyutin.local"
},
"summary": "👩‍👩‍👧",
"description": "Four levels: outmost (root), outer, inner",
"homepage": "http://httpbin.org/html",
"source": {
"git": "http://malyutin.local/matroyshka.git",
"tag": "1.0.0"
},
"license": "MIT",
"source_files": "Outmost.{h,m}",
"default_subspecs": "Outer",
"platforms": {
"osx": null,
"ios": null,
"tvos": null,
"watchos": null
},
"subspecs": [
{
"name": "Outer",
"source_files": "Outer/Outer.{h,m}",
"subspecs": [
{
"name": "Inner",
"source_files": "Inner/Inner.{h,m}"
}
]
},
{
"name": "Foo",
"source_files": "Foo/Foo.{h,m}"
},
{
"name": "Bar",
"source_files": "Bar/Bar.{h,m}"
}
]
}
...@@ -116,14 +116,15 @@ def fixture_file_accessor(spec_or_name, platform = Pod::Platform.ios) ...@@ -116,14 +116,15 @@ def fixture_file_accessor(spec_or_name, platform = Pod::Platform.ios)
end end
def fixture_target_definition(name = 'Pods', platform = Pod::Platform.ios) def fixture_target_definition(name = 'Pods', platform = Pod::Platform.ios)
Pod::Podfile::TargetDefinition.new(name, Pod::Podfile.new, 'name' => name, 'platform' => platform) platform_hash = { platform.symbolic_name => platform.deployment_target }
Pod::Podfile::TargetDefinition.new(name, Pod::Podfile.new, 'name' => name, 'platform' => platform_hash)
end end
def fixture_pod_target(spec_or_name, target_definition = nil) def fixture_pod_target(spec_or_name, target_definitions = [])
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_definitions << fixture_target_definition if target_definitions.empty?
target_definition.store_pod(spec.name) target_definitions.each { |td| td.store_pod(spec.name) }
Pod::PodTarget.new([spec], [target_definition], config.sandbox).tap do |pod_target| Pod::PodTarget.new([spec], target_definitions, config.sandbox).tap do |pod_target|
pod_target.file_accessors << fixture_file_accessor(spec, pod_target.platform) pod_target.file_accessors << fixture_file_accessor(spec, pod_target.platform)
consumer = spec.consumer(pod_target.platform) consumer = spec.consumer(pod_target.platform)
pod_target.spec_consumers << consumer pod_target.spec_consumers << consumer
......
...@@ -4,24 +4,22 @@ module Pod ...@@ -4,24 +4,22 @@ module Pod
module Generator module Generator
module XCConfig module XCConfig
describe AggregateXCConfig do describe AggregateXCConfig do
def spec def specs
fixture_spec('banana-lib/BananaLib.podspec') [fixture_spec('banana-lib/BananaLib.podspec')]
end end
def pod_target(spec) def pod_target(spec, target_definition)
fixture_pod_target(spec) fixture_pod_target(spec, [target_definition])
end end
before do before do
@spec = spec @target_definition = fixture_target_definition
@spec.user_target_xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' } @specs = specs
@spec.pod_target_xcconfig = { 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11' } @specs.first.user_target_xcconfig = { 'OTHER_LDFLAGS' => '-no_compact_unwind' }
@pod_target = pod_target(@spec) @specs.first.pod_target_xcconfig = { 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11' }
@consumer = @pod_target.spec_consumers.last @pod_targets = @specs.map { |spec| pod_target(spec, @target_definition) }
@target = fixture_aggregate_target([@pod_target]) @target = fixture_aggregate_target(@pod_targets, @target_definition)
@target.target_definition.should == @pod_target.target_definitions.first @target.target_definition.whitelist_pod_for_configuration(@specs.first.name, 'Release')
@target.target_definition.whitelist_pod_for_configuration(@spec.name, 'Release')
@podfile = @target.target_definition.podfile
@generator = AggregateXCConfig.new(@target, 'Release') @generator = AggregateXCConfig.new(@target, 'Release')
end end
...@@ -33,6 +31,8 @@ module Pod ...@@ -33,6 +31,8 @@ module Pod
#--------------------------------------------------------------------# #--------------------------------------------------------------------#
before do before do
@consumer = @pod_targets.first.spec_consumers.last
@podfile = @target.target_definition.podfile
@xcconfig = @generator.generate @xcconfig = @generator.generate
end end
...@@ -74,7 +74,7 @@ module Pod ...@@ -74,7 +74,7 @@ module Pod
describe 'if a pod target does not contain source files' do describe 'if a pod target does not contain source files' do
before do before do
@pod_target.file_accessors.first.stubs(:source_files).returns([]) @pod_targets.first.file_accessors.first.stubs(:source_files).returns([])
@xcconfig = @generator.generate @xcconfig = @generator.generate
end end
...@@ -94,8 +94,8 @@ module Pod ...@@ -94,8 +94,8 @@ module Pod
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
describe 'with library' do describe 'with library' do
def spec def specs
fixture_spec('banana-lib/BananaLib.podspec') [fixture_spec('banana-lib/BananaLib.podspec')]
end end
behaves_like 'AggregateXCConfig' behaves_like 'AggregateXCConfig'
...@@ -115,12 +115,12 @@ module Pod ...@@ -115,12 +115,12 @@ module Pod
end end
describe 'with a scoped pod target' do describe 'with a scoped pod target' do
def pod_target(spec) def pod_target(spec, target_definition)
fixture_pod_target(spec).scoped.first fixture_pod_target(spec, [target_definition]).scoped.first
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 '-l"Pods-BananaLib"' @xcconfig.to_hash['OTHER_LDFLAGS'].should.include '-l"BananaLib-Pods"'
end end
end end
...@@ -138,8 +138,8 @@ module Pod ...@@ -138,8 +138,8 @@ module Pod
end end
describe 'with framework' do describe 'with framework' do
def spec def specs
fixture_spec('orange-framework/OrangeFramework.podspec') [fixture_spec('orange-framework/OrangeFramework.podspec')]
end end
before do before do
...@@ -153,8 +153,8 @@ module Pod ...@@ -153,8 +153,8 @@ module Pod
end end
describe 'with a vendored-library pod' do describe 'with a vendored-library pod' do
def spec def specs
fixture_spec('monkey/monkey.podspec') [fixture_spec('monkey/monkey.podspec')]
end end
it 'does add the framework build path to the xcconfig' do it 'does add the framework build path to the xcconfig' do
...@@ -171,8 +171,8 @@ module Pod ...@@ -171,8 +171,8 @@ module Pod
end end
it 'includes the public header paths as system headers' do it 'includes the public header paths as system headers' do
expected = '$(inherited) -iquote "$CONFIGURATION_BUILD_DIR/OrangeFramework.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public"' expected = '$(inherited) -iquote "$CONFIGURATION_BUILD_DIR/OrangeFramework/OrangeFramework.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public"'
@generator.stubs(:pod_targets).returns([@pod_target, pod_target(fixture_spec('orange-framework/OrangeFramework.podspec'))]) @generator.stubs(:pod_targets).returns([@pod_targets.first, pod_target(fixture_spec('orange-framework/OrangeFramework.podspec'), @target_definition)])
@xcconfig = @generator.generate @xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected @xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end end
...@@ -188,32 +188,39 @@ module Pod ...@@ -188,32 +188,39 @@ module Pod
end end
end end
it 'sets the PODS_FRAMEWORK_BUILD_PATH build variable' do
@xcconfig.to_hash['PODS_FRAMEWORK_BUILD_PATH'].should == '"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods"'
end
describe 'with a scoped pod target' do describe 'with a scoped pod target' do
def pod_target(spec) def specs
fixture_pod_target(spec).scoped.first [
fixture_spec('banana-lib/BananaLib.podspec'),
fixture_spec('orange-framework/OrangeFramework.podspec'),
]
end
def pod_target(spec, target_definition)
target_definition = fixture_target_definition(spec.name)
target_definition.stubs(:parent).returns(@target_definition.podfile)
fixture_pod_target(spec, [target_definition, @target_definition].uniq).tap do |pod_target|
pod_target.stubs(:scope_suffix).returns('iOS')
end
end 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) "$CONFIGURATION_BUILD_DIR/BananaLib-iOS" "$CONFIGURATION_BUILD_DIR/OrangeFramework-iOS"'
end end
it 'adds the framework header paths to the xcconfig, with quotes, as local headers' do it 'adds the framework header paths to the xcconfig, with quotes, as local headers' do
expected = '$(inherited) -iquote "$PODS_FRAMEWORK_BUILD_PATH/OrangeFramework.framework/Headers"' expected = '$(inherited) -iquote "$CONFIGURATION_BUILD_DIR/BananaLib-iOS/BananaLib.framework/Headers" -iquote "$CONFIGURATION_BUILD_DIR/OrangeFramework-iOS/OrangeFramework.framework/Headers"'
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected @xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end end
end end
describe 'with an unscoped pod target' do describe 'with an unscoped pod target' do
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.be.nil @xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should == '$(inherited) "$CONFIGURATION_BUILD_DIR/OrangeFramework"'
end end
it 'adds the framework header paths to the xcconfig, with quotes, as local headers' do it 'adds the framework header paths to the xcconfig, with quotes, as local headers' do
expected = '$(inherited) -iquote "$CONFIGURATION_BUILD_DIR/OrangeFramework.framework/Headers"' expected = '$(inherited) -iquote "$CONFIGURATION_BUILD_DIR/OrangeFramework/OrangeFramework.framework/Headers"'
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected @xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end end
end end
...@@ -271,12 +278,16 @@ module Pod ...@@ -271,12 +278,16 @@ module Pod
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
describe 'with multiple pod targets with user_target_xcconfigs' do describe 'with multiple pod targets with user_target_xcconfigs' do
def specs
[
fixture_spec('banana-lib/BananaLib.podspec'),
fixture_spec('orange-framework/OrangeFramework.podspec'),
]
end
before do before do
spec_b = fixture_spec('orange-framework/OrangeFramework.podspec') @consumer_a = @pod_targets[0].spec_consumers.last
@pod_target_b = fixture_pod_target(spec_b) @consumer_b = @pod_targets[1].spec_consumers.last
@consumer_a = @consumer
@consumer_b = @pod_target_b.spec_consumers.last
@target.pod_targets << @pod_target_b
end end
describe 'with boolean build settings' do describe 'with boolean build settings' do
...@@ -315,7 +326,7 @@ module Pod ...@@ -315,7 +326,7 @@ module Pod
it 'adds values from all subspecs' do it 'adds values from all subspecs' do
@consumer_b.stubs(:user_target_xcconfig).returns('OTHER_CPLUSPLUSFLAGS' => '-std=c++1y') @consumer_b.stubs(:user_target_xcconfig).returns('OTHER_CPLUSPLUSFLAGS' => '-std=c++1y')
consumer_c = mock(:user_target_xcconfig => { 'OTHER_CPLUSPLUSFLAGS' => '-stdlib=libc++' }) consumer_c = mock(:user_target_xcconfig => { 'OTHER_CPLUSPLUSFLAGS' => '-stdlib=libc++' })
@pod_target_b.stubs(:spec_consumers).returns([@consumer_b, consumer_c]) @pod_targets[1].stubs(:spec_consumers).returns([@consumer_b, consumer_c])
@xcconfig = @generator.generate @xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_CPLUSPLUSFLAGS'].should == '-std=c++1y -stdlib=libc++' @xcconfig.to_hash['OTHER_CPLUSPLUSFLAGS'].should == '-std=c++1y -stdlib=libc++'
end end
......
require File.expand_path('../../../../spec_helper', __FILE__)
module Pod
describe PodVariantSet = Installer::Analyzer::PodVariantSet do
describe '#scope_suffixes' do
before do
@root_spec = fixture_spec('matryoshka/matryoshka.podspec')
@default_subspec = @root_spec.subspec_by_name('matryoshka/Outer')
@inner_subspec = @root_spec.subspec_by_name('matryoshka/Outer/Inner')
@foo_subspec = @root_spec.subspec_by_name('matryoshka/Foo')
@bar_subspec = @root_spec.subspec_by_name('matryoshka/Bar')
end
PodVariant = Pod::Installer::Analyzer::PodVariant.freeze
it 'returns an empty scope if there is only one variant' do
variants = PodVariantSet.new([PodVariant.new([@root_spec], Platform.ios)])
variants.scope_suffixes.values.should == [nil]
end
it 'returns scopes by built types if they qualify' do
variants = PodVariantSet.new([
PodVariant.new([@root_spec], Platform.ios, true),
PodVariant.new([@root_spec], Platform.ios, false),
])
variants.scope_suffixes.values.should == %w(framework library)
end
it 'returns scopes by platform names if they qualify' do
variants = PodVariantSet.new([
PodVariant.new([@root_spec], Platform.ios),
PodVariant.new([@root_spec], Platform.osx),
])
variants.scope_suffixes.values.should == %w(iOS OSX)
end
it 'returns scopes by versioned platform names if they qualify' do
variants = PodVariantSet.new([
PodVariant.new([@root_spec], Platform.ios),
PodVariant.new([@root_spec], Platform.new(:ios, '7.0')),
])
variants.scope_suffixes.values.should == %w(iOS iOS7.0)
end
it 'returns scopes by subspec names if they qualify' do
variants = PodVariantSet.new([
PodVariant.new([@foo_subspec], Platform.ios),
PodVariant.new([@bar_subspec], Platform.ios),
])
variants.scope_suffixes.values.should == %w(Foo Bar)
end
it 'returns scopes by subspec names if they qualify and handle partial root spec presence well' do
variants = PodVariantSet.new([
PodVariant.new([@foo_subspec], Platform.ios),
PodVariant.new([@root_spec, @bar_subspec], Platform.ios),
])
variants.scope_suffixes.values.should == %w(Foo .root-Bar)
end
it 'allows to differentiate between an exclusive variant with a specific subspec and ' \
'an inclusive variant with the default subspecs plus a non-default subspec' do
variants = PodVariantSet.new([
PodVariant.new([@foo_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec, @foo_subspec], Platform.ios),
])
variants.scope_suffixes.values.should == %w(Foo .default-Foo)
end
it 'omits default specs' do
variants = PodVariantSet.new([
PodVariant.new([@root_spec, @default_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec, @foo_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec, @bar_subspec], Platform.ios),
])
variants.scope_suffixes.values.should == [nil, '.default-Foo', '.default-Bar']
end
it 'omits common specs' do
variants = PodVariantSet.new([
PodVariant.new([@root_spec, @default_subspec, @inner_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec, @inner_subspec, @foo_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec, @inner_subspec, @bar_subspec], Platform.ios),
])
variants.scope_suffixes.values.should == %w(.common .common-Foo .common-Bar)
end
it 'returns scopes by platform names and subspec names if they qualify' do
variants = PodVariantSet.new([
PodVariant.new([@root_spec, @default_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec], Platform.osx),
PodVariant.new([@root_spec, @default_subspec, @foo_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec, @bar_subspec], Platform.osx),
])
variants.scope_suffixes.values.should == %w(
iOS
OSX
.default-Foo
.default-Bar
)
end
it 'returns scopes by versioned platform names and subspec names if they qualify' do
variants = PodVariantSet.new([
PodVariant.new([@root_spec, @default_subspec], Platform.new(:ios, '7.0')),
PodVariant.new([@root_spec, @default_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec, @foo_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec], Platform.osx),
PodVariant.new([@root_spec, @default_subspec, @foo_subspec], Platform.osx),
PodVariant.new([@root_spec, @default_subspec, @bar_subspec], Platform.osx),
])
variants.scope_suffixes.values.should == %w(
iOS7.0
iOS
OSX
.default-Foo-iOS
.default-Foo-OSX
.default-Bar
)
end
it 'returns scopes by built types, versioned platform names and subspec names' do
variants = PodVariantSet.new([
PodVariant.new([@root_spec, @default_subspec], Platform.new(:ios, '7.0')),
PodVariant.new([@root_spec, @default_subspec], Platform.ios),
PodVariant.new([@root_spec, @default_subspec], Platform.osx, true),
PodVariant.new([@root_spec, @default_subspec, @foo_subspec], Platform.osx, true),
])
variants.scope_suffixes.values.should == %w(
library-iOS7.0
library-iOS
framework
.default-Foo
)
end
end
end
end
require File.expand_path('../../../../spec_helper', __FILE__)
module Pod
describe PodVariant = Installer::Analyzer::PodVariant do
before do
@specs = [stub('Spec'), stub('Spec/Foo')]
@platform = Platform.ios
end
it 'can be initialized with specs and platform' do
variant = PodVariant.new(@specs, @platform)
variant.specs.should == @specs
variant.platform.should == @platform
variant.requires_frameworks.should == false
end
it 'can be initialized with specs, platform and whether it requires frameworks' do
variant = PodVariant.new(@specs, @platform, true)
variant.specs.should == @specs
variant.platform.should == @platform
variant.requires_frameworks.should == true
end
it 'can return the root spec' do
spec = fixture_spec('banana-lib/BananaLib.podspec')
variant = PodVariant.new([spec], Platform.ios)
variant.root_spec.should == spec
end
it 'can be compared for equality with another variant with the same specs, platform and value for whether it requires frameworks' do
spec = PodVariant.new(@specs, @platform, false)
spec.should == PodVariant.new(@specs, @platform, false)
spec.should.not == PodVariant.new([@specs.first], @platform, false)
spec.should.not == PodVariant.new(@specs, Platform.osx, false)
spec.should.not == PodVariant.new(@specs, @platform, true)
end
it 'can be used as hash keys' do
k0 = PodVariant.new(@specs, @platform, false)
v0 = stub('Value at index 0')
k1 = PodVariant.new(@specs, @platform, true)
v1 = stub('Value at index 1')
hash = { k0 => v0, k1 => v1 }
hash[k0].should == v0
hash[k1].should == v1
end
end
end
...@@ -4,6 +4,11 @@ module Pod ...@@ -4,6 +4,11 @@ module Pod
describe Installer::Analyzer do describe Installer::Analyzer do
describe 'Analysis' do describe 'Analysis' do
before do before do
repos = [fixture('spec-repos/test_repo'), fixture('spec-repos/master')]
aggregate = Pod::Source::Aggregate.new(repos)
Pod::SourcesManager.stubs(:aggregate).returns(aggregate)
aggregate.sources.first.stubs(:url).returns(SpecHelper.test_repo_url)
@podfile = Pod::Podfile.new do @podfile = Pod::Podfile.new do
platform :ios, '6.0' platform :ios, '6.0'
project 'SampleProject/SampleProject' project 'SampleProject/SampleProject'
...@@ -131,13 +136,19 @@ module Pod ...@@ -131,13 +136,19 @@ module Pod
#--------------------------------------# #--------------------------------------#
it 'generates the model to represent the target definitions' do it 'generates the model to represent the target definitions' do
target = @analyzer.analyze.targets.first result = @analyzer.analyze
target.pod_targets.map(&:name).sort.should == [ target, test_target = result.targets
'JSONKit',
'AFNetworking', test_target.pod_targets.map(&:name).sort.should == %w(
'SVPullToRefresh', libextobjc-EXTKeyPathCoding-EXTSynthesize
'Pods-SampleProject-libextobjc', ).sort
].sort
target.pod_targets.map(&:name).sort.should == %w(
JSONKit
AFNetworking
libextobjc-EXTKeyPathCoding
SVPullToRefresh
).sort
target.support_files_dir.should == config.sandbox.target_support_files_dir('Pods-SampleProject') target.support_files_dir.should == config.sandbox.target_support_files_dir('Pods-SampleProject')
target.pod_targets.map(&:archs).uniq.should == [[]] target.pod_targets.map(&:archs).uniq.should == [[]]
...@@ -156,42 +167,69 @@ module Pod ...@@ -156,42 +167,69 @@ module Pod
target.platform.to_s.should == 'iOS 6.0' target.platform.to_s.should == 'iOS 6.0'
end end
it 'generates the set of dependent pod targets' do describe 'dependent pod targets' do
@podfile = Pod::Podfile.new do it 'picks transitive dependencies up' do
platform :ios, '8.0' @podfile = Pod::Podfile.new do
project 'SampleProject/SampleProject' platform :ios, '8.0'
pod 'RestKit', '~> 0.23.0' project 'SampleProject/SampleProject'
target 'TestRunner' do pod 'RestKit', '~> 0.23.0'
pod 'RestKit/Testing', '~> 0.23.0' target 'TestRunner' do
pod 'RestKit/Testing', '~> 0.23.0'
end
end end
@analyzer = Pod::Installer::Analyzer.new(config.sandbox, @podfile, nil)
result = @analyzer.analyze
result.targets.count.should == 1
target = result.targets.first
restkit_target = target.pod_targets.find { |pt| pt.pod_name == 'RestKit' }
restkit_target.dependent_targets.map(&:pod_name).sort.should == %w(
AFNetworking
ISO8601DateFormatterValueTransformer
RKValueTransformers
SOCKit
TransitionKit
)
restkit_target.dependent_targets.all?(&:scoped).should.be.true
end end
@analyzer = Pod::Installer::Analyzer.new(config.sandbox, @podfile, nil)
target = @analyzer.analyze.targets.first
restkit_target = target.pod_targets.find { |pt| pt.pod_name == 'RestKit' }
restkit_target.should.be.scoped
restkit_target.dependent_targets.map(&:pod_name).sort.should == %w(
AFNetworking
ISO8601DateFormatterValueTransformer
RKValueTransformers
SOCKit
TransitionKit
)
restkit_target.dependent_targets.all?(&:scoped).should.be.true
end
describe 'deduplication' do it 'picks the right variants up when there are multiple' do
before do @podfile = Pod::Podfile.new do
repos = [fixture('spec-repos/test_repo'), fixture('spec-repos/master')] source SpecHelper.test_repo_url
aggregate = Pod::Source::Aggregate.new(repos) platform :ios, '8.0'
Pod::SourcesManager.stubs(:aggregate).returns(aggregate) project 'SampleProject/SampleProject'
aggregate.sources.first.stubs(:url).returns(SpecHelper.test_repo_url)
# The order of target definitions is important for this test.
target 'TestRunner' do
pod 'OrangeFramework'
pod 'matryoshka/Foo'
end
target 'SampleProject' do
pod 'OrangeFramework'
end
end
@analyzer = Pod::Installer::Analyzer.new(config.sandbox, @podfile, nil)
result = @analyzer.analyze
result.targets.count.should == 2
pod_target = result.targets[0].pod_targets.find { |pt| pt.pod_name == 'OrangeFramework' }
pod_target.dependent_targets.count == 1
pod_target.dependent_targets.first.specs.map(&:name).should == %w(
matryoshka
matryoshka/Outer
matryoshka/Outer/Inner
)
end end
end
describe 'deduplication' do
it 'deduplicate targets if possible' do it 'deduplicate targets if possible' do
podfile = Pod::Podfile.new do podfile = Pod::Podfile.new do
source SpecHelper.test_repo_url source SpecHelper.test_repo_url
platform :ios, '6.0' platform :ios, '6.0'
project 'SampleProject/SampleProject' project 'SampleProject/SampleProject'
target 'SampleProject' do target 'SampleProject' do
pod 'BananaLib' pod 'BananaLib'
pod 'monkey' pod 'monkey'
...@@ -201,48 +239,48 @@ module Pod ...@@ -201,48 +239,48 @@ module Pod
pod 'monkey' pod 'monkey'
end end
end end
target 'CLITool' do
platform :osx, '10.10'
pod 'monkey'
end
end end
analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile) analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile)
analyzer.analyze result = analyzer.analyze
analyzer.analyze.targets.flat_map { |at| at.pod_targets.map { |pt| "#{at.name}/#{pt.name}" } }.sort.should == %w( pod_targets = result.targets.flat_map(&:pod_targets).uniq
Pods-SampleProject-TestRunner/BananaLib Hash[pod_targets.map { |t| [t.label, t.target_definitions.map(&:label).sort] }.sort].should == {
Pods-SampleProject-TestRunner/monkey 'BananaLib' => %w(Pods-SampleProject Pods-SampleProject-TestRunner),
Pods-SampleProject/BananaLib 'monkey-iOS' => %w(Pods-SampleProject Pods-SampleProject-TestRunner),
Pods-SampleProject/monkey 'monkey-OSX' => %w(Pods-CLITool),
).sort }
end end
it "doesn't deduplicate targets, where transitive dependencies can't be deduplicated" do it "doesn't deduplicate targets across different integration modes" do
podfile = Pod::Podfile.new do podfile = Pod::Podfile.new do
source SpecHelper.test_repo_url source SpecHelper.test_repo_url
platform :ios, '6.0' platform :ios, '6.0'
project 'SampleProject/SampleProject' xcodeproj 'SampleProject/SampleProject'
pod 'BananaLib'
pod 'monkey'
target 'SampleProject' do target 'SampleProject' do
use_frameworks!
pod 'BananaLib'
target 'TestRunner' do target 'TestRunner' do
use_frameworks!(false)
pod 'BananaLib' pod 'BananaLib'
pod 'monkey'
end end
end end
target 'CLITool' do
platform :osx, '10.10'
pod 'monkey'
end
end end
analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile) analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile)
analyzer.analyze result = analyzer.analyze
analyzer.analyze.targets.flat_map { |at| at.pod_targets.map { |pt| "#{at.name}/#{pt.name}" } }.sort.should == %w( pod_targets = result.targets.flat_map(&:pod_targets).uniq.sort_by(&:name)
Pods-CLITool/Pods-CLITool-monkey Hash[pod_targets.map { |t| [t.label, t.target_definitions.map(&:label)] }].should == {
Pods-SampleProject-TestRunner/Pods-SampleProject-TestRunner-BananaLib 'BananaLib-library' => %w(Pods-SampleProject-TestRunner),
Pods-SampleProject-TestRunner/Pods-SampleProject-TestRunner-monkey 'BananaLib-framework' => %w(Pods-SampleProject),
Pods-SampleProject/Pods-SampleProject-BananaLib 'monkey-library' => %w(Pods-SampleProject-TestRunner),
Pods-SampleProject/Pods-SampleProject-monkey 'monkey-framework' => %w(Pods-SampleProject),
).sort }
end end
it "doesn't deduplicate targets when deduplication is disabled" do it "doesn't deduplicate targets when deduplication is disabled" do
...@@ -262,13 +300,13 @@ module Pod ...@@ -262,13 +300,13 @@ module Pod
end end
end end
analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile) analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile)
analyzer.analyze result = analyzer.analyze
analyzer.analyze.targets.flat_map { |at| at.pod_targets.map { |pt| "#{at.name}/#{pt.name}" } }.sort.should == %w( result.targets.flat_map { |at| at.pod_targets.map { |pt| "#{at.name}/#{pt.name}" } }.sort.should == %w(
Pods-SampleProject-TestRunner/Pods-SampleProject-TestRunner-BananaLib Pods-SampleProject-TestRunner/BananaLib-Pods-SampleProject-TestRunner
Pods-SampleProject-TestRunner/Pods-SampleProject-TestRunner-monkey Pods-SampleProject-TestRunner/monkey-Pods-SampleProject-TestRunner
Pods-SampleProject/Pods-SampleProject-BananaLib Pods-SampleProject/BananaLib-Pods-SampleProject
Pods-SampleProject/Pods-SampleProject-monkey Pods-SampleProject/monkey-Pods-SampleProject
).sort ).sort
end end
end end
......
...@@ -177,9 +177,9 @@ module Pod ...@@ -177,9 +177,9 @@ 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([stub('Spec')], [stub('TargetDefinition')], config.sandbox) pod_target_1 = PodTarget.new([stub('Spec')], [fixture_target_definition], 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([stub('Spec')], [stub('TargetDefinition')], config.sandbox) pod_target_2 = PodTarget.new([stub('Spec')], [fixture_target_definition], 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 }
...@@ -187,7 +187,7 @@ module Pod ...@@ -187,7 +187,7 @@ module Pod
end end
it 'handles pods without file accessors' do it 'handles pods without file accessors' do
pod_target_1 = PodTarget.new([stub('Spec')], [stub('TargetDefinition')], config.sandbox) pod_target_1 = PodTarget.new([stub('Spec')], [fixture_target_definition], 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 == []
......
...@@ -6,10 +6,11 @@ module Pod ...@@ -6,10 +6,11 @@ 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'
project 'dummy' project 'SampleProject/SampleProject'
target 'SampleProject'
end end
@target_definition = @podfile.target_definitions['Pods'] @target_definition = @podfile.target_definitions['SampleProject']
@project = Project.new(config.sandbox.project_path) @project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project config.sandbox.project = @project
...@@ -23,12 +24,10 @@ module Pod ...@@ -23,12 +24,10 @@ module Pod
end end
@target = AggregateTarget.new(@target_definition, config.sandbox) @target = AggregateTarget.new(@target_definition, config.sandbox)
@target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@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.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]
...@@ -41,17 +40,17 @@ module Pod ...@@ -41,17 +40,17 @@ module Pod
it 'adds file references for the support files of the target' do it 'adds file references for the support files of the target' do
@installer.install! @installer.install!
group = @project.support_files_group['Pods'] group = @project.support_files_group['Pods-SampleProject']
group.children.map(&:display_name).sort.should == [ group.children.map(&:display_name).sort.should == [
'Pods-acknowledgements.markdown', 'Pods-SampleProject-acknowledgements.markdown',
'Pods-acknowledgements.plist', 'Pods-SampleProject-acknowledgements.plist',
'Pods-dummy.m', 'Pods-SampleProject-dummy.m',
'Pods-frameworks.sh', 'Pods-SampleProject-frameworks.sh',
'Pods-resources.sh', 'Pods-SampleProject-resources.sh',
'Pods.appstore.xcconfig', 'Pods-SampleProject.appstore.xcconfig',
'Pods.debug.xcconfig', 'Pods-SampleProject.debug.xcconfig',
'Pods.release.xcconfig', 'Pods-SampleProject.release.xcconfig',
'Pods.test.xcconfig', 'Pods-SampleProject.test.xcconfig',
] ]
end end
...@@ -138,16 +137,16 @@ module Pod ...@@ -138,16 +137,16 @@ module Pod
it 'creates a create copy resources script' do it 'creates a create copy resources script' do
@installer.install! @installer.install!
support_files_dir = config.sandbox.target_support_files_dir('Pods') support_files_dir = config.sandbox.target_support_files_dir('Pods-SampleProject')
script = support_files_dir + 'Pods-resources.sh' script = support_files_dir + 'Pods-SampleProject-resources.sh'
script.read.should.include?('logo-sidebar.png') script.read.should.include?('logo-sidebar.png')
end end
it 'does not add framework resources to copy resources script' do it 'does not add framework resources to copy resources script' do
@pod_target.stubs(:requires_frameworks? => true) @pod_target.stubs(:requires_frameworks? => true)
@installer.install! @installer.install!
support_files_dir = config.sandbox.target_support_files_dir('Pods') support_files_dir = config.sandbox.target_support_files_dir('Pods-SampleProject')
script = support_files_dir + 'Pods-resources.sh' script = support_files_dir + 'Pods-SampleProject-resources.sh'
script.read.should.not.include?('logo-sidebar.png') script.read.should.not.include?('logo-sidebar.png')
end end
...@@ -161,8 +160,8 @@ module Pod ...@@ -161,8 +160,8 @@ module Pod
@pod_target.stubs(:requires_frameworks? => true) @pod_target.stubs(:requires_frameworks? => true)
@target.stubs(:requires_frameworks? => true) @target.stubs(:requires_frameworks? => true)
@installer.install! @installer.install!
support_files_dir = config.sandbox.target_support_files_dir('Pods') support_files_dir = config.sandbox.target_support_files_dir('Pods-SampleProject')
script = support_files_dir + 'Pods-frameworks.sh' script = support_files_dir + 'Pods-SampleProject-frameworks.sh'
script.read.should.include?('BananaLib.framework') script.read.should.include?('BananaLib.framework')
end end
...@@ -186,28 +185,28 @@ module Pod ...@@ -186,28 +185,28 @@ module Pod
@pod_target.stubs(:requires_frameworks? => true) @pod_target.stubs(:requires_frameworks? => true)
@target.stubs(:requires_frameworks? => true) @target.stubs(:requires_frameworks? => true)
@installer.install! @installer.install!
support_files_dir = config.sandbox.target_support_files_dir('Pods') support_files_dir = config.sandbox.target_support_files_dir('Pods-SampleProject')
script = support_files_dir + 'Pods-frameworks.sh' script = support_files_dir + 'Pods-SampleProject-frameworks.sh'
script.read.should.not.include?('BananaLib.framework') script.read.should.not.include?('BananaLib.framework')
end end
it 'creates the acknowledgements files ' do it 'creates the acknowledgements files ' do
@installer.install! @installer.install!
support_files_dir = config.sandbox.target_support_files_dir('Pods') support_files_dir = config.sandbox.target_support_files_dir('Pods-SampleProject')
markdown = support_files_dir + 'Pods-acknowledgements.markdown' markdown = support_files_dir + 'Pods-SampleProject-acknowledgements.markdown'
markdown.read.should.include?('Permission is hereby granted') markdown.read.should.include?('Permission is hereby granted')
plist = support_files_dir + 'Pods-acknowledgements.plist' plist = support_files_dir + 'Pods-SampleProject-acknowledgements.plist'
plist.read.should.include?('Permission is hereby granted') plist.read.should.include?('Permission is hereby granted')
end end
it 'creates a dummy source to ensure the creation of a single base library' do it 'creates a dummy source to ensure the creation of a single base library' do
@installer.install! @installer.install!
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.path.include?('Pods-dummy.m') } build_file = build_files.find { |bf| bf.file_ref.path.include?('Pods-SampleProject-dummy.m') }
build_file.should.be.not.nil build_file.should.be.not.nil
build_file.file_ref.path.should == 'Pods-dummy.m' build_file.file_ref.path.should == 'Pods-SampleProject-dummy.m'
support_files_dir = config.sandbox.target_support_files_dir('Pods') support_files_dir = config.sandbox.target_support_files_dir('Pods-SampleProject')
dummy = support_files_dir + 'Pods-dummy.m' dummy = support_files_dir + 'Pods-SampleProject-dummy.m'
dummy.read.should.include?('@interface PodsDummy_Pods') dummy.read.should.include?('@interface PodsDummy_Pods')
end end
end end
......
...@@ -7,9 +7,10 @@ module Pod ...@@ -7,9 +7,10 @@ module Pod
config.sandbox.prepare config.sandbox.prepare
@podfile = Podfile.new do @podfile = Podfile.new do
platform :ios, '6.0' platform :ios, '6.0'
project 'dummy' project 'SampleProject/SampleProject'
target 'SampleProject'
end end
@target_definition = @podfile.target_definitions['Pods'] @target_definition = @podfile.target_definitions['SampleProject']
@project = Project.new(config.sandbox.project_path) @project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project config.sandbox.project = @project
...@@ -141,47 +142,44 @@ module Pod ...@@ -141,47 +142,44 @@ module Pod
@installer.install! @installer.install!
group = @project['Pods/BananaLib/Support Files'] group = @project['Pods/BananaLib/Support Files']
group.children.map(&:display_name).sort.should == [ group.children.map(&:display_name).sort.should == [
'Pods-BananaLib-dummy.m', 'BananaLib-Pods-SampleProject-dummy.m',
'Pods-BananaLib-prefix.pch', 'BananaLib-Pods-SampleProject-prefix.pch',
'Pods-BananaLib.xcconfig', 'BananaLib-Pods-SampleProject.xcconfig',
] ]
end end
it 'adds the target for the static library to the project' do it 'adds the target for the static library to the project' do
@installer.install! @installer.install!
@project.targets.count.should == 1 @project.targets.count.should == 1
@project.targets.first.name.should == 'Pods-BananaLib' @project.targets.first.name.should == 'BananaLib-Pods-SampleProject'
end end
it 'adds the resource bundle targets' do describe 'resource bundle targets' do
@pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => []) before do
@installer.install! @pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => [])
bundle_target = @project.targets.find { |t| t.name == 'Pods-BananaLib-banana_bundle' } @installer.install!
bundle_target.should.be.an.instance_of Xcodeproj::Project::Object::PBXNativeTarget @bundle_target = @project.targets.find { |t| t.name == 'BananaLib-Pods-SampleProject-banana_bundle' }
bundle_target.product_reference.name.should == 'banana_bundle.bundle' end
bundle_target.product_reference.path.should == 'banana_bundle.bundle'
bundle_target.platform_name.should == :ios
bundle_target.deployment_target.should == '4.3'
end
it 'adds the build configurations to the resources bundle targets' do
@pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => [])
@installer.install!
bundle_target = @project.targets.find { |t| t.name == 'Pods-BananaLib-banana_bundle' }
file = config.sandbox.root + @pod_target.xcconfig_path it 'adds the resource bundle targets' do
bundle_target.build_configurations.each do |bc| @bundle_target.should.be.an.instance_of Xcodeproj::Project::Object::PBXNativeTarget
bc.base_configuration_reference.real_path.should == file @bundle_target.product_reference.name.should == 'banana_bundle.bundle'
@bundle_target.product_reference.path.should == 'banana_bundle.bundle'
@bundle_target.platform_name.should == :ios
@bundle_target.deployment_target.should == '4.3'
end end
end
it 'sets the correct targeted device family for the resource 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' => []) file = config.sandbox.root + @pod_target.xcconfig_path
@installer.install! @bundle_target.build_configurations.each do |bc|
bundle_target = @project.targets.find { |t| t.name == 'Pods-BananaLib-banana_bundle' } bc.base_configuration_reference.real_path.should == file
end
end
bundle_target.build_configurations.each do |bc| it 'sets the correct targeted device family for the resource bundle targets' do
bc.build_settings['TARGETED_DEVICE_FAMILY'].should == '1,2' @bundle_target.build_configurations.each do |bc|
bc.build_settings['TARGETED_DEVICE_FAMILY'].should == '1,2'
end
end end
end end
end end
...@@ -206,23 +204,24 @@ module Pod ...@@ -206,23 +204,24 @@ module Pod
@project.targets.first.name.should == 'BananaLib' @project.targets.first.name.should == 'BananaLib'
end end
it 'adds the resource bundle targets' do describe 'resource bundle targets' do
@pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => []) before do
@installer.install! @pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => [])
bundle_target = @project.targets.find { |t| t.name == 'BananaLib-banana_bundle' } @installer.install!
bundle_target.should.be.an.instance_of Xcodeproj::Project::Object::PBXNativeTarget @bundle_target = @project.targets.find { |t| t.name == 'BananaLib-banana_bundle' }
bundle_target.product_reference.name.should == 'banana_bundle.bundle' end
bundle_target.product_reference.path.should == 'banana_bundle.bundle'
end
it 'adds the build configurations to the resources bundle targets' do it 'adds the resource bundle targets' do
@pod_target.file_accessors.first.stubs(:resource_bundles).returns('banana_bundle' => []) @bundle_target.should.be.an.instance_of Xcodeproj::Project::Object::PBXNativeTarget
@installer.install! @bundle_target.product_reference.name.should == 'banana_bundle.bundle'
bundle_target = @project.targets.find { |t| t.name == 'BananaLib-banana_bundle' } @bundle_target.product_reference.path.should == 'banana_bundle.bundle'
end
file = config.sandbox.root + @pod_target.xcconfig_path it 'adds the build configurations to the resources bundle targets' do
bundle_target.build_configurations.each do |bc| file = config.sandbox.root + @pod_target.xcconfig_path
bc.base_configuration_reference.real_path.should == file @bundle_target.build_configurations.each do |bc|
bc.base_configuration_reference.real_path.should == file
end
end end
end end
end end
...@@ -275,7 +274,7 @@ module Pod ...@@ -275,7 +274,7 @@ module Pod
before do before do
@project.add_pod_group('snake', fixture('snake')) @project.add_pod_group('snake', fixture('snake'))
@pod_target = fixture_pod_target('snake/snake.podspec', @target_definition) @pod_target = fixture_pod_target('snake/snake.podspec', [@target_definition])
@pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release } @pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release }
@pod_target.stubs(:requires_frameworks? => true) @pod_target.stubs(:requires_frameworks? => true)
group = @project.group_for_spec('snake') group = @project.group_for_spec('snake')
......
...@@ -5,9 +5,10 @@ module Pod ...@@ -5,9 +5,10 @@ module Pod
before do before do
@podfile = Podfile.new do @podfile = Podfile.new do
platform :ios platform :ios
project 'dummy' project 'SampleProject/SampleProject'
target 'SampleProject'
end end
@target_definition = @podfile.target_definitions['Pods'] @target_definition = @podfile.target_definitions['SampleProject']
@project = Project.new(config.sandbox.project_path) @project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project config.sandbox.project = @project
......
...@@ -205,12 +205,6 @@ module Pod ...@@ -205,12 +205,6 @@ module Pod
@integrator.send(:targets_to_integrate).map(&:name).should == ['Pods-SampleProject', 'Pods-SampleProject-empty'] @integrator.send(:targets_to_integrate).map(&:name).should == ['Pods-SampleProject', 'Pods-SampleProject-empty']
end end
it 'does skip libraries with only abstract target definitions' do
@integrator.targets.map(&:name).should == ['Pods-SampleProject', 'Pods-SampleProject-empty']
@podfile.target_definition_list.each { |td| td.abstract = true }
@integrator.send(:targets_to_integrate).map(&:name).should == []
end
it 'skips saving projects that are not dirtied (but touches them instead)' do it 'skips saving projects that are not dirtied (but touches them instead)' do
project = mock('Project') project = mock('Project')
project.stubs(:path).returns(Pathname('project.xcodeproj')) project.stubs(:path).returns(Pathname('project.xcodeproj'))
......
...@@ -61,7 +61,6 @@ module Pod ...@@ -61,7 +61,6 @@ module Pod
before do before do
@installer.stubs(:resolve_dependencies) @installer.stubs(:resolve_dependencies)
@installer.stubs(:download_dependencies) @installer.stubs(:download_dependencies)
@installer.stubs(:determine_dependency_product_types)
@installer.stubs(:verify_no_duplicate_framework_names) @installer.stubs(:verify_no_duplicate_framework_names)
@installer.stubs(:verify_no_static_framework_transitive_dependencies) @installer.stubs(:verify_no_static_framework_transitive_dependencies)
@installer.stubs(:verify_framework_usage) @installer.stubs(:verify_framework_usage)
...@@ -232,6 +231,7 @@ module Pod ...@@ -232,6 +231,7 @@ module Pod
use_frameworks! use_frameworks!
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 'matryoshka', :path => (fixture_path + 'matryoshka').to_s
pod 'monkey', :path => (fixture_path + 'monkey').to_s pod 'monkey', :path => (fixture_path + 'monkey').to_s
target 'SampleProject' target 'SampleProject'
...@@ -251,6 +251,7 @@ module Pod ...@@ -251,6 +251,7 @@ module Pod
target.pod_targets.select(&:requires_frameworks?).map(&:name).sort.should == %w( target.pod_targets.select(&:requires_frameworks?).map(&:name).sort.should == %w(
BananaLib BananaLib
OrangeFramework OrangeFramework
matryoshka
monkey monkey
) )
end end
...@@ -271,6 +272,7 @@ module Pod ...@@ -271,6 +272,7 @@ module Pod
project 'SampleProject/SampleProject' project 'SampleProject/SampleProject'
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 'matryoshka', :path => (fixture_path + 'matryoshka').to_s
pod 'monkey', :path => (fixture_path + 'monkey').to_s pod 'monkey', :path => (fixture_path + 'monkey').to_s
target 'SampleProject' target 'SampleProject'
end end
...@@ -315,6 +317,7 @@ module Pod ...@@ -315,6 +317,7 @@ module Pod
use_frameworks! use_frameworks!
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 'matryoshka', :path => (fixture_path + 'matryoshka').to_s
pod 'monkey', :path => (fixture_path + 'monkey').to_s pod 'monkey', :path => (fixture_path + 'monkey').to_s
target 'SampleProject' target 'SampleProject'
end end
...@@ -358,6 +361,7 @@ module Pod ...@@ -358,6 +361,7 @@ module Pod
platform :ios, '8.0' platform :ios, '8.0'
project 'SampleProject/SampleProject' project 'SampleProject/SampleProject'
pod 'OrangeFramework', :path => (fixture_path + 'orange-framework').to_s pod 'OrangeFramework', :path => (fixture_path + 'orange-framework').to_s
pod 'matryoshka', :path => (fixture_path + 'matryoshka').to_s
target 'SampleProject' target 'SampleProject'
end end
lockfile = generate_lockfile lockfile = generate_lockfile
...@@ -443,7 +447,7 @@ module Pod ...@@ -443,7 +447,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([stub('Spec')], [stub('TargetDefinition')], config.sandbox)] @pod_targets = [PodTarget.new([stub('Spec')], [fixture_target_definition], 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
...@@ -484,7 +488,7 @@ module Pod ...@@ -484,7 +488,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], [stub('TargetDefinition')], config.sandbox) pod_target = PodTarget.new([spec], [fixture_target_definition], 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, [])
...@@ -494,7 +498,7 @@ module Pod ...@@ -494,7 +498,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], [stub('TargetDefinition')], config.sandbox) pod_target = PodTarget.new([spec], [fixture_target_definition], 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, [])
...@@ -583,15 +587,11 @@ module Pod ...@@ -583,15 +587,11 @@ 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([stub('Spec')], [stub('TargetDefinition')], config.sandbox) target_definition_osx = fixture_target_definition('OSX Target', Platform.new(:osx, '10.8'))
pod_target_osx = PodTarget.new([stub('Spec')], [stub('TargetDefinition')], config.sandbox) target_definition_ios = fixture_target_definition('iOS Target', Platform.new(:ios, '6.0'))
pod_target_ios.stubs(:platform).returns(Platform.new(:ios, '6.0')) aggregate_target_osx = AggregateTarget.new(target_definition_osx, config.sandbox)
pod_target_osx.stubs(:platform).returns(Platform.new(:osx, '10.8')) aggregate_target_ios = AggregateTarget.new(target_definition_ios, config.sandbox)
aggregate_target_ios = AggregateTarget.new(nil, config.sandbox) @installer.stubs(:aggregate_targets).returns([aggregate_target_osx, aggregate_target_ios])
aggregate_target_osx = AggregateTarget.new(nil, config.sandbox)
aggregate_target_ios.stubs(:platform).returns(Platform.new(:ios, '6.0'))
aggregate_target_osx.stubs(:platform).returns(Platform.new(:osx, '10.8'))
@installer.stubs(:aggregate_targets).returns([aggregate_target_ios, aggregate_target_osx])
@installer.stubs(:pod_targets).returns([]) @installer.stubs(:pod_targets).returns([])
@installer.send(:prepare_pods_project) @installer.send(:prepare_pods_project)
build_settings = @installer.pods_project.build_configurations.map(&:build_settings) build_settings = @installer.pods_project.build_configurations.map(&:build_settings)
...@@ -779,9 +779,8 @@ module Pod ...@@ -779,9 +779,8 @@ module Pod
proj = Xcodeproj::Project.new(tmp_directory + 'Yolo.xcodeproj', false, 1) proj = Xcodeproj::Project.new(tmp_directory + 'Yolo.xcodeproj', false, 1)
proj.save proj.save
aggregate_target = AggregateTarget.new(nil, config.sandbox) aggregate_target = AggregateTarget.new(fixture_target_definition, config.sandbox)
aggregate_target.stubs(:platform).returns(Platform.new(:ios, '6.0')) aggregate_target.user_project = proj
aggregate_target.stubs(:user_project).returns(proj)
@installer.stubs(:aggregate_targets).returns([aggregate_target]) @installer.stubs(:aggregate_targets).returns([aggregate_target])
@installer.send(:prepare_pods_project) @installer.send(:prepare_pods_project)
...@@ -823,7 +822,7 @@ module Pod ...@@ -823,7 +822,7 @@ module Pod
describe 'Integrating client projects' do describe 'Integrating client projects' do
it 'integrates the client projects' do it 'integrates the client projects' do
@installer.stubs(:aggregate_targets).returns([AggregateTarget.new(nil, config.sandbox)]) @installer.stubs(:aggregate_targets).returns([AggregateTarget.new(fixture_target_definition, config.sandbox)])
Installer::UserProjectIntegrator.any_instance.expects(:integrate!) Installer::UserProjectIntegrator.any_instance.expects(:integrate!)
@installer.send(:integrate_user_project) @installer.send(:integrate_user_project)
end end
......
...@@ -80,10 +80,6 @@ module Pod ...@@ -80,10 +80,6 @@ module Pod
it 'returns the path of the xcconfig file relative to the user project' do it 'returns the path of the xcconfig file relative to the user project' do
@target.xcconfig_relative_path('Release').should == 'Pods/Target Support Files/Pods/Pods.release.xcconfig' @target.xcconfig_relative_path('Release').should == 'Pods/Target Support Files/Pods/Pods.release.xcconfig'
end end
it 'returns the path for the CONFIGURATION_BUILD_DIR build setting' do
@target.scoped_configuration_build_dir.should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods'
end
end end
describe 'Pod targets' do describe 'Pod targets' do
...@@ -198,7 +194,7 @@ module Pod ...@@ -198,7 +194,7 @@ module Pod
describe 'With frameworks' do describe 'With frameworks' do
before do before do
@pod_target = fixture_pod_target('orange-framework/OrangeFramework.podspec', fixture_target_definition('iOS Example')) @pod_target = fixture_pod_target('orange-framework/OrangeFramework.podspec', [fixture_target_definition('iOS Example')])
@target = AggregateTarget.new(@pod_target.target_definitions.first, 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]
......
...@@ -30,17 +30,24 @@ module Pod ...@@ -30,17 +30,24 @@ module Pod
it 'returns its name' do it 'returns its name' do
@pod_target.name.should == 'BananaLib' @pod_target.name.should == 'BananaLib'
@pod_target.scoped.first.name.should == 'Pods-BananaLib' @pod_target.scoped.first.name.should == 'BananaLib-Pods'
end end
it 'returns its label' do it 'returns its label' do
@pod_target.label.should == 'BananaLib' @pod_target.label.should == 'BananaLib'
@pod_target.scoped.first.label.should == 'Pods-BananaLib' @pod_target.scoped.first.label.should == 'BananaLib-Pods'
end
it 'returns its label' do
@pod_target.label.should == 'BananaLib'
@pod_target.scoped.first.label.should == 'BananaLib-Pods'
spec_scoped_pod_target = @pod_target.scoped.first.tap { |t| t.stubs(:scope_suffix).returns('.default-GreenBanana') }
spec_scoped_pod_target.label.should == 'BananaLib.default-GreenBanana'
end end
it 'returns the name of its product' do it 'returns the name of its product' do
@pod_target.product_name.should == 'libBananaLib.a' @pod_target.product_name.should == 'libBananaLib.a'
@pod_target.scoped.first.product_name.should == 'libPods-BananaLib.a' @pod_target.scoped.first.product_name.should == 'libBananaLib-Pods.a'
end end
it 'returns the spec consumers for the pod targets' do it 'returns the spec consumers for the pod targets' do
...@@ -57,7 +64,7 @@ module Pod ...@@ -57,7 +64,7 @@ module Pod
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 == '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' @pod_target.scoped.first.resources_bundle_target_label('Fruits').should == 'BananaLib-Pods-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
...@@ -109,7 +116,7 @@ module Pod ...@@ -109,7 +116,7 @@ module Pod
'Pods/Target Support Files/BananaLib/BananaLib.release.xcconfig', 'Pods/Target Support Files/BananaLib/BananaLib.release.xcconfig',
) )
@pod_target.scoped.first.xcconfig_path('Release').to_s.should.include?( @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/BananaLib-Pods/BananaLib-Pods.release.xcconfig',
) )
end end
...@@ -118,7 +125,7 @@ module Pod ...@@ -118,7 +125,7 @@ module Pod
'Pods/Target Support Files/BananaLib/BananaLib.release-1.xcconfig', 'Pods/Target Support Files/BananaLib/BananaLib.release-1.xcconfig',
) )
@pod_target.scoped.first.xcconfig_path("Release#{File::SEPARATOR}1").to_s.should.include?( @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/BananaLib-Pods/BananaLib-Pods.release-1.xcconfig',
) )
end end
...@@ -127,7 +134,7 @@ module Pod ...@@ -127,7 +134,7 @@ module Pod
'Pods/Target Support Files/BananaLib/BananaLib-prefix.pch', 'Pods/Target Support Files/BananaLib/BananaLib-prefix.pch',
) )
@pod_target.scoped.first.prefix_header_path.to_s.should.include?( @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/BananaLib-Pods/BananaLib-Pods-prefix.pch',
) )
end end
...@@ -142,7 +149,7 @@ module Pod ...@@ -142,7 +149,7 @@ module Pod
'Pods/Target Support Files/BananaLib/Info.plist', 'Pods/Target Support Files/BananaLib/Info.plist',
) )
@pod_target.scoped.first.info_plist_path.to_s.should.include?( @pod_target.scoped.first.info_plist_path.to_s.should.include?(
'Pods/Target Support Files/Pods-BananaLib/Info.plist', 'Pods/Target Support Files/BananaLib-Pods/Info.plist',
) )
end end
...@@ -151,7 +158,7 @@ module Pod ...@@ -151,7 +158,7 @@ module Pod
'Pods/Target Support Files/BananaLib/BananaLib-dummy.m', 'Pods/Target Support Files/BananaLib/BananaLib-dummy.m',
) )
@pod_target.scoped.first.dummy_source_path.to_s.should.include?( @pod_target.scoped.first.dummy_source_path.to_s.should.include?(
'Pods/Target Support Files/Pods-BananaLib/Pods-BananaLib-dummy.m', 'Pods/Target Support Files/BananaLib-Pods/BananaLib-Pods-dummy.m',
) )
end end
...@@ -162,8 +169,17 @@ module Pod ...@@ -162,8 +169,17 @@ 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
@pod_target.configuration_build_dir.should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)' @pod_target.configuration_build_dir.should == '$CONFIGURATION_BUILD_DIR/BananaLib'
@pod_target.scoped.first.configuration_build_dir.should == '$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/Pods' @pod_target.scoped.first.configuration_build_dir.should == '$CONFIGURATION_BUILD_DIR/BananaLib-Pods'
@pod_target.configuration_build_dir('$PODS_SHARED_BUILD_DIR').should == '$PODS_SHARED_BUILD_DIR/BananaLib'
@pod_target.scoped.first.configuration_build_dir('$PODS_SHARED_BUILD_DIR').should == '$PODS_SHARED_BUILD_DIR/BananaLib-Pods'
end
it 'returns the path for the CONFIGURATION_BUILD_DIR build setting' do
@pod_target.build_product_path.should == '$CONFIGURATION_BUILD_DIR/BananaLib/libBananaLib.a'
@pod_target.scoped.first.build_product_path.should == '$CONFIGURATION_BUILD_DIR/BananaLib-Pods/libBananaLib-Pods.a'
@pod_target.build_product_path('$BUILT_PRODUCTS_DIR').should == '$BUILT_PRODUCTS_DIR/BananaLib/libBananaLib.a'
@pod_target.scoped.first.build_product_path('$BUILT_PRODUCTS_DIR').should == '$BUILT_PRODUCTS_DIR/BananaLib-Pods/libBananaLib-Pods.a'
end end
end end
...@@ -192,7 +208,7 @@ module Pod ...@@ -192,7 +208,7 @@ module Pod
it 'returns the library name' do it 'returns the library name' do
@pod_target.static_library_name.should == 'libBananaLib.a' @pod_target.static_library_name.should == 'libBananaLib.a'
@pod_target.scoped.first.static_library_name.should == 'libPods-BananaLib.a' @pod_target.scoped.first.static_library_name.should == 'libBananaLib-Pods.a'
end end
it 'returns :framework as product type' do it 'returns :framework as product type' do
...@@ -207,7 +223,7 @@ module Pod ...@@ -207,7 +223,7 @@ 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 == 'libBananaLib.a' @pod_target.product_name.should == 'libBananaLib.a'
@pod_target.scoped.first.product_name.should == 'libPods-BananaLib.a' @pod_target.scoped.first.product_name.should == 'libBananaLib-Pods.a'
end end
it 'returns the framework name' do it 'returns the framework name' do
...@@ -216,7 +232,7 @@ module Pod ...@@ -216,7 +232,7 @@ module Pod
it 'returns the library name' do it 'returns the library name' do
@pod_target.static_library_name.should == 'libBananaLib.a' @pod_target.static_library_name.should == 'libBananaLib.a'
@pod_target.scoped.first.static_library_name.should == 'libPods-BananaLib.a' @pod_target.scoped.first.static_library_name.should == 'libBananaLib-Pods.a'
end end
it 'returns :static_library as product type' do it 'returns :static_library as product type' do
...@@ -253,7 +269,7 @@ module Pod ...@@ -253,7 +269,7 @@ module Pod
it 'returns the library name' do it 'returns the library name' do
@pod_target.static_library_name.should == 'libOrangeFramework.a' @pod_target.static_library_name.should == 'libOrangeFramework.a'
@pod_target.scoped.first.static_library_name.should == 'libPods-OrangeFramework.a' @pod_target.scoped.first.static_library_name.should == 'libOrangeFramework-Pods.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