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

build_headers[R]

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

dependent_targets[RW]

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

upon.
file_accessors[R]

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

specifications of this target.
non_test_specs[R]

@return [Array<Specification>] All of the specs within this target that are not test 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.

target_definitions[R]

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

that generated this target.
test_dependent_targets_by_spec_name[RW]

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

test_specs[R]

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

Subset of #specs.

Public Class Methods

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

Initialize a new instance

@param [Sandbox] sandbox @see Target#sandbox @param [Boolean] host_requires_frameworks @see Target#host_requires_frameworks @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<TargetDefinition>] target_definitions @see target_definitions @param [Array<Sandbox::FileAccessor>] file_accessors @see file_accessors @param [String] scope_suffix @see scope_suffix

Calls superclass method Pod::Target::new
# File lib/cocoapods/target/pod_target.rb, line 61
def initialize(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs,
               target_definitions, file_accessors = [], scope_suffix = nil)
  super(sandbox, host_requires_frameworks, 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 only abstract TargetDefinitions!" if target_definitions.all?(&:abstract?)
  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
  @test_specs, @non_test_specs = @specs.partition(&:test_specification?)
  @build_headers = Sandbox::HeadersStore.new(sandbox, 'Private', :private)
  @dependent_targets = []
  @test_dependent_targets_by_spec_name = {}
  @build_config_cache = {}
end

Public Instance Methods

all_dependent_targets() click to toggle source

@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 456
def all_dependent_targets
  [self, *recursive_dependent_targets, *recursive_test_dependent_targets].uniq
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 502
def build_product_path(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE)
  "#{configuration_build_dir(dir)}/#{product_name}"
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 493
def configuration_build_dir(dir = BuildSettings::CONFIGURATION_BUILD_DIR_VARIABLE)
  "#{dir}/#{label}"
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 225
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 231
def contains_test_specifications?
  !test_specs.empty?
end
copy_resources_script_path_for_test_type(test_type) click to toggle source

@param [Symbol] test_type

The test type this embed frameworks script path is for.

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

# File lib/cocoapods/target/pod_target.rb, line 373
def copy_resources_script_path_for_test_type(test_type)
  support_files_dir + "#{test_target_label(test_type)}-resources.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 209
def defines_module?
  return @defines_module if defined?(@defines_module)
  return @defines_module = true if uses_swift? || requires_frameworks?
  return @defines_module = true if target_definitions.all? { |td| td.build_pod_as_module?(pod_name) }

  @defines_module = non_test_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 413
def dependencies
  spec_consumers.flat_map do |consumer|
    consumer.dependencies.map { |dep| Specification.root_name(dep.name) }
  end.uniq
end
embed_frameworks_script_path_for_test_type(test_type) click to toggle source

@param [Symbol] test_type

The test type this embed frameworks script path is for.

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

# File lib/cocoapods/target/pod_target.rb, line 382
def embed_frameworks_script_path_for_test_type(test_type)
  support_files_dir + "#{test_target_label(test_type)}-frameworks.sh"
end
framework_paths() click to toggle source

@return [Hash{String=>Array<Hash{Symbol=>String}>}] 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 245
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 = { :name => framework_path.basename.to_s,
                      :input_path => "${PODS_ROOT}/#{relative_path_to_sandbox}",
                      :output_path => "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/#{framework_path.basename}" }
        # 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}")
        if dsym_path.exist?
          framework[:dsym_name] = dsym_name
          framework[:dsym_input_path] = "${PODS_ROOT}/#{relative_path_to_sandbox}.dSYM"
          framework[:dsym_output_path] = "${DWARF_DSYM_FOLDER_PATH}/#{dsym_name}"
        end
        frameworks << framework
      end
      if !file_accessor.spec.test_specification? && should_build? && requires_frameworks? && !static_framework?
        frameworks << { :name => product_name,
                        :input_path => build_product_path('${BUILT_PRODUCTS_DIR}'),
                        :output_path => "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/#{product_name}" }
      end
      hash[file_accessor.spec.name] = frameworks
    end
  end
end
header_search_paths(include_test_dependent_targets = false) click to toggle source

@param [Boolean] include_test_dependent_targets

whether to include header search paths for test dependent targets

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

# File lib/cocoapods/target/pod_target.rb, line 524
def header_search_paths(include_test_dependent_targets = false)
  header_search_paths = []
  header_search_paths.concat(build_headers.search_paths(platform, nil, false))
  header_search_paths.concat(sandbox.public_headers.search_paths(platform, pod_name, uses_modular_headers?))
  dependent_targets = recursive_dependent_targets
  dependent_targets += recursive_test_dependent_targets if include_test_dependent_targets
  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
info_plist_path_for_test_type(test_type) click to toggle source

@param [Symbol] test_type

The test type this Info.plist path is for.

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

# File lib/cocoapods/target/pod_target.rb, line 391
def info_plist_path_for_test_type(test_type)
  support_files_dir + "#{test_target_label(test_type)}-Info.plist"
end
inhibit_warnings?() click to toggle source

Checks if warnings should be inhibited for this pod.

@return [Bool]

# File lib/cocoapods/target/pod_target.rb, line 464
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(&:label)}), which contain different " \
      'settings to inhibit warnings. CocoaPods does not currently ' \
      'support different settings and will fall back to your preference ' \
      'set in the root target definition.'
    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 107
def label
  if scope_suffix.nil? || scope_suffix[0] == '.'
    "#{root_spec.name}#{scope_suffix}"
  else
    "#{root_spec.name}-#{scope_suffix}"
  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 339
def module_map_path
  basename = "#{label}.modulemap"
  if requires_frameworks?
    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
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 332
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 508
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 131
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 397
def prefix_header_path
  support_files_dir + "#{label}-prefix.pch"
end
prefix_header_path_for_test_type(test_type) click to toggle source

@param [Symbol] test_type

The test type prefix header path is for.

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

# File lib/cocoapods/target/pod_target.rb, line 406
def prefix_header_path_for_test_type(test_type)
  support_files_dir + "#{test_target_label(test_type)}-prefix.pch"
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 139
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 299
def product_type_for_test_type(test_type)
  case test_type
  when :unit
    :unit_test_bundle
  else
    raise Informative, "Unknown test type `#{test_type}`."
  end
end
recursive_dependent_targets() click to toggle source

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

dependency upon.
# File lib/cocoapods/target/pod_target.rb, line 422
def recursive_dependent_targets
  @recursive_dependent_targets ||= _add_recursive_dependent_targets(Set.new).delete(self).to_a
end
recursive_test_dependent_targets() click to toggle source

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

test dependency upon.
# File lib/cocoapods/target/pod_target.rb, line 438
def recursive_test_dependent_targets
  @recursive_test_dependent_targets ||= _add_recursive_test_dependent_targets(Set.new).to_a
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.
# File lib/cocoapods/target/pod_target.rb, line 278
def resource_paths
  @resource_paths ||= begin
    file_accessors.each_with_object({}) do |file_accessor, hash|
      resource_paths = file_accessor.resources.map { |res| "${PODS_ROOT}/#{res.relative_path_from(sandbox.project.path.dirname)}" }
      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
    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 355
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 326
def root_spec
  specs.first.root
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 86
def scoped(cache = {})
  target_definitions.map do |target_definition|
    cache_key = [specs, target_definition]
    if cache[cache_key]
      cache[cache_key]
    else
      target = PodTarget.new(sandbox, host_requires_frameworks, user_build_configurations, archs, platform, specs, [target_definition], file_accessors, target_definition.label)
      target.dependent_targets = dependent_targets.flat_map { |pt| pt.scoped(cache) }.select { |pt| pt.target_definitions == [target_definition] }
      target.test_dependent_targets_by_spec_name = Hash[test_dependent_targets_by_spec_name.map do |spec_name, test_pod_targets|
        scoped_test_pod_targets = test_pod_targets.flat_map do |test_pod_target|
          test_pod_target.scoped(cache).select { |pt| pt.target_definitions == [target_definition] }
        end
        [spec_name, scoped_test_pod_targets]
      end]
      cache[cache_key] = 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 219
def script_phases
  spec_consumers.flat_map(&:script_phases)
end
should_build?() click to toggle source

@return [Bool] 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 147
def should_build?
  return @should_build if defined? @should_build
  accessors = file_accessors.reject { |fa| fa.spec.test_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 158
def spec_consumers
  specs.map { |spec| spec.consumer(platform) }
end
spec_swift_version() click to toggle source

@return [String] the Swift version within the root spec. Might be `nil` if none is set.

# File lib/cocoapods/target/pod_target.rb, line 125
def spec_swift_version
  root_spec.swift_version
end
static_framework?() click to toggle source

@return [Boolean] Whether the target should build a static framework.

# File lib/cocoapods/target/pod_target.rb, line 199
def static_framework?
  requires_frameworks? && root_spec.static_framework
end
supported_test_types() click to toggle source

@return [Array<Symbol>] All of the test supported types within this target.

# File lib/cocoapods/target/pod_target.rb, line 237
def supported_test_types
  test_specs.map(&:test_type).uniq
end
swift_version() click to toggle source

@return [String] the Swift version for the target. If the pod author has provided a swift version

then that is the one returned, otherwise the Swift version is determined by the user
targets that include this pod target.
# File lib/cocoapods/target/pod_target.rb, line 119
def swift_version
  spec_swift_version || target_definitions.map(&:swift_version).compact.uniq.first
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 165
def test_spec_consumers
  test_specs.map { |test_spec| test_spec.consumer(platform) }
end
test_target_label(test_type) click to toggle source

@param [Symbol] test_type

The test type to use for producing the test label.

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

# File lib/cocoapods/target/pod_target.rb, line 364
def test_target_label(test_type)
  "#{label}-#{test_type.capitalize}-Tests"
end
test_type_for_product_type(product_type) click to toggle source

Returns the corresponding test type given the product type.

@param [Symbol] product_type

The product type to map to a test type.

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

# File lib/cocoapods/target/pod_target.rb, line 315
def test_type_for_product_type(product_type)
  case product_type
  when :unit_test_bundle
    :unit
  else
    raise Informative, "Unknown product type `#{product_type}`."
  end
end
uses_swift?() click to toggle source

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

# File lib/cocoapods/target/pod_target.rb, line 171
def uses_swift?
  return @uses_swift if defined? @uses_swift
  @uses_swift = begin
    file_accessors.reject { |a| a.spec.test_specification? }.any? do |file_accessor|
      file_accessor.source_files.any? { |sf| sf.extname == '.swift' }
    end
  end
end
uses_swift_for_test_type?(test_type) click to toggle source

Checks whether a particular test type uses Swift or not.

@param [Symbol] test_type

The test type to check whether it uses Swift or not.

@return [Boolean] Whether the target uses Swift code in the specified test type.

# File lib/cocoapods/target/pod_target.rb, line 187
def uses_swift_for_test_type?(test_type)
  @uses_swift_for_test_type ||= {}
  return @uses_swift_for_test_type[test_type] if @uses_swift_for_test_type.key?(test_type)
  @uses_swift_for_test_type[test_type] = begin
    file_accessors.select { |a| a.spec.test_specification? && a.spec.test_type == test_type }.any? do |file_accessor|
      file_accessor.source_files.any? { |sf| sf.extname == '.swift' }
    end
  end
end
version() click to toggle source

@return [String] The version associated with this target

# File lib/cocoapods/target/pod_target.rb, line 514
def version
  version = root_spec.version
  [version.major, version.minor, version.patch].join('.')
end

Protected Instance Methods

_add_recursive_dependent_targets(set) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 426
def _add_recursive_dependent_targets(set)
  dependent_targets.each do |target|
    target._add_recursive_dependent_targets(set) 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 548
def uses_modular_headers?(only_if_defines_modules = true)
  return false if only_if_defines_modules && !defines_module?
  spec_consumers.none?(&:header_mappings_dir) && spec_consumers.none?(&:header_dir)
end

Private Instance Methods

_add_recursive_test_dependent_targets(set) click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 442
def _add_recursive_test_dependent_targets(set)
  test_dependent_targets_by_spec_name.each_value do |dependent_targets|
    dependent_targets.each do |target|
      target._add_recursive_dependent_targets(set) if set.add?(target)
    end
  end

  set
end
create_build_settings() click to toggle source
# File lib/cocoapods/target/pod_target.rb, line 555
def create_build_settings
  BuildSettings::PodTargetSettings.new(self)
end