class Pod::PodTarget

Stores the information relative to the target used to compile a single Pod. A pod can have one or more activated spec, subspecs and test specs.

Attributes

app_dependent_targets_by_spec_name[R]

@return [Hash{String=>Array<PodTarget>}] all target dependencies by app spec name.

app_dependent_targets_by_spec_name_by_config[R]
app_spec_build_settings[R]

@return [Hash{String => BuildSettings}] the app spec build settings for this target.

app_spec_build_settings_by_config[R]
app_specs[R]

@return [Array<Specification>] All of the specs within this target that are app specs.

Subset of #specs.
build_headers[R]

@return [HeadersStore] the header directory for the target.

dependent_targets[R]

@return [Array<PodTarget>] the targets that this target has a dependency

upon.
dependent_targets_by_config[R]
file_accessors[R]

@return [Array<Sandbox::FileAccessor>] the file accessors for the

specifications of this target.
library_specs[R]

@return [Array<Specification>] All of the specs within this target that are library specs.

Subset of #specs.
scope_suffix[R]

@return [String] the suffix used for this target when deduplicated. May be ‘nil`.

@note This affects the value returned by configuration_build_dir

and accessors relying on this as #build_product_path.
specs[R]

@return [Array<Specification>] the spec, subspecs and test specs of the target.

swift_version[R]

@return [String] the Swift version for this target.

target_definitions[R]

@return [Array<TargetDefinition>] the target definitions of the Podfile

that generated this target.
test_app_hosts_by_spec[RW]

@return [Hash{Specification => (Specification,PodTarget)}] tuples of app specs and pod targets by test spec.

test_dependent_targets_by_spec_name[R]

@return [Hash{String=>Array<PodTarget>}] all target dependencies by test spec name.

test_dependent_targets_by_spec_name_by_config[R]
test_spec_build_settings[R]

@return [Hash{String => BuildSettings}] the test spec build settings for this target.

test_spec_build_settings_by_config[R]
test_specs[R]

@return [Array<Specification>] All of the test specs within this target.

Subset of #specs.

Public Class Methods

new(sandbox, build_type, user_build_configurations, archs, platform, specs, target_definitions, file_accessors = [], scope_suffix = nil, swift_version = nil) click to toggle source

Initialize a new instance

@param [Sandbox] sandbox @see Target#sandbox @param [BuildType] build_type @see Target#build_type @param [Hash{String=>Symbol}] user_build_configurations @see Target#user_build_configurations @param [Array<String>] archs @see Target#archs @param [Platform] platform @see Target#platform @param [Array<Specification>] specs @see specs @param [Array<TargetDefinition>] target_definitions @see target_definitions @param [Array<Sandbox::FileAccessor>] file_accessors @see file_accessors @param [String] scope_suffix @see scope_suffix @param [String] swift_version @see swift_version

Calls superclass method Pod::Target::new
# File lib/cocoapods/target/pod_target.rb, line 137
def initialize(sandbox, build_type, user_build_configurations, archs, platform, specs, target_definitions,
               file_accessors = [], scope_suffix = nil, swift_version = nil)
  super(sandbox, build_type, user_build_configurations, archs, platform)
  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 with an empty string scope suffix!" if scope_suffix == ''
  @specs = specs.dup.freeze
  @target_definitions = target_definitions
  @file_accessors = file_accessors
  @scope_suffix = scope_suffix
  @swift_version = swift_version
  all_specs_by_type = @specs.group_by(&:spec_type)
  @library_specs = all_specs_by_type[:library] || []
  @test_specs = all_specs_by_type[:test] || []
  @app_specs = all_specs_by_type[:app] || []
  @build_headers = Sandbox::HeadersStore.new(sandbox, 'Private', :private)
  self.dependent_targets = []
  self.test_dependent_targets_by_spec_name = Hash[test_specs.map { |ts| [ts.name, []] }]
  self.app_dependent_targets_by_spec_name = Hash[app_specs.map { |as| [as.name, []] }]
  @test_app_hosts_by_spec = {}
  @build_config_cache = {}
  @test_spec_build_settings_by_config = create_test_build_settings_by_config
  @app_spec_build_settings_by_config = create_app_build_settings_by_config
end

Public Instance Methods

all_files() click to toggle source

@return [Array<Pathname>] The list of all files tracked.

# File lib/cocoapods/target/pod_target.rb, line 208
def all_files
  Sandbox::FileAccessor.all_files(file_accessors)
end
app_dependent_targets_by_spec_name=(app_dependent_targets_by_spec_name) click to toggle source

@deprecated

# File lib/cocoapods/target/pod_target.rb, line 92
def app_dependent_targets_by_spec_name=(app_dependent_targets_by_spec_name)
  @app_dependent_targets_by_spec_name = app_dependent_targets_by_spec_name
  @app_dependent_targets_by_spec_name_by_config = Hash[app_dependent_targets_by_spec_name.map do |k, v|
    [k, { :debug => v, :release => v }]
  end]
end
app_dependent_targets_by_spec_name_by_config=(app_dependent_targets_by_spec_name_by_config) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 99
def app_dependent_targets_by_spec_name_by_config=(app_dependent_targets_by_spec_name_by_config)
  @app_dependent_targets_by_spec_name_by_config = app_dependent_targets_by_spec_name_by_config
  @app_dependent_targets_by_spec_name = Hash[app_dependent_targets_by_spec_name_by_config.map do |k, v|
    [k, v.each_value.reduce(Set.new, &:|).to_a]
  end]
end
app_host_dependent_targets_for_spec(spec, configuration: nil) click to toggle source

@param [Specification] spec

the spec to return app host dependencies for

@param [String] configuration

the configuration to retrieve the app host dependent targets for.

@return [Array<PodTarget>] the app host dependent targets for the given spec.

# File lib/cocoapods/target/pod_target.rb, line 632
def app_host_dependent_targets_for_spec(spec, configuration: nil)
  return [] unless spec.test_specification? && spec.consumer(platform).test_type == :unit
  app_host_info = test_app_hosts_by_spec[spec]
  if app_host_info.nil?
    []
  else
    app_spec, app_target = *app_host_info
    app_target.dependent_targets_for_app_spec(app_spec, :configuration => configuration)
  end
end
app_host_target_label(test_spec) click to toggle source

@param [Specification] test_spec

the test spec to use for producing the app host target label.

@return [(String,String)] a tuple, where the first item is the PodTarget#label of the pod target that defines the

app host, and the second item is the target name of the app host
# File lib/cocoapods/target/pod_target.rb, line 614
def app_host_target_label(test_spec)
  app_spec, app_target = test_app_hosts_by_spec[test_spec]

  if app_spec
    [app_target.name, app_target.app_target_label(app_spec)]
  elsif test_spec.consumer(platform).requires_app_host?
    [name, "AppHost-#{label}-#{label_for_test_type(test_spec.test_type)}-Tests"]
  end
end
app_spec_consumers() click to toggle source

@return [Array<Specification::Consumer>] the app specification consumers for

the target.
# File lib/cocoapods/target/pod_target.rb, line 317
def app_spec_consumers
  app_specs.map { |app_spec| app_spec.consumer(platform) }
end
app_target_label(app_spec) click to toggle source

@param [Specification] app_spec

The app spec to use for producing the app label.

@return [String] The derived name of the app target.

# File lib/cocoapods/target/pod_target.rb, line 604
def app_target_label(app_spec)
  "#{label}-#{subspec_label(app_spec)}"
end
build_product_path(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE) click to toggle source

@param [String] dir

@see #configuration_build_dir

@return [String] The absolute path to the build product

# File lib/cocoapods/target/pod_target.rb, line 990
def build_product_path(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE)
  "#{configuration_build_dir(dir)}/#{product_name}"
end
build_settings_by_config_for_spec(spec) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 1052
def build_settings_by_config_for_spec(spec)
  case spec.spec_type
  when :test then test_spec_build_settings_by_config[spec.name]
  when :app  then app_spec_build_settings_by_config[spec.name]
  else            build_settings
  end || raise(ArgumentError, "No build settings for #{spec}")
end
build_settings_for_spec(spec, configuration: nil) click to toggle source

@param [Specification] spec the specification to return build settings for.

@param [String] configuration the configuration to scope the build settings.

@return [BuildSettings::PodTargetSettings] The build settings for the given spec

# File lib/cocoapods/target/pod_target.rb, line 1046
def build_settings_for_spec(spec, configuration: nil)
  raise ArgumentError, 'Must give configuration' unless configuration
  configuration = user_build_configurations[configuration] if user_build_configurations.key?(configuration)
  build_settings_by_config_for_spec(spec)[configuration] || raise(ArgumentError, "No build settings for #{spec} (configuration #{configuration.inspect}) (known configurations #{config_variants})")
end
configuration_build_dir(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE) click to toggle source

@param [String] dir

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.

@return [String] The absolute path to the configuration build dir

# File lib/cocoapods/target/pod_target.rb, line 981
def configuration_build_dir(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE)
  "#{dir}/#{label}"
end
contains_app_specifications?() click to toggle source

@return [Boolean] Whether the target has any app specifications.

# File lib/cocoapods/target/pod_target.rb, line 399
def contains_app_specifications?
  !app_specs.empty?
end
contains_script_phases?() click to toggle source

@return [Boolean] Whether the target contains any script phases.

# File lib/cocoapods/target/pod_target.rb, line 387
def contains_script_phases?
  !script_phases.empty?
end
contains_test_specifications?() click to toggle source

@return [Boolean] Whether the target has any tests specifications.

# File lib/cocoapods/target/pod_target.rb, line 393
def contains_test_specifications?
  !test_specs.empty?
end
copy_dsyms_script_input_files_path() click to toggle source

@return [Pathname] The absolute path of the copy dSYM script phase input file list.

# File lib/cocoapods/target/pod_target.rb, line 785
def copy_dsyms_script_input_files_path
  support_files_dir + "#{label}-copy-dsyms-input-files.xcfilelist"
end
copy_dsyms_script_output_files_path() click to toggle source

@return [Pathname] The absolute path of the copy dSYM script phase output file list.

# File lib/cocoapods/target/pod_target.rb, line 791
def copy_dsyms_script_output_files_path
  support_files_dir + "#{label}-copy-dsyms-output-files.xcfilelist"
end
copy_dsyms_script_path() click to toggle source

@return [Pathname] The absolute path of the copy dSYMs script.

# File lib/cocoapods/target/pod_target.rb, line 779
def copy_dsyms_script_path
  support_files_dir + "#{label}-copy-dsyms.sh"
end
copy_resources_script_input_files_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this copy resources script path is for.

@return [Pathname] The absolute path of the copy resources script input file list for the given spec.

# File lib/cocoapods/target/pod_target.rb, line 680
def copy_resources_script_input_files_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-resources-input-files.xcfilelist"
end
copy_resources_script_output_files_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this copy resources script path is for.

@return [Pathname] The absolute path of the copy resources script output file list for the given spec.

# File lib/cocoapods/target/pod_target.rb, line 689
def copy_resources_script_output_files_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-resources-output-files.xcfilelist"
end
copy_resources_script_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this copy resources script path is for.

@return [Pathname] The absolute path of the copy resources script for the given spec.

# File lib/cocoapods/target/pod_target.rb, line 671
def copy_resources_script_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-resources.sh"
end
copy_xcframeworks_script_input_files_path() click to toggle source

@return [String] The path of the copy xcframeworks input files file list

# File lib/cocoapods/target/pod_target.rb, line 728
def copy_xcframeworks_script_input_files_path
  support_files_dir + "#{label}-xcframeworks-input-files.xcfilelist"
end
copy_xcframeworks_script_output_files_path() click to toggle source

@return [String] The path of the copy xcframeworks output files file list

# File lib/cocoapods/target/pod_target.rb, line 734
def copy_xcframeworks_script_output_files_path
  support_files_dir + "#{label}-xcframeworks-output-files.xcfilelist"
end
copy_xcframeworks_script_path() click to toggle source

@return [Pathname] The absolute path of the copy xcframeworks script.

# File lib/cocoapods/target/pod_target.rb, line 722
def copy_xcframeworks_script_path
  support_files_dir + "#{label}-xcframeworks.sh"
end
defines_module?() click to toggle source

@return [Boolean] Whether the target defines a “module”

(and thus will need a module map and umbrella header).

@note Static library targets can temporarily opt in to this behavior by setting

`DEFINES_MODULE = YES` in their specification's `pod_target_xcconfig`.
# File lib/cocoapods/target/pod_target.rb, line 359
def defines_module?
  return @defines_module if defined?(@defines_module)
  return @defines_module = true if uses_swift? || build_as_framework?

  explicit_target_definitions = target_definitions.select { |td| td.dependencies.any? { |d| d.root_name == pod_name } }
  tds_by_answer = explicit_target_definitions.group_by { |td| td.build_pod_as_module?(pod_name) }

  if tds_by_answer.size > 1
    UI.warn "Unable to determine whether to build `#{label}` as a module due to a conflict " \
      "between the following target definitions:\n\t- #{tds_by_answer.map do |a, td|
                                                          "`#{td.to_sentence}` #{a ? "requires `#{label}` as a module" : "does not require `#{label}` as a module"}"
                                                        end.join("\n\t- ")}\n\n" \
      "Defaulting to skip building `#{label}` as a module."
  elsif tds_by_answer.keys.first == true || target_definitions.all? { |td| td.build_pod_as_module?(pod_name) }
    return @defines_module = true
  end

  @defines_module = library_specs.any? { |s| s.consumer(platform).pod_target_xcconfig['DEFINES_MODULE'] == 'YES' }
end
dependencies() click to toggle source

@return [Array<String>] The names of the Pods on which this target

depends.
# File lib/cocoapods/target/pod_target.rb, line 816
def dependencies
  spec_consumers.flat_map do |consumer|
    consumer.dependencies.map { |dep| Specification.root_name(dep.name) }
  end.uniq
end
dependent_targets=(dependent_targets) click to toggle source

@deprecated

# File lib/cocoapods/target/pod_target.rb, line 56
def dependent_targets=(dependent_targets)
  @dependent_targets = dependent_targets
  @dependent_targets_by_config = { :debug => dependent_targets, :release => dependent_targets }
end
dependent_targets_by_config=(dependent_targets_by_config) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 61
def dependent_targets_by_config=(dependent_targets_by_config)
  @dependent_targets_by_config = dependent_targets_by_config
  @dependent_targets = dependent_targets_by_config.each_value.reduce([], &:|)
end
dependent_targets_for_app_spec(app_spec, configuration: nil) click to toggle source

@param [Specification] app_spec

the app spec to scope dependencies for

@param [String] configuration

the configuration to retrieve the app dependent targets for.

@return [Array<PodTarget>] the canonical list of dependent targets this target has a dependency upon.

This list includes the target itself as well as its recursive dependent and app dependent targets.
# File lib/cocoapods/target/pod_target.rb, line 944
def dependent_targets_for_app_spec(app_spec, configuration: nil)
  [self, *recursive_dependent_targets(:configuration => configuration), *recursive_app_dependent_targets(app_spec, :configuration => configuration)].uniq
end
dependent_targets_for_test_spec(test_spec, configuration: nil) click to toggle source

@param [Specification] test_spec

the test spec to scope dependencies for

@param [String] configuration

the configuration to retrieve the test dependent targets for.

@return [Array<PodTarget>] the canonical list of dependent targets this target has a dependency upon.

This list includes the target itself as well as its recursive dependent and test dependent targets.
# File lib/cocoapods/target/pod_target.rb, line 897
def dependent_targets_for_test_spec(test_spec, configuration: nil)
  [self, *recursive_dependent_targets(:configuration => configuration), *recursive_test_dependent_targets(test_spec, :configuration => configuration)].uniq
end
deployment_target_for_non_library_spec(spec) click to toggle source

@param [Specification] spec The non library spec to calculate the deployment target for.

@return [String] The deployment target to use for the non library spec. If the non library spec explicitly

specifies one then this is the one used otherwise the one that was determined by the analyzer is used.
# File lib/cocoapods/target/pod_target.rb, line 489
def deployment_target_for_non_library_spec(spec)
  raise ArgumentError, 'Must be a non library spec.' unless spec.non_library_specification?
  spec.deployment_target(platform.name.to_s) || platform.deployment_target.to_s
end
embed_frameworks_script_input_files_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this embed frameworks script path is for.

@return [Pathname] The absolute path of the embed frameworks script input file list for the given spec.

# File lib/cocoapods/target/pod_target.rb, line 707
def embed_frameworks_script_input_files_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-frameworks-input-files.xcfilelist"
end
embed_frameworks_script_output_files_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this embed frameworks script path is for.

@return [Pathname] The absolute path of the embed frameworks script output file list for the given spec.

# File lib/cocoapods/target/pod_target.rb, line 716
def embed_frameworks_script_output_files_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-frameworks-output-files.xcfilelist"
end
embed_frameworks_script_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this embed frameworks script path is for.

@return [Pathname] The absolute path of the embed frameworks script for the given spec.

# File lib/cocoapods/target/pod_target.rb, line 698
def embed_frameworks_script_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-frameworks.sh"
end
framework_paths() click to toggle source

@return [Hash{String=>Array<Xcode::FrameworkPaths>}] The vendored and non vendored framework paths this target

depends upon keyed by spec name. For the root spec and subspecs the framework path of the target itself
is included.
# File lib/cocoapods/target/pod_target.rb, line 407
def framework_paths
  @framework_paths ||= begin
    file_accessors.each_with_object({}) do |file_accessor, hash|
      frameworks = file_accessor.vendored_dynamic_artifacts.map do |framework_path|
        relative_path_to_sandbox = framework_path.relative_path_from(sandbox.root)
        framework_source = "${PODS_ROOT}/#{relative_path_to_sandbox}"
        # Until this can be configured, assume the dSYM file uses the file name as the framework.
        # See https://github.com/CocoaPods/CocoaPods/issues/1698
        dsym_name = "#{framework_path.basename}.dSYM"
        dsym_path = Pathname.new("#{framework_path.dirname}/#{dsym_name}")
        dsym_source = if dsym_path.exist?
                        "${PODS_ROOT}/#{relative_path_to_sandbox}.dSYM"
                      end
        dirname = framework_path.dirname
        bcsymbolmap_paths = if dirname.exist?
                              Dir.chdir(dirname) do
                                Dir.glob('*.bcsymbolmap').map do |bcsymbolmap_file_name|
                                  bcsymbolmap_path = dirname + bcsymbolmap_file_name
                                  "${PODS_ROOT}/#{bcsymbolmap_path.relative_path_from(sandbox.root)}"
                                end
                              end
                            end
        Xcode::FrameworkPaths.new(framework_source, dsym_source, bcsymbolmap_paths)
      end
      if file_accessor.spec.library_specification? && should_build? && build_as_dynamic_framework?
        frameworks << Xcode::FrameworkPaths.new(build_product_path('${BUILT_PRODUCTS_DIR}'))
      end
      hash[file_accessor.spec.name] = frameworks
    end
  end
end
header_mappings_by_file_accessor() click to toggle source

@return [Hash{FileAccessor => Hash}] Hash of file accessors by header mappings.

# File lib/cocoapods/target/pod_target.rb, line 220
def header_mappings_by_file_accessor
  valid_accessors = file_accessors.reject { |fa| fa.spec.non_library_specification? }
  Hash[valid_accessors.map do |file_accessor|
    # Private headers will always end up in Pods/Headers/Private/PodA/*.h
    # This will allow for `""` imports to work.
    [file_accessor, header_mappings(file_accessor, file_accessor.headers)]
  end]
end
header_search_paths(include_dependent_targets_for_test_spec: nil, include_dependent_targets_for_app_spec: nil, include_private_headers: true, configuration: nil) click to toggle source

@param [Boolean] include_dependent_targets_for_test_spec

whether to include header search paths for test dependent targets

@param [Boolean] include_dependent_targets_for_app_spec

whether to include header search paths for app dependent targets

@param [Boolean] include_private_headers

whether to include header search paths for private headers of this
target

@param [String] configuration

the configuration to return header search paths for or `nil` for all configurations.

@return [Array<String>] The set of header search paths this target uses.

# File lib/cocoapods/target/pod_target.rb, line 1022
def header_search_paths(include_dependent_targets_for_test_spec: nil, include_dependent_targets_for_app_spec: nil,
                        include_private_headers: true, configuration: nil)
  header_search_paths = []
  header_search_paths.concat(build_headers.search_paths(platform, nil, false)) if include_private_headers
  header_search_paths.concat(sandbox.public_headers.search_paths(platform, pod_name, uses_modular_headers?))
  dependent_targets = recursive_dependent_targets(:configuration => configuration)
  if include_dependent_targets_for_test_spec
    dependent_targets += recursive_test_dependent_targets(include_dependent_targets_for_test_spec, :configuration => configuration)
  end
  if include_dependent_targets_for_app_spec
    dependent_targets += recursive_app_dependent_targets(include_dependent_targets_for_app_spec, :configuration => configuration)
  end
  dependent_targets.uniq.each do |dependent_target|
    header_search_paths.concat(sandbox.public_headers.search_paths(platform, dependent_target.pod_name, defines_module? && dependent_target.uses_modular_headers?(false)))
  end
  header_search_paths.uniq
end
headers_sandbox() click to toggle source

@return [Pathname] the pathname for headers in the sandbox.

# File lib/cocoapods/target/pod_target.rb, line 214
def headers_sandbox
  Pathname.new(pod_name)
end
info_plist_entries() click to toggle source

@return [Hash] the additional entries to add to the generated Info.plist

# File lib/cocoapods/target/pod_target.rb, line 567
def info_plist_entries
  root_spec.info_plist
end
info_plist_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this Info.plist path is for.

@return [Pathname] The absolute path of the Info.plist for the given spec.

# File lib/cocoapods/target/pod_target.rb, line 800
def info_plist_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-Info.plist"
end
inhibit_warnings?() click to toggle source

Checks if warnings should be inhibited for this pod.

@return [Boolean]

# File lib/cocoapods/target/pod_target.rb, line 952
def inhibit_warnings?
  return @inhibit_warnings if defined? @inhibit_warnings
  whitelists = target_definitions.map do |target_definition|
    target_definition.inhibits_warnings_for_pod?(root_spec.name)
  end.uniq

  if whitelists.empty?
    @inhibit_warnings = false
    false
  elsif whitelists.count == 1
    @inhibit_warnings = whitelists.first
    whitelists.first
  else
    UI.warn "The pod `#{pod_name}` is linked to different targets " \
      "(#{target_definitions.map { |td| "`#{td.name}`" }.to_sentence}), which contain different " \
      'settings to inhibit warnings. CocoaPods does not currently ' \
      'support different settings and will fall back to your preference ' \
      'set in the root target definition.'
    @inhibit_warnings = podfile.root_target_definitions.first.inhibits_warnings_for_pod?(root_spec.name)
  end
end
label() click to toggle source

@return [String] the label for the target.

# File lib/cocoapods/target/pod_target.rb, line 198
def label
  if scope_suffix.nil? || scope_suffix[0] == '.'
    "#{root_spec.name}#{scope_suffix}"
  else
    "#{root_spec.name}-#{scope_suffix}"
  end
end
label_for_test_type(test_type) click to toggle source

Returns the label to use for the given test type. This is used to generate native target names for test specs.

@param [Symbol] test_type

The test type to map to provided by the test specification DSL.

@return [String] The native product type to use.

# File lib/cocoapods/target/pod_target.rb, line 522
def label_for_test_type(test_type)
  case test_type
  when :unit
    'Unit'
  when :ui
    'UI'
  else
    raise ArgumentError, "Unknown test type `#{test_type}`."
  end
end
module_map_path() click to toggle source

@return [Pathname] the absolute path of the LLVM module map file that

defines the module structure for the compiler.
Calls superclass method Pod::Target#module_map_path
# File lib/cocoapods/target/pod_target.rb, line 548
def module_map_path
  basename = "#{label}.modulemap"
  if build_as_framework?
    super
  elsif file_accessors.any?(&:module_map)
    build_headers.root + product_module_name + basename
  else
    sandbox.public_headers.root + product_module_name + basename
  end
end
non_library_spec_label(spec)

for backwards compatibility

Alias for: spec_label
pod_name() click to toggle source

@return [String] The name of the Pod that this target refers to.

# File lib/cocoapods/target/pod_target.rb, line 541
def pod_name
  root_spec.name
end
pod_target_srcroot() click to toggle source

@return [String] The source path of the root for this target relative to ‘$(PODS_ROOT)`

# File lib/cocoapods/target/pod_target.rb, line 996
def pod_target_srcroot
  "${PODS_ROOT}/#{sandbox.pod_dir(pod_name).relative_path_from(sandbox.root)}"
end
podfile() click to toggle source

@return [Podfile] The podfile which declares the dependency.

# File lib/cocoapods/target/pod_target.rb, line 249
def podfile
  target_definitions.first.podfile
end
prefix_header_path() click to toggle source

@return [Pathname] the absolute path of the prefix header file.

# File lib/cocoapods/target/pod_target.rb, line 561
def prefix_header_path
  support_files_dir + "#{label}-prefix.pch"
end
prefix_header_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this prefix header path is for.

@return [Pathname] the absolute path of the prefix header file for the given spec.

# File lib/cocoapods/target/pod_target.rb, line 809
def prefix_header_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-prefix.pch"
end
prepare_artifacts_script_input_files_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this script path is for.

@return [Pathname] The absolute path of the prepare artifacts script input file list for the given spec.

@deprecated

@todo Remove in 2.0

# File lib/cocoapods/target/pod_target.rb, line 760
def prepare_artifacts_script_input_files_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-artifacts-input-files.xcfilelist"
end
prepare_artifacts_script_output_files_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this script path is for.

@return [Pathname] The absolute path of the prepare artifacts script output file list for the given spec.

@deprecated

@todo Remove in 2.0

# File lib/cocoapods/target/pod_target.rb, line 773
def prepare_artifacts_script_output_files_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-artifacts-output-files.xcfilelist"
end
prepare_artifacts_script_path_for_spec(spec) click to toggle source

@param [Specification] spec

The spec this script path is for.

@return [Pathname] The absolute path of the prepare artifacts script for the given spec.

@deprecated

@todo Remove in 2.0

# File lib/cocoapods/target/pod_target.rb, line 747
def prepare_artifacts_script_path_for_spec(spec)
  support_files_dir + "#{spec_label(spec)}-artifacts.sh"
end
product_basename_for_spec(spec) click to toggle source

@param [Specification] spec the specification

@return [String] the product basename of the specification’s target

# File lib/cocoapods/target/pod_target.rb, line 274
def product_basename_for_spec(spec)
  user_specified = build_settings_by_config_for_spec(spec).
                   each_value.
                   map { |settings| settings.merged_pod_target_xcconfigs['PRODUCT_NAME'] }.
                   compact.
                   uniq

  if user_specified.size == 1
    user_specified.first
  else
    spec_label(spec)
  end
end
product_module_name() click to toggle source

@return [String] The name to use for the source code module constructed

for this target, and which will be used to import the module in
implementation source files.
# File lib/cocoapods/target/pod_target.rb, line 267
def product_module_name
  root_spec.module_name
end
product_type_for_test_type(test_type) click to toggle source

Returns the corresponding native product type to use given the test type. This is primarily used when creating the native targets in order to produce the correct test bundle target based on the type of tests included.

@param [Symbol] test_type

The test type to map to provided by the test specification DSL.

@return [Symbol] The native product type to use.

# File lib/cocoapods/target/pod_target.rb, line 503
def product_type_for_test_type(test_type)
  case test_type
  when :unit
    :unit_test_bundle
  when :ui
    :ui_test_bundle
  else
    raise ArgumentError, "Unknown test type `#{test_type}`."
  end
end
project_name() click to toggle source

@return [String] the project name derived from the target definitions that integrate this pod. If none is

specified then the name of the pod is used by default.

@note The name is guaranteed to be the same across all target definitions and is validated by the target

validator during installation.
# File lib/cocoapods/target/pod_target.rb, line 259
def project_name
  target_definitions.map { |td| td.project_name_for_pod(pod_name) }.compact.first || pod_name
end
public_header_mappings_by_file_accessor() click to toggle source

@return [Hash{FileAccessor => Hash}] Hash of file accessors by public header mappings.

# File lib/cocoapods/target/pod_target.rb, line 231
def public_header_mappings_by_file_accessor
  valid_accessors = file_accessors.reject { |fa| fa.spec.non_library_specification? }
  Hash[valid_accessors.map do |file_accessor|
    # Public headers on the other hand will be added in Pods/Headers/Public/PodA/PodA/*.h
    # The extra folder is intentional in order for `<>` imports to work.
    [file_accessor, header_mappings(file_accessor, file_accessor.public_headers)]
  end]
end
recursive_app_dependent_targets(app_spec, configuration: nil) click to toggle source

@param [Specification] app_spec

the app spec to scope dependencies for

@param [String] configuration

the configuration to retrieve the app dependent targets for.

@return [Array<PodTarget>] the recursive targets that this target has a

app dependency upon.
# File lib/cocoapods/target/pod_target.rb, line 910
def recursive_app_dependent_targets(app_spec, configuration: nil)
  @recursive_app_dependent_targets ||= {}
  @recursive_app_dependent_targets[app_spec] ||= begin
    hash = Hash[config_variants.map do |config|
      [config, _add_recursive_app_dependent_targets(app_spec, Set.new, :configuration => config).to_a.freeze]
    end]
    hash[nil] = hash.each_value.reduce(Set.new, &:|).to_a.freeze
    hash
  end
  @recursive_app_dependent_targets[app_spec][configuration]
end
recursive_dependent_targets(configuration: nil) click to toggle source

Returns all dependent targets of this target. If a configuration is passed then the list can be scoped to a given configuration.

@param [String] configuration

The configuration to return the dependent targets for or `nil` if all configurations should be included.

@return [Array<PodTarget>] the recursive targets that this target has a dependency upon.

# File lib/cocoapods/target/pod_target.rb, line 830
def recursive_dependent_targets(configuration: nil)
  @recursive_dependent_targets ||= begin
    hash = Hash[config_variants.map do |config|
      [config, _add_recursive_dependent_targets(Set.new, :configuration => config).delete(self).to_a.freeze]
    end]
    hash[nil] = hash.each_value.reduce(Set.new, &:|).to_a
    hash
  end
  @recursive_dependent_targets.fetch(configuration) { raise ArgumentError, "No configuration #{configuration} for #{self}, known configurations are #{@recursive_dependent_targets.keys}" }
end
recursive_test_dependent_targets(test_spec, configuration: nil) click to toggle source

@param [Specification] test_spec

the test spec to scope dependencies for

@param [String] configuration

the configuration to retrieve the test dependent targets for.

@return [Array<PodTarget>] the recursive targets that this target has a

test dependency upon.
# File lib/cocoapods/target/pod_target.rb, line 863
def recursive_test_dependent_targets(test_spec, configuration: nil)
  @recursive_test_dependent_targets ||= {}
  @recursive_test_dependent_targets[test_spec] ||= begin
    hash = Hash[config_variants.map do |config|
      [config, _add_recursive_test_dependent_targets(test_spec, Set.new, :configuration => config).to_a.freeze]
    end]
    hash[nil] = hash.each_value.reduce(Set.new, &:|).to_a.freeze
    hash
  end
  @recursive_test_dependent_targets[test_spec][configuration]
end
resource_paths() click to toggle source

@return [Hash{String=>Array<String>}] The resource and resource bundle paths this target depends upon keyed by

spec name. Resource (not resource bundles) paths can vary depending on the type of spec:
  - App specs _always_ get their resource paths added to "Copy Bundle Resources" phase from
    [PodTargetInstaller] therefore their resource paths are never included here.
  - Test specs may have their resource paths added to "Copy Bundle Resources" if the target itself is
    built as a framework, which is again checked and handled by PodTargetInstaller. If that is true then
    the resource paths are not included, otherwise they are included and handled via the CocoaPods copy
    resources script phase.
  - Library specs _do not_ have per-configuration CocoaPods copy resources script phase and their resource
    paths will be added to "Copy Bundle Resources" phase if the target is built as a framework because
    it supports it. We always include the resource paths for library specs because they are also
    integrated to the user target.
# File lib/cocoapods/target/pod_target.rb, line 466
def resource_paths
  @resource_paths ||= begin
    file_accessors.each_with_object({}) do |file_accessor, hash|
      resource_paths = if file_accessor.spec.app_specification? || (file_accessor.spec.test_specification? && build_as_framework?)
                         []
                       else
                         file_accessor.resources.map do |res|
                           "${PODS_ROOT}/#{res.relative_path_from(sandbox.project_path.dirname)}"
                         end
                       end
      prefix = Pod::Target::BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE
      prefix = configuration_build_dir unless file_accessor.spec.test_specification?
      resource_bundle_paths = file_accessor.resource_bundles.keys.map { |name| "#{prefix}/#{name.shellescape}.bundle" }
      hash[file_accessor.spec.name] = (resource_paths + resource_bundle_paths).map(&:to_s)
    end
  end
end
resources_bundle_target_label(bundle_name) click to toggle source

@param [String] bundle_name

The name of the bundle product, which is given by the +spec+.

@return [String] The derived name of the resource bundle target.

# File lib/cocoapods/target/pod_target.rb, line 576
def resources_bundle_target_label(bundle_name)
  "#{label}-#{bundle_name}"
end
root_spec() click to toggle source

@return [Specification] The root specification for the target.

# File lib/cocoapods/target/pod_target.rb, line 535
def root_spec
  @root_spec ||= specs.first.root
end
scheme_for_spec(spec) click to toggle source

@param [Specification] spec

The spec to return scheme configuration for.

@return [Hash] The scheme configuration used or empty if none is specified.

# File lib/cocoapods/target/pod_target.rb, line 659
def scheme_for_spec(spec)
  return {} if (spec.library_specification? && !spec.root?) || spec.available_platforms.none? do |p|
    p.name == platform.name
  end
  spec.consumer(platform).scheme
end
scoped(cache = {}) click to toggle source

Scopes the current target based on the existing pod targets within the cache.

@param [Hash{Array => PodTarget}] cache

the cached target for a previously scoped target.

@return [Array<PodTarget>] a scoped copy for each target definition.

# File lib/cocoapods/target/pod_target.rb, line 169
def scoped(cache = {})
  target_definitions.map do |target_definition|
    cache_key = [specs, target_definition]
    cache[cache_key] ||= begin
      target = PodTarget.new(sandbox, build_type, user_build_configurations, archs, platform, specs,
                             [target_definition], file_accessors, target_definition.label, swift_version)
      scope_dependent_targets = ->(dependent_targets) do
        dependent_targets.flat_map do |pod_target|
          pod_target.scoped(cache).select { |pt| pt.target_definitions == [target_definition] }
        end
      end

      target.dependent_targets_by_config = Hash[dependent_targets_by_config.map { |k, v| [k, scope_dependent_targets[v]] }]
      target.test_dependent_targets_by_spec_name_by_config = Hash[test_dependent_targets_by_spec_name_by_config.map do |spec_name, test_pod_targets_by_config|
        [spec_name, Hash[test_pod_targets_by_config.map { |k, v| [k, scope_dependent_targets[v]] }]]
      end]
      target.app_dependent_targets_by_spec_name_by_config = Hash[app_dependent_targets_by_spec_name_by_config.map do |spec_name, app_pod_targets_by_config|
        [spec_name, Hash[app_pod_targets_by_config.map { |k, v| [k, scope_dependent_targets[v]] }]]
      end]
      target.test_app_hosts_by_spec = Hash[test_app_hosts_by_spec.map do |spec, (app_host_spec, app_pod_target)|
        [spec, [app_host_spec, app_pod_target.scoped(cache).find { |pt| pt.target_definitions == [target_definition] }]]
      end]
      target
    end
  end
end
script_phases() click to toggle source

@return [Array<Hash{Symbol=>String}>] An array of hashes where each hash represents a single script phase.

# File lib/cocoapods/target/pod_target.rb, line 381
def script_phases
  spec_consumers.flat_map(&:script_phases)
end
should_build?() click to toggle source

@return [Boolean] Whether or not this target should be built.

A target should not be built if it has no source files.

# File lib/cocoapods/target/pod_target.rb, line 292
def should_build?
  return @should_build if defined? @should_build
  accessors = file_accessors.select { |fa| fa.spec.library_specification? }
  source_files = accessors.flat_map(&:source_files)
  source_files -= accessors.flat_map(&:headers)
  @should_build = !source_files.empty?
end
spec_consumers() click to toggle source

@return [Array<Specification::Consumer>] the specification consumers for

the target.
# File lib/cocoapods/target/pod_target.rb, line 303
def spec_consumers
  specs.map { |spec| spec.consumer(platform) }
end
spec_label(spec) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 643
def spec_label(spec)
  case spec.spec_type
  when :library then label
  when :test then test_target_label(spec)
  when :app then app_target_label(spec)
  else raise ArgumentError, "Unhandled spec type #{spec.spec_type.inspect} for #{spec.inspect}"
  end
end
Also aliased as: non_library_spec_label
spec_swift_versions() click to toggle source

@return [Array<Version>] the Swift versions supported. Might be empty if the author has not

specified any versions, most likely due to legacy reasons.
# File lib/cocoapods/target/pod_target.rb, line 243
def spec_swift_versions
  root_spec.swift_versions
end
subspec_label(subspec) click to toggle source

@param [Specification] subspec

The subspec to use for producing the label.

@return [String] The derived name of the target.

# File lib/cocoapods/target/pod_target.rb, line 585
def subspec_label(subspec)
  raise ArgumentError, 'Must not be a root spec' if subspec.root?
  subspec.name.split('/')[1..-1].join('-').to_s
end
test_app_hosts_by_spec_name() click to toggle source

@deprecated Use ‘test_app_hosts_by_spec` instead.

@todo Remove in 2.0

@return [Hash{String => (Specification,PodTarget)}] tuples of app specs and pod targets by test spec name.

# File lib/cocoapods/target/pod_target.rb, line 1162
def test_app_hosts_by_spec_name
  Hash[test_app_hosts_by_spec.map do |spec, value|
    [spec.name, value]
  end]
end
test_dependent_targets_by_spec_name=(test_dependent_targets_by_spec_name) click to toggle source

@deprecated

# File lib/cocoapods/target/pod_target.rb, line 72
def test_dependent_targets_by_spec_name=(test_dependent_targets_by_spec_name)
  @test_dependent_targets_by_spec_name = test_dependent_targets_by_spec_name
  @test_dependent_targets_by_spec_name_by_config = Hash[test_dependent_targets_by_spec_name.map do |k, v|
    [k, { :debug => v, :release => v }]
  end]
end
test_dependent_targets_by_spec_name_by_config=(test_dependent_targets_by_spec_name_by_config) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 79
def test_dependent_targets_by_spec_name_by_config=(test_dependent_targets_by_spec_name_by_config)
  @test_dependent_targets_by_spec_name_by_config = test_dependent_targets_by_spec_name_by_config
  @test_dependent_targets_by_spec_name = Hash[test_dependent_targets_by_spec_name_by_config.map do |k, v|
    [k, v.each_value.reduce(Set.new, &:|).to_a]
  end]
end
test_spec_consumers() click to toggle source

@return [Array<Specification::Consumer>] the test specification consumers for

the target.
# File lib/cocoapods/target/pod_target.rb, line 310
def test_spec_consumers
  test_specs.map { |test_spec| test_spec.consumer(platform) }
end
test_target_label(test_spec) click to toggle source

@param [Specification] test_spec

The test spec to use for producing the test label.

@return [String] The derived name of the test target.

# File lib/cocoapods/target/pod_target.rb, line 595
def test_target_label(test_spec)
  "#{label}-#{label_for_test_type(test_spec.test_type)}-#{subspec_label(test_spec)}"
end
user_config_names_by_config_type() click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 1060
def user_config_names_by_config_type
  user_build_configurations.each_with_object({}) do |(user, type), hash|
    hash[type] ||= []
    hash[type] << user
  end.each_value(&:freeze).freeze
end
uses_swift?() click to toggle source

Checks whether the target itself plus its specs uses Swift code. This check excludes source files from non library specs. Note that if a target does not need to be built (no source code), we fallback to check whether it indicates a swift version.

@return [Boolean] Whether the target uses Swift code.

# File lib/cocoapods/target/pod_target.rb, line 328
def uses_swift?
  return @uses_swift if defined? @uses_swift
  @uses_swift = (!should_build? && !spec_swift_versions.empty?) ||
    file_accessors.select { |a| a.spec.library_specification? }.any? do |file_accessor|
      uses_swift_for_spec?(file_accessor.spec)
    end
end
uses_swift_for_spec?(spec) click to toggle source

Checks whether a specification uses Swift or not.

@param [Specification] spec

The spec to query against.

@return [Boolean] Whether the target uses Swift code within the requested non library spec.

# File lib/cocoapods/target/pod_target.rb, line 343
def uses_swift_for_spec?(spec)
  @uses_swift_for_spec_cache ||= {}
  return @uses_swift_for_spec_cache[spec.name] if @uses_swift_for_spec_cache.key?(spec.name)
  @uses_swift_for_spec_cache[spec.name] = begin
    file_accessor = file_accessors.find { |fa| fa.spec == spec }
    raise "[Bug] Unable to find file accessor for spec `#{spec.inspect}` in pod target `#{label}`" unless file_accessor
    file_accessor.source_files.any? { |sf| sf.extname == '.swift' }
  end
end
version() click to toggle source

@return [String] The version associated with this target

# File lib/cocoapods/target/pod_target.rb, line 1002
def version
  version = root_spec.version
  [version.major, version.minor, version.patch].join('.')
end
xcframeworks() click to toggle source

@return [Hash{String=>Array<Xcode::XCFramework>}] The vendored xcframeworks this target

depends upon keyed by spec name.
# File lib/cocoapods/target/pod_target.rb, line 442
def xcframeworks
  @xcframeworks ||= begin
    file_accessors.each_with_object({}) do |file_accessor, hash|
      frameworks = file_accessor.vendored_xcframeworks.map do |framework_path|
        Xcode::XCFramework.new(file_accessor.spec.name, framework_path)
      end
      hash[file_accessor.spec.name] = frameworks
    end
  end
end

Protected Instance Methods

_add_recursive_dependent_targets(set, configuration: nil) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 841
def _add_recursive_dependent_targets(set, configuration: nil)
  if defined?(@recursive_dependent_targets)
    return set.merge(@recursive_dependent_targets[configuration])
  end
  dependent_targets = configuration ? dependent_targets_by_config[configuration] : self.dependent_targets
  dependent_targets.each do |target|
    target._add_recursive_dependent_targets(set, :configuration => configuration) if set.add?(target)
  end

  set
end
uses_modular_headers?(only_if_defines_modules = true) click to toggle source

Returns whether the pod target should use modular headers.

@param [Boolean] only_if_defines_modules

whether the use of modular headers should require the target to define a module

@note This must return false when a pod has a ‘header_mappings_dir` or `header_dir`,

as that allows the spec to customize the header structure, and
therefore it might not be expecting the module name to be prepended
to imports at all.
# File lib/cocoapods/target/pod_target.rb, line 1079
def uses_modular_headers?(only_if_defines_modules = true)
  return false if only_if_defines_modules && !defines_module?
  return @uses_modular_headers if defined? @uses_modular_headers
  @uses_modular_headers = spec_consumers.none?(&:header_mappings_dir) && spec_consumers.none?(&:header_dir)
end

Private Instance Methods

_add_recursive_app_dependent_targets(app_spec, set, configuration: nil) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 922
def _add_recursive_app_dependent_targets(app_spec, set, configuration: nil)
  raise ArgumentError, 'Must give a app spec' unless app_spec
  dependent_targets = configuration ? app_dependent_targets_by_spec_name_by_config[app_spec.name][configuration] : app_dependent_targets_by_spec_name[app_spec.name]
  raise ArgumentError, "Unable to find deps for #{app_spec} for config #{configuration.inspect} #{app_dependent_targets_by_spec_name_by_config.inspect}" unless dependent_targets

  dependent_targets.each do |target|
    target._add_recursive_dependent_targets(set, :configuration => configuration) if set.add?(target)
  end

  set
end
_add_recursive_test_dependent_targets(test_spec, set, configuration: nil) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 875
def _add_recursive_test_dependent_targets(test_spec, set, configuration: nil)
  raise ArgumentError, 'Must give a test spec' unless test_spec
  dependent_targets = configuration ? test_dependent_targets_by_spec_name_by_config[test_spec.name][configuration] : test_dependent_targets_by_spec_name[test_spec.name]
  raise ArgumentError, "Unable to find deps for #{test_spec} for config #{configuration.inspect} (out of #{test_dependent_targets_by_spec_name_by_config.inspect})" unless dependent_targets

  dependent_targets.each do |target|
    target._add_recursive_dependent_targets(set, :configuration => configuration) if set.add?(target)
  end

  set
end
config_variants() click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 1087
def config_variants
  if user_build_configurations.empty?
    %i(debug release)
  else
    user_build_configurations.values.uniq
  end
end
create_app_build_settings_by_config() click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 1109
def create_app_build_settings_by_config
  Hash[app_specs.map do |app_spec|
    [app_spec.name, Hash[config_variants.map do |config|
      [config, BuildSettings::PodTargetSettings.new(self, app_spec, :configuration => config)]
    end]]
  end]
end
create_build_settings() click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 1095
def create_build_settings
  Hash[config_variants.map do |config|
    [config, BuildSettings::PodTargetSettings.new(self, nil, :configuration => config)]
  end]
end
create_test_build_settings_by_config() click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 1101
def create_test_build_settings_by_config
  Hash[test_specs.map do |test_spec|
    [test_spec.name, Hash[config_variants.map do |config|
      [config, BuildSettings::PodTargetSettings.new(self, test_spec, :configuration => config)]
    end]]
  end]
end
header_mappings(file_accessor, headers) click to toggle source

Computes the destination sub-directory in the sandbox

@param [Sandbox::FileAccessor] file_accessor

The consumer file accessor for which the headers need to be
linked.

@param [Array<Pathname>] headers

The absolute paths of the headers which need to be mapped.

@return [Hash{Pathname => Array<Pathname>}] A hash containing the

headers folders as the keys and the absolute paths of the
header files as the values.
# File lib/cocoapods/target/pod_target.rb, line 1130
def header_mappings(file_accessor, headers)
  consumer = file_accessor.spec_consumer
  header_mappings_dir = consumer.header_mappings_dir
  dir = headers_sandbox
  dir += consumer.header_dir if consumer.header_dir

  mappings = {}
  headers.each do |header|
    next if header.to_s.include?('.framework/')

    sub_dir = dir
    if header_mappings_dir
      relative_path = header.relative_path_from(file_accessor.path_list.root + header_mappings_dir)
      sub_dir += relative_path.dirname
    end
    mappings[sub_dir] ||= []
    mappings[sub_dir] << header
  end
  mappings
end