Unverified Commit 93011ece authored by Samuel Giddins's avatar Samuel Giddins Committed by GitHub

Merge pull request #7449 from CocoaPods/seg-more-perf

More performance improvements
parents 2619458c bb81dffc
...@@ -140,8 +140,7 @@ module Pod ...@@ -140,8 +140,7 @@ module Pod
# #
def self.links_dependency?(aggregate_target, pod_target) def self.links_dependency?(aggregate_target, pod_target)
return true if aggregate_target.nil? || aggregate_target.target_definition.inheritance == 'complete' return true if aggregate_target.nil? || aggregate_target.target_definition.inheritance == 'complete'
targets = aggregate_target.pod_targets - aggregate_target.search_paths_aggregate_targets.flat_map(&:pod_targets) aggregate_target.pod_targets_to_link.include?(pod_target)
targets.include?(pod_target)
end end
# Adds build settings for dynamic vendored frameworks and libraries. # Adds build settings for dynamic vendored frameworks and libraries.
......
...@@ -429,7 +429,7 @@ module Pod ...@@ -429,7 +429,7 @@ module Pod
end end
def print_post_install_message def print_post_install_message
podfile_dependencies = podfile.dependencies.uniq.size podfile_dependencies = analysis_result.podfile_dependency_cache.podfile_dependencies.size
pods_installed = root_specs.size pods_installed = root_specs.size
title_options = { :verbose_prefix => '-> '.green } title_options = { :verbose_prefix => '-> '.green }
UI.titled_section('Pod installation complete! ' \ UI.titled_section('Pod installation complete! ' \
...@@ -548,7 +548,7 @@ module Pod ...@@ -548,7 +548,7 @@ module Pod
# @return [void] # @return [void]
# #
def write_lockfiles def write_lockfiles
external_source_pods = podfile.dependencies.select(&:external_source).map(&:root_name).uniq external_source_pods = analysis_result.podfile_dependency_cache.podfile_dependencies.select(&:external_source).map(&:root_name).uniq
checkout_options = sandbox.checkout_sources.select { |root_name, _| external_source_pods.include? root_name } checkout_options = sandbox.checkout_sources.select { |root_name, _| external_source_pods.include? root_name }
@lockfile = Lockfile.generate(podfile, analysis_result.specifications, checkout_options, analysis_result.specs_by_source) @lockfile = Lockfile.generate(podfile, analysis_result.specifications, checkout_options, analysis_result.specs_by_source)
......
...@@ -10,11 +10,12 @@ module Pod ...@@ -10,11 +10,12 @@ module Pod
delegate_installation_options { podfile } delegate_installation_options { podfile }
autoload :AnalysisResult, 'cocoapods/installer/analyzer/analysis_result' autoload :AnalysisResult, 'cocoapods/installer/analyzer/analysis_result'
autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer'
autoload :SpecsState, 'cocoapods/installer/analyzer/specs_state'
autoload :LockingDependencyAnalyzer, 'cocoapods/installer/analyzer/locking_dependency_analyzer' autoload :LockingDependencyAnalyzer, 'cocoapods/installer/analyzer/locking_dependency_analyzer'
autoload :PodfileDependencyCache, 'cocoapods/installer/analyzer/podfile_dependency_cache'
autoload :PodVariant, 'cocoapods/installer/analyzer/pod_variant' autoload :PodVariant, 'cocoapods/installer/analyzer/pod_variant'
autoload :PodVariantSet, 'cocoapods/installer/analyzer/pod_variant_set' autoload :PodVariantSet, 'cocoapods/installer/analyzer/pod_variant_set'
autoload :SandboxAnalyzer, 'cocoapods/installer/analyzer/sandbox_analyzer'
autoload :SpecsState, 'cocoapods/installer/analyzer/specs_state'
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'
...@@ -54,6 +55,7 @@ module Pod ...@@ -54,6 +55,7 @@ module Pod
@has_dependencies = true @has_dependencies = true
@test_pod_target_analyzer_cache = {} @test_pod_target_analyzer_cache = {}
@test_pod_target_key = Struct.new(:name, :pod_targets) @test_pod_target_key = Struct.new(:name, :pod_targets)
@podfile_dependency_cache = PodfileDependencyCache.from_podfile(podfile)
end end
# Performs the analysis. # Performs the analysis.
...@@ -71,6 +73,7 @@ module Pod ...@@ -71,6 +73,7 @@ module Pod
validate_podfile! validate_podfile!
validate_lockfile_version! validate_lockfile_version!
@result = AnalysisResult.new @result = AnalysisResult.new
@result.podfile_dependency_cache = @podfile_dependency_cache
if installation_options.integrate_targets? if installation_options.integrate_targets?
@result.target_inspections = inspect_targets_to_integrate @result.target_inspections = inspect_targets_to_integrate
else else
...@@ -186,7 +189,7 @@ module Pod ...@@ -186,7 +189,7 @@ module Pod
alias_method :specs_updated?, :specs_updated alias_method :specs_updated?, :specs_updated
def validate_podfile! def validate_podfile!
validator = Installer::PodfileValidator.new(podfile) validator = Installer::PodfileValidator.new(podfile, @podfile_dependency_cache)
validator.validate validator.validate
unless validator.valid? unless validator.valid?
...@@ -234,7 +237,7 @@ module Pod ...@@ -234,7 +237,7 @@ module Pod
pods_state pods_state
else else
state = SpecsState.new state = SpecsState.new
state.added.merge(podfile.dependencies.map(&:root_name)) state.added.merge(@podfile_dependency_cache.podfile_dependencies.map(&:root_name))
state state
end end
end end
...@@ -395,8 +398,7 @@ module Pod ...@@ -395,8 +398,7 @@ module Pod
embedded_targets = aggregate_targets.select(&:requires_host_target?) embedded_targets = aggregate_targets.select(&:requires_host_target?)
analyze_host_targets_in_podfile(aggregate_targets, embedded_targets) analyze_host_targets_in_podfile(aggregate_targets, embedded_targets)
use_frameworks_embedded_targets = embedded_targets.select(&:requires_frameworks?) use_frameworks_embedded_targets, non_use_frameworks_embedded_targets = embedded_targets.partition(&:requires_frameworks?)
non_use_frameworks_embedded_targets = embedded_targets.reject(&:requires_frameworks?)
aggregate_targets.each do |target| aggregate_targets.each do |target|
# For targets that require frameworks, we always have to copy their pods to their # For targets that require frameworks, we always have to copy their pods to their
# host targets because those frameworks will all be loaded from the host target's bundle # host targets because those frameworks will all be loaded from the host target's bundle
...@@ -408,9 +410,9 @@ module Pod ...@@ -408,9 +410,9 @@ module Pod
end end
end end
aggregate_targets.each do |target| aggregate_targets.each do |target|
target.search_paths_aggregate_targets = aggregate_targets.select do |aggregate_target| target.search_paths_aggregate_targets.concat(aggregate_targets.select do |aggregate_target|
target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition) target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition)
end end).freeze
end end
end end
...@@ -634,7 +636,7 @@ module Pod ...@@ -634,7 +636,7 @@ module Pod
else else
pods_to_update = result.podfile_state.changed + result.podfile_state.deleted pods_to_update = result.podfile_state.changed + result.podfile_state.deleted
pods_to_update += update[:pods] if update_mode == :selected pods_to_update += update[:pods] if update_mode == :selected
local_pod_names = podfile.dependencies.select(&:local?).map(&:root_name) local_pod_names = @podfile_dependency_cache.podfile_dependencies.select(&:local?).map(&:root_name)
pods_to_unlock = local_pod_names.reject do |pod_name| pods_to_unlock = local_pod_names.reject do |pod_name|
sandbox.specification(pod_name).checksum == lockfile.checksum(pod_name) sandbox.specification(pod_name).checksum == lockfile.checksum(pod_name)
end end
...@@ -675,7 +677,7 @@ module Pod ...@@ -675,7 +677,7 @@ module Pod
end end
def verify_no_pods_with_different_sources! def verify_no_pods_with_different_sources!
deps_with_different_sources = podfile.dependencies.group_by(&:root_name). deps_with_different_sources = @podfile_dependency_cache.podfile_dependencies.group_by(&:root_name).
select { |_root_name, dependencies| dependencies.map(&:external_source).uniq.count > 1 } select { |_root_name, dependencies| dependencies.map(&:external_source).uniq.count > 1 }
deps_with_different_sources.each do |root_name, dependencies| deps_with_different_sources.each do |root_name, dependencies|
raise Informative, 'There are multiple dependencies with different ' \ raise Informative, 'There are multiple dependencies with different ' \
...@@ -698,7 +700,7 @@ module Pod ...@@ -698,7 +700,7 @@ module Pod
def dependencies_to_fetch def dependencies_to_fetch
@deps_to_fetch ||= begin @deps_to_fetch ||= begin
deps_to_fetch = [] deps_to_fetch = []
deps_with_external_source = podfile.dependencies.select(&:external_source) deps_with_external_source = @podfile_dependency_cache.podfile_dependencies.select(&:external_source)
if update_mode == :all if update_mode == :all
deps_to_fetch = deps_with_external_source deps_to_fetch = deps_with_external_source
...@@ -731,7 +733,7 @@ module Pod ...@@ -731,7 +733,7 @@ module Pod
elsif update_mode == :all elsif update_mode == :all
pods_to_fetch += result.podfile_state.unchanged + result.podfile_state.deleted pods_to_fetch += result.podfile_state.unchanged + result.podfile_state.deleted
end end
pods_to_fetch += podfile.dependencies. pods_to_fetch += @podfile_dependency_cache.podfile_dependencies.
select { |dep| Hash(dep.external_source).key?(:podspec) && sandbox.specification_path(dep.root_name).nil? }. select { |dep| Hash(dep.external_source).key?(:podspec) && sandbox.specification_path(dep.root_name).nil? }.
map(&:root_name) map(&:root_name)
pods_to_fetch pods_to_fetch
...@@ -739,7 +741,7 @@ module Pod ...@@ -739,7 +741,7 @@ module Pod
end end
def store_existing_checkout_options def store_existing_checkout_options
podfile.dependencies.select(&:external_source).each do |dep| @podfile_dependency_cache.podfile_dependencies.select(&:external_source).each do |dep|
if checkout_options = lockfile && lockfile.checkout_options_for_pod_named(dep.root_name) if checkout_options = lockfile && lockfile.checkout_options_for_pod_named(dep.root_name)
sandbox.store_checkout_source(dep.root_name, checkout_options) sandbox.store_checkout_source(dep.root_name, checkout_options)
end end
...@@ -766,7 +768,7 @@ module Pod ...@@ -766,7 +768,7 @@ module Pod
# grouped by target. # grouped by target.
# #
def resolve_dependencies def resolve_dependencies
duplicate_dependencies = podfile.dependencies.group_by(&:name). duplicate_dependencies = @podfile_dependency_cache.podfile_dependencies.group_by(&:name).
select { |_name, dependencies| dependencies.count > 1 } select { |_name, dependencies| dependencies.count > 1 }
duplicate_dependencies.each do |name, dependencies| duplicate_dependencies.each do |name, dependencies|
UI.warn "There are duplicate dependencies on `#{name}` in #{UI.path podfile.defined_in_file}:\n\n" \ UI.warn "There are duplicate dependencies on `#{name}` in #{UI.path podfile.defined_in_file}:\n\n" \
...@@ -857,8 +859,8 @@ module Pod ...@@ -857,8 +859,8 @@ module Pod
plugin_sources = @plugin_sources || [] plugin_sources = @plugin_sources || []
# Add any sources specified using the :source flag on individual dependencies. # Add any sources specified using the :source flag on individual dependencies.
dependency_sources = podfile.dependencies.map(&:podspec_repo).compact dependency_sources = @podfile_dependency_cache.podfile_dependencies.map(&:podspec_repo).compact
all_dependencies_have_sources = dependency_sources.count == podfile.dependencies.count all_dependencies_have_sources = dependency_sources.count == @podfile_dependency_cache.podfile_dependencies.count
if all_dependencies_have_sources if all_dependencies_have_sources
sources = dependency_sources sources = dependency_sources
...@@ -890,7 +892,7 @@ module Pod ...@@ -890,7 +892,7 @@ module Pod
# #
def verify_platforms_specified! def verify_platforms_specified!
unless installation_options.integrate_targets? unless installation_options.integrate_targets?
podfile.target_definition_list.each do |target_definition| @podfile_dependency_cache.target_definition_list.each do |target_definition|
if !target_definition.empty? && target_definition.platform.nil? if !target_definition.empty? && target_definition.platform.nil?
raise Informative, 'It is necessary to specify the platform in the Podfile if not integrating.' raise Informative, 'It is necessary to specify the platform in the Podfile if not integrating.'
end end
...@@ -909,7 +911,7 @@ module Pod ...@@ -909,7 +911,7 @@ module Pod
def inspect_targets_to_integrate def inspect_targets_to_integrate
inspection_result = {} inspection_result = {}
UI.section 'Inspecting targets to integrate' do UI.section 'Inspecting targets to integrate' do
inspectors = podfile.target_definition_list.map do |target_definition| inspectors = @podfile_dependency_cache.target_definition_list.map do |target_definition|
next if target_definition.abstract? next if target_definition.abstract?
TargetInspector.new(target_definition, config.installation_root) TargetInspector.new(target_definition, config.installation_root)
end.compact end.compact
......
...@@ -33,8 +33,14 @@ module Pod ...@@ -33,8 +33,14 @@ module Pod
# @return [Hash{TargetDefinition => Array<TargetInspectionResult>}] the # @return [Hash{TargetDefinition => Array<TargetInspectionResult>}] the
# results of inspecting the user targets # results of inspecting the user targets
#
attr_accessor :target_inspections attr_accessor :target_inspections
# @return [PodfileDependencyCache] the cache of all dependencies in the
# podfile.
#
attr_accessor :podfile_dependency_cache
# @return [Hash{String=>Symbol}] A hash representing all the user build # @return [Hash{String=>Symbol}] A hash representing all the user build
# configurations across all integration targets. Each key # configurations across all integration targets. Each key
# corresponds to the name of a configuration and its value to # corresponds to the name of a configuration and its value to
......
module Pod
class Installer
class Analyzer
# Caches podfile & target definition dependencies, so they do not need to be re-computed
# from the internal hash on each access
#
class PodfileDependencyCache
# @return [Array<Pod::Dependency>]
# All the dependencies in the podfile
#
attr_reader :podfile_dependencies
def initialize(podfile_dependencies, dependencies_by_target_definition)
@podfile_dependencies = podfile_dependencies
@dependencies_by_target_definition = dependencies_by_target_definition
end
# Returns the dependencies for the given target definition
#
def target_definition_dependencies(target_definition)
@dependencies_by_target_definition[target_definition] ||
raise(ArgumentError, "dependencies for #{target_definition.inspect} do not exist in the cache")
end
# Returns a list of all of the target definitions in the Podfile
#
def target_definition_list
@dependencies_by_target_definition.keys
end
# Creates a {PodfileDependencyCache} from the given {Podfile}
#
def self.from_podfile(podfile)
podfile_dependencies = []
dependencies_by_target_definition = {}
podfile.target_definition_list.each do |target_definition|
deps = target_definition.dependencies.freeze
podfile_dependencies.concat deps
dependencies_by_target_definition[target_definition] = deps
end
podfile_dependencies.uniq!
new(podfile_dependencies.freeze, dependencies_by_target_definition.freeze)
end
end
end
end
end
...@@ -20,8 +20,9 @@ module Pod ...@@ -20,8 +20,9 @@ module Pod
# @param [Podfile] podfile # @param [Podfile] podfile
# The podfile to validate # The podfile to validate
# #
def initialize(podfile) def initialize(podfile, podfile_dependency_cache = Analyzer::PodfileDependencyCache.from_podfile(podfile))
@podfile = podfile @podfile = podfile
@podfile_dependency_cache = podfile_dependency_cache
@errors = [] @errors = []
@warnings = [] @warnings = []
@validated = false @validated = false
...@@ -67,11 +68,7 @@ module Pod ...@@ -67,11 +68,7 @@ module Pod
end end
def validate_pod_directives def validate_pod_directives
dependencies = podfile.target_definitions.flat_map do |_, target| @podfile_dependency_cache.podfile_dependencies.each do |dependency|
target.dependencies
end.uniq
dependencies.each do |dependency|
validate_conflicting_external_sources!(dependency) validate_conflicting_external_sources!(dependency)
end end
end end
...@@ -106,7 +103,7 @@ module Pod ...@@ -106,7 +103,7 @@ module Pod
# @return [void] # @return [void]
# #
def validate_dependencies_are_present! def validate_dependencies_are_present!
if podfile.target_definitions.values.all?(&:empty?) if @podfile_dependency_cache.target_definition_list.all?(&:empty?)
add_warning 'The Podfile does not contain any dependencies.' add_warning 'The Podfile does not contain any dependencies.'
end end
end end
...@@ -116,8 +113,8 @@ module Pod ...@@ -116,8 +113,8 @@ module Pod
# target, or be inherited by a target where `inheritance == complete`. # target, or be inherited by a target where `inheritance == complete`.
# #
def validate_no_abstract_only_pods! def validate_no_abstract_only_pods!
all_dependencies = podfile.dependencies all_dependencies = @podfile_dependency_cache.podfile_dependencies
concrete_dependencies = podfile.target_definition_list.reject(&:abstract?).flat_map(&:dependencies).uniq concrete_dependencies = @podfile_dependency_cache.target_definition_list.reject(&:abstract?).flat_map { |td| @podfile_dependency_cache.target_definition_dependencies(td) }
abstract_only_dependencies = all_dependencies - concrete_dependencies abstract_only_dependencies = all_dependencies - concrete_dependencies
abstract_only_dependencies.each do |dep| abstract_only_dependencies.each do |dep|
add_error "The dependency `#{dep}` is not used in any concrete target." add_error "The dependency `#{dep}` is not used in any concrete target."
...@@ -125,7 +122,7 @@ module Pod ...@@ -125,7 +122,7 @@ module Pod
end end
def validate_no_duplicate_targets! def validate_no_duplicate_targets!
podfile.target_definition_list.group_by { |td| [td.name, td.user_project_path] }. @podfile_dependency_cache.target_definition_list.group_by { |td| [td.name, td.user_project_path] }.
each do |(name, project), definitions| each do |(name, project), definitions|
next unless definitions.size > 1 next unless definitions.size > 1
error = "The target `#{name}` is declared twice" error = "The target `#{name}` is declared twice"
......
...@@ -40,6 +40,15 @@ module Pod ...@@ -40,6 +40,15 @@ module Pod
# #
attr_reader :development_pods attr_reader :development_pods
# Overridden to generate UUIDs in a much faster way, since we don't need to check for collisions
# (as the Pods project is regenerated each time, and thus all UUIDs will have come from this method)
def generate_available_uuid_list(count = 100)
start = @generated_uuids.size
uniques = Array.new(count) { |i| format('%011X0', start + i) }
@generated_uuids += uniques
@available_uuids += uniques
end
public public
# @!group Legacy Xcode build root # @!group Legacy Xcode build root
......
...@@ -85,9 +85,11 @@ module Pod ...@@ -85,9 +85,11 @@ module Pod
# @param [Array<Dependency>] locked_dependencies @see locked_dependencies # @param [Array<Dependency>] locked_dependencies @see locked_dependencies
# @param [Array<Source>, Source] sources @see sources # @param [Array<Source>, Source] sources @see sources
# #
def initialize(sandbox, podfile, locked_dependencies, sources) def initialize(sandbox, podfile, locked_dependencies, sources,
podfile_dependency_cache: Installer::Analyzer::PodfileDependencyCache.from_podfile(podfile))
@sandbox = sandbox @sandbox = sandbox
@podfile = podfile @podfile = podfile
@podfile_dependency_cache = podfile_dependency_cache
@locked_dependencies = locked_dependencies @locked_dependencies = locked_dependencies
@sources = Array(sources) @sources = Array(sources)
@platforms_by_dependency = Hash.new { |h, k| h[k] = [] } @platforms_by_dependency = Hash.new { |h, k| h[k] = [] }
...@@ -107,11 +109,13 @@ module Pod ...@@ -107,11 +109,13 @@ module Pod
# definition. # definition.
# #
def resolve def resolve
dependencies = podfile.target_definition_list.flat_map do |target| dependencies = @podfile_dependency_cache.target_definition_list.flat_map do |target|
target.dependencies.each do |dep| @podfile_dependency_cache.target_definition_dependencies(target).each do |dep|
@platforms_by_dependency[dep].push(target.platform).uniq! if target.platform next unless target.platform
@platforms_by_dependency[dep].push(target.platform)
end end
end end
@platforms_by_dependency.each_value(&:uniq!)
@activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies) @activated = Molinillo::Resolver.new(self, self).resolve(dependencies, locked_dependencies)
resolver_specs_by_target resolver_specs_by_target
rescue Molinillo::ResolverError => e rescue Molinillo::ResolverError => e
...@@ -125,9 +129,9 @@ module Pod ...@@ -125,9 +129,9 @@ module Pod
# #
def resolver_specs_by_target def resolver_specs_by_target
@resolver_specs_by_target ||= {}.tap do |resolver_specs_by_target| @resolver_specs_by_target ||= {}.tap do |resolver_specs_by_target|
podfile.target_definition_list.each do |target|
dependencies = {} dependencies = {}
specs = target.dependencies.flat_map do |dep| @podfile_dependency_cache.target_definition_list.each do |target|
specs = @podfile_dependency_cache.target_definition_dependencies(target).flat_map do |dep|
name = dep.name name = dep.name
node = @activated.vertex_named(name) node = @activated.vertex_named(name)
(valid_dependencies_for_target_from_node(target, dependencies, node) << node).map { |s| [s, node.payload.test_specification?] } (valid_dependencies_for_target_from_node(target, dependencies, node) << node).map { |s| [s, node.payload.test_specification?] }
...@@ -559,11 +563,11 @@ module Pod ...@@ -559,11 +563,11 @@ module Pod
# dependencies for `target`. # dependencies for `target`.
# #
def valid_dependencies_for_target_from_node(target, dependencies, node) def valid_dependencies_for_target_from_node(target, dependencies, node)
dependencies[node.name] ||= begin dependencies[[node.name, target.platform]] ||= begin
validate_platform(node.payload, target) validate_platform(node.payload, target)
dependency_nodes = [] dependency_nodes = []
node.outgoing_edges.each do |edge| node.outgoing_edges.each do |edge|
next unless edge_is_valid_for_target?(edge, target) next unless edge_is_valid_for_target_platform?(edge, target.platform)
dependency_nodes << edge.destination dependency_nodes << edge.destination
end end
...@@ -574,14 +578,14 @@ module Pod ...@@ -574,14 +578,14 @@ module Pod
end end
# Whether the given `edge` should be followed to find dependencies for the # Whether the given `edge` should be followed to find dependencies for the
# given `target`. # given `target_platform`.
# #
# @return [Bool] # @return [Bool]
# #
def edge_is_valid_for_target?(edge, target) def edge_is_valid_for_target_platform?(edge, target_platform)
requirement_name = edge.requirement.name requirement_name = edge.requirement.name
edge.origin.payload.all_dependencies(target.platform).any? do |dep| edge.origin.payload.all_dependencies(target_platform).any? do |dep|
dep.name == requirement_name dep.name == requirement_name
end end
end end
......
...@@ -140,7 +140,7 @@ module Pod ...@@ -140,7 +140,7 @@ module Pod
# @return [Array<AggregateTarget>] The aggregate targets whose pods this # @return [Array<AggregateTarget>] The aggregate targets whose pods this
# target must be able to import, but will not directly link against. # target must be able to import, but will not directly link against.
# #
attr_accessor :search_paths_aggregate_targets attr_reader :search_paths_aggregate_targets
# @param [String] build_configuration The build configuration for which the # @param [String] build_configuration The build configuration for which the
# the pod targets should be returned. # the pod targets should be returned.
...@@ -149,11 +149,16 @@ module Pod ...@@ -149,11 +149,16 @@ module Pod
# configuration. # configuration.
# #
def pod_targets_for_build_configuration(build_configuration) def pod_targets_for_build_configuration(build_configuration)
pod_targets.select do |pod_target| @pod_targets_for_build_configuration ||= {}
@pod_targets_for_build_configuration[build_configuration] ||= pod_targets.select do |pod_target|
pod_target.include_in_build_config?(target_definition, build_configuration) pod_target.include_in_build_config?(target_definition, build_configuration)
end end
end end
def pod_targets_to_link
@pod_targets_to_link ||= pod_targets.to_set - search_paths_aggregate_targets.flat_map(&:pod_targets)
end
# @return [Array<Specification>] The specifications used by this aggregate target. # @return [Array<Specification>] The specifications used by this aggregate target.
# #
def specs def specs
...@@ -191,9 +196,7 @@ module Pod ...@@ -191,9 +196,7 @@ module Pod
@framework_paths_by_config ||= begin @framework_paths_by_config ||= begin
framework_paths_by_config = {} framework_paths_by_config = {}
user_build_configurations.keys.each do |config| user_build_configurations.keys.each do |config|
relevant_pod_targets = pod_targets.select do |pod_target| relevant_pod_targets = pod_targets_for_build_configuration(config)
pod_target.include_in_build_config?(target_definition, config)
end
framework_paths_by_config[config] = relevant_pod_targets.flat_map { |pt| pt.framework_paths(false) } framework_paths_by_config[config] = relevant_pod_targets.flat_map { |pt| pt.framework_paths(false) }
end end
framework_paths_by_config framework_paths_by_config
...@@ -208,8 +211,7 @@ module Pod ...@@ -208,8 +211,7 @@ module Pod
pod_target.should_build? && pod_target.requires_frameworks? && !pod_target.static_framework? pod_target.should_build? && pod_target.requires_frameworks? && !pod_target.static_framework?
end end
user_build_configurations.keys.each_with_object({}) do |config, resources_by_config| user_build_configurations.keys.each_with_object({}) do |config, resources_by_config|
resources_by_config[config] = relevant_pod_targets.flat_map do |pod_target| resources_by_config[config] = (relevant_pod_targets & pod_targets_for_build_configuration(config)).flat_map do |pod_target|
next [] unless pod_target.include_in_build_config?(target_definition, config)
(pod_target.resource_paths(false) + [bridge_support_file].compact).uniq (pod_target.resource_paths(false) + [bridge_support_file].compact).uniq
end end
end end
......
...@@ -522,10 +522,8 @@ module Pod ...@@ -522,10 +522,8 @@ module Pod
if whitelists.empty? if whitelists.empty?
@build_config_cache[key] = true @build_config_cache[key] = true
true
elsif whitelists.count == 1 elsif whitelists.count == 1
@build_config_cache[key] = whitelists.first @build_config_cache[key] = whitelists.first
whitelists.first
else else
raise Informative, "The subspecs of `#{pod_name}` are linked to " \ raise Informative, "The subspecs of `#{pod_name}` are linked to " \
"different build configurations for the `#{target_definition}` " \ "different build configurations for the `#{target_definition}` " \
......
...@@ -497,7 +497,7 @@ module Pod ...@@ -497,7 +497,7 @@ module Pod
it 'should include inherited search paths' do it 'should include inherited search paths' do
# It's the responsibility of the analyzer to # It's the responsibility of the analyzer to
# populate this when the file is loaded. # populate this when the file is loaded.
@blank_target.search_paths_aggregate_targets = [@target] @blank_target.search_paths_aggregate_targets.replace [@target]
@xcconfig = @generator.generate @xcconfig = @generator.generate
@xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.not.be.nil @xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.not.be.nil
end end
......
require File.expand_path('../../../../spec_helper', __FILE__)
module Pod
class Installer
class Analyzer
describe PodfileDependencyCache do
describe '.from_podfile' do
it 'returns a warmed cache' do
podfile = Podfile.new do
pod 'A'
target 'T1' do
pod 'B'
target 'T1T' do
inherit! :search_paths
pod 'C'
end
end
target 'T2' do
pod 'B'
target 'T2T' do
inherit! :none
pod 'D'
end
end
end
cache = PodfileDependencyCache.from_podfile(podfile)
cache.podfile_dependencies.should == podfile.dependencies
target_definitions = podfile.target_definition_list
cache.target_definition_list.should == target_definitions
podfile.target_definition_list.each do |td|
cache.target_definition_dependencies(td).should == td.dependencies
end
lambda { cache.target_definition_dependencies(nil) }.should.raise(ArgumentError)
end
end
end
end
end
end
...@@ -598,8 +598,11 @@ module Pod ...@@ -598,8 +598,11 @@ module Pod
it 'fetches the dependencies with external sources' do it 'fetches the dependencies with external sources' do
podfile_state = Installer::Analyzer::SpecsState.new podfile_state = Installer::Analyzer::SpecsState.new
podfile_state.added << 'BananaLib' podfile_state.added << 'BananaLib'
@podfile = Podfile.new do
pod 'BananaLib', :git => 'example.com'
end
@analyzer = Installer::Analyzer.new(@sandbox, @podfile)
@analyzer.stubs(:result).returns(stub(:podfile_state => podfile_state)) @analyzer.stubs(:result).returns(stub(:podfile_state => podfile_state))
@podfile.stubs(:dependencies).returns([Dependency.new('BananaLib', :git => 'example.com')])
ExternalSources::DownloaderSource.any_instance.expects(:fetch) ExternalSources::DownloaderSource.any_instance.expects(:fetch)
@analyzer.send(:fetch_external_sources) @analyzer.send(:fetch_external_sources)
end end
...@@ -607,11 +610,12 @@ module Pod ...@@ -607,11 +610,12 @@ module Pod
it 'does not download the same source multiple times for different subspecs' do it 'does not download the same source multiple times for different subspecs' do
podfile_state = Installer::Analyzer::SpecsState.new podfile_state = Installer::Analyzer::SpecsState.new
podfile_state.added << 'ARAnalytics' podfile_state.added << 'ARAnalytics'
@podfile = Podfile.new do
pod 'ARAnalytics/Mixpanel', :git => 'https://github.com/orta/ARAnalytics', :commit => '6f1a1c314894437e7e5c09572c276e644dbfb64b'
pod 'ARAnalytics/HockeyApp', :git => 'https://github.com/orta/ARAnalytics', :commit => '6f1a1c314894437e7e5c09572c276e644dbfb64b'
end
@analyzer = Installer::Analyzer.new(@sandbox, @podfile)
@analyzer.stubs(:result).returns(stub(:podfile_state => podfile_state)) @analyzer.stubs(:result).returns(stub(:podfile_state => podfile_state))
@podfile.stubs(:dependencies).returns([
Dependency.new('ARAnalytics/Mixpanel', :git => 'https://github.com/orta/ARAnalytics', :commit => '6f1a1c314894437e7e5c09572c276e644dbfb64b'),
Dependency.new('ARAnalytics/HockeyApp', :git => 'https://github.com/orta/ARAnalytics', :commit => '6f1a1c314894437e7e5c09572c276e644dbfb64b'),
])
ExternalSources::DownloaderSource.any_instance.expects(:fetch).once ExternalSources::DownloaderSource.any_instance.expects(:fetch).once
@analyzer.send(:fetch_external_sources) @analyzer.send(:fetch_external_sources)
end end
...@@ -984,7 +988,7 @@ module Pod ...@@ -984,7 +988,7 @@ module Pod
describe 'podfile validation' do describe 'podfile validation' do
before do before do
@sandbox = stub('Sandbox') @sandbox = stub('Sandbox')
@podfile = stub('Podfile') @podfile = Podfile.new
@analyzer = Installer::Analyzer.new(@sandbox, @podfile) @analyzer = Installer::Analyzer.new(@sandbox, @podfile)
end end
......
...@@ -371,6 +371,7 @@ module Pod ...@@ -371,6 +371,7 @@ module Pod
describe '#clean_sandbox' do describe '#clean_sandbox' do
before do before do
@analysis_result = Installer::Analyzer::AnalysisResult.new @analysis_result = Installer::Analyzer::AnalysisResult.new
@analysis_result.podfile_dependency_cache = Installer::Analyzer::PodfileDependencyCache.from_podfile(@installer.podfile)
@analysis_result.specifications = [] @analysis_result.specifications = []
@analysis_result.sandbox_state = Installer::Analyzer::SpecsState.new @analysis_result.sandbox_state = Installer::Analyzer::SpecsState.new
@spec = stub(:name => 'Spec', :test_specification? => false) @spec = stub(:name => 'Spec', :test_specification? => false)
...@@ -563,6 +564,7 @@ module Pod ...@@ -563,6 +564,7 @@ module Pod
describe '#write_lockfiles' do describe '#write_lockfiles' do
before do before do
@analysis_result = Installer::Analyzer::AnalysisResult.new @analysis_result = Installer::Analyzer::AnalysisResult.new
@analysis_result.podfile_dependency_cache = Installer::Analyzer::PodfileDependencyCache.from_podfile(@installer.podfile)
@analysis_result.specifications = [fixture_spec('banana-lib/BananaLib.podspec')] @analysis_result.specifications = [fixture_spec('banana-lib/BananaLib.podspec')]
@analysis_result.specs_by_source = {} @analysis_result.specs_by_source = {}
@installer.stubs(:analysis_result).returns(@analysis_result) @installer.stubs(:analysis_result).returns(@analysis_result)
......
This diff is collapsed.
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