Commit cffad7d0 authored by Marius Rackwitz's avatar Marius Rackwitz

[Analyzer] Revised model-generation

The analyzer generates now first deduplicated pod targets and instantiates them with all target definitions, where they are used, and then generates all the aggregate targets. So it can select the required pod target for each the aggregate target and doesn't need to alter intermediate products as before.
parent 9a4f361d
......@@ -219,16 +219,15 @@ module Pod
private
# Creates the models that represent the libraries generated by CocoaPods.
# Creates the models that represent the targets generated by CocoaPods.
#
# @return [Array<Target>] the generated libraries.
# @return [Array<AggregateTarget>]
#
def generate_targets
targets = []
result.specs_by_target.each do |target_definition, specs|
targets << generate_target(target_definition, specs, targets.map(&:pod_targets).flatten)
pod_targets = generate_pod_targets(result.specs_by_target)
result.specs_by_target.map do |target_definition, _|
generate_target(target_definition, pod_targets)
end
targets
end
# Setup the aggregate target for a single user target
......@@ -236,16 +235,12 @@ module Pod
# @param [TargetDefinition] target_definition
# the target definition for the user target.
#
# @param [Array<Specification>] specs
# the specifications that need to be installed grouped by the
# given target definition.
#
# @param [Array<PodTarget>] pod_targets
# the pod targets, which were generated so far.
# the pod targets, which were generated.
#
# @return [AggregateTarget]
#
def generate_target(target_definition, specs, pod_targets)
def generate_target(target_definition, pod_targets)
target = AggregateTarget.new(target_definition, sandbox)
target.host_requires_frameworks |= target_definition.uses_frameworks?
......@@ -265,64 +260,72 @@ module Pod
end
end
target.pod_targets = generate_pod_targets(target, specs, pod_targets)
target.pod_targets = pod_targets.select do |pod_target|
pod_target.target_definitions.include?(target_definition)
end
target
end
# Setup the pod targets for an aggregate target. Group specs and subspecs
# by their root to create a {PodTarget} for each spec.
#
# @param [AggregateTarget] target
# the aggregate target
# Setup the pod targets for an aggregate target. Deduplicates resulting
# targets by grouping by grouping by platform and subspec by their root
# to create a {PodTarget} for each spec.
#
# @param [Array<Specification>] specs
# the specifications that need to be installed.
#
# @param [Array<PodTarget>] pod_targets
# the pod targets, which were generated so far.
# @param [Hash{Podfile::TargetDefinition => Array<Specification>}] specs_by_target
# the resolved specifications grouped by target.
#
# @return [Array<PodTarget>]
#
def generate_pod_targets(target, specs, pod_targets)
grouped_specs = specs.group_by(&:root).values.uniq
grouped_specs.map do |pod_specs|
if config.deduplicate_targets?
# If there are no or already multiple pod targets with a common root,
# or the one which exists differs in the activated subspec set, then
# we need to generate another pod target
root_spec = pod_specs.first.root
common_root_pod_targets = pod_targets.
select { |t| t.platform == target.platform }.
select { |t| t.root_spec == root_spec }
if common_root_pod_targets.count != 1 || common_root_pod_targets.first.specs != pod_specs
pod_target = generate_pod_target(target, pod_specs)
unless common_root_pod_targets.empty?
common_root_pod_targets.each { |t| t.scoped = true }
pod_target.scoped = true
def generate_pod_targets(specs_by_target)
if config.deduplicate_targets?
all_specs = specs_by_target.flat_map do |target_definition, dependent_specs|
dependent_specs.group_by(&:root).map do |root_spec, specs|
[root_spec, specs, target_definition]
end
end
distinct_targets = all_specs.each_with_object({}) do |dependency, hash|
root_spec, specs, target_definition = *dependency
hash[root_spec] ||= {}
(hash[root_spec][[specs, target_definition.platform]] ||= []) << target_definition
end
distinct_targets.values.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.map do |distinctor, target_definitions|
specs, _ = *distinctor
generate_pod_target(target_definitions, specs, scoped: true)
end
pod_target
else
common_root_pod_targets.first
(specs, _), target_definitions = targets_by_distinctors.first
generate_pod_target(target_definitions, specs)
end
end
else
specs_by_target.flat_map do |target_definition, specs|
grouped_specs = specs.group_by.group_by(&:root).values.uniq
grouped_specs.flat_map do |pod_specs|
generate_pod_target([target_definition], pod_specs, scoped: true)
end
else
generate_pod_target(target, pod_specs).scoped
end
end
end
# Create a target for each spec group and add it to the aggregate target
# Create a target for each spec group
#
# @param [AggregateTarget] target
# @param [TargetDefinitions] target_definitions
# the aggregate target
#
# @param [Array<Specification>] specs
# the specifications of an equal root.
#
# @param [Bool] scoped
# whether the pod target should be scoped
#
# @return [PodTarget]
#
def generate_pod_target(target, pod_specs)
pod_target = PodTarget.new(pod_specs, target.target_definition, sandbox)
def generate_pod_target(target_definitions, pod_specs, scoped: false)
pod_target = PodTarget.new(pod_specs, target_definitions, sandbox, scoped)
if config.integrate_targets?
target_inspections = result.target_inspections.select { |t, _| target_definitions.include?(t) }.values
......@@ -330,7 +333,7 @@ module Pod
pod_target.archs = target_inspections.map(&:archs).uniq.sort
else
pod_target.user_build_configurations = {}
if target.platform.name == :osx
if target_definitions.first.platform.name == :osx
pod_target.archs = '$(ARCHS_STANDARD_64_BIT)'
end
end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment