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
@return [Hash{String=>Array<PodTarget>}] all target dependencies by app spec name.
@return [Hash{String => BuildSettings}] the app spec build settings for this target.
@return [Array<Specification>] All of the specs within this target that are app specs.
Subset of #specs.
@return [HeadersStore] the header directory for the target.
@return [Array<PodTarget>] the targets that this target has a dependency
upon.
@return [Array<Sandbox::FileAccessor>] the file accessors for the
specifications of this target.
@return [Array<Specification>] All of the specs within this target that are library specs.
Subset of #specs.
@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.
@return [Array<Specification>] the spec, subspecs and test specs of the target.
@return [String] the Swift version for this target.
@return [Array<TargetDefinition>] the target definitions of the Podfile
that generated this target.
@return [Hash{Specification => (Specification
,PodTarget)}] tuples of app specs and pod targets by test spec.
@return [Hash{String=>Array<PodTarget>}] all target dependencies by test spec name.
@return [Hash{String => BuildSettings}] the test spec build settings for this target.
@return [Array<Specification>] All of the test specs within this target.
Subset of #specs.
Public Class Methods
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
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
@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
@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
# 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
@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
@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
@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
@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
@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
# 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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
# 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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
@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
Checks if warnings should be inhibited for this pod.
@return [Bool]
# 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
@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
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
@return [Pathname] the absolute path of the LLVM module map file that
defines the module structure for the compiler.
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
@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
@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
@return [Podfile] The podfile which declares the dependency.
# File lib/cocoapods/target/pod_target.rb, line 249 def podfile target_definitions.first.podfile end
@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
@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
@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
@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
@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
@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
@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
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
@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
@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
@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
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
@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
@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
@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
@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
@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
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
@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
@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 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
@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
# 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
@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
@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
@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
@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
# 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
@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
@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
# 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
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
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
@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
@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
# 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
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
# 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
# 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
# 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
# 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
# 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
# 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
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