lib/cocoapods-core/specification/dsl.rb
require 'cocoapods-core/specification/dsl/attribute_support'
require 'cocoapods-core/specification/dsl/attribute'
require 'cocoapods-core/specification/dsl/platform_proxy'
module Pod
class Specification
#- NOTE ------------------------------------------------------------------#
# The order of the methods defined in this file and the order of the
# methods is relevant for the documentation generated on the
# CocoaPods/cocoapods.github.com repository.
#-------------------------------------------------------------------------#
# A specification describes a version of Pod library. It includes details
# about where the source should be fetched from, what files to use, the
# build settings to apply, and other general metadata such as its name,
# version, and description.
#
# ---
#
# A stub specification file can be generated by the [pod spec
# create](http://guides.cocoapods.org/terminal/commands.html#pod_spec_create) command.
#
# ---
#
# The specification DSL provides great flexibility and dynamism. Moreover,
# the DSL adopts the
# [convention over configuration](http://en.wikipedia.org/wiki/Convention_over_configuration)
# and thus it can be very simple:
#
# Pod::Spec.new do |spec|
# spec.name = 'Reachability'
# spec.version = '3.1.0'
# spec.license = { :type => 'BSD' }
# spec.homepage = 'https://github.com/tonymillion/Reachability'
# spec.authors = { 'Tony Million' => 'tonymillion@gmail.com' }
# spec.summary = 'ARC and GCD Compatible Reachability Class for iOS and OS X.'
# spec.source = { :git => 'https://github.com/tonymillion/Reachability.git', :tag => 'v3.1.0' }
# spec.source_files = 'Reachability.{h,m}'
# spec.framework = 'SystemConfiguration'
# end
#
# Or it can be quite detailed:
#
# Pod::Spec.new do |spec|
# spec.name = 'Reachability'
# spec.version = '3.1.0'
# spec.license = { :type => 'BSD' }
# spec.homepage = 'https://github.com/tonymillion/Reachability'
# spec.authors = { 'Tony Million' => 'tonymillion@gmail.com' }
# spec.summary = 'ARC and GCD Compatible Reachability Class for iOS and OS X.'
# spec.source = { :git => 'https://github.com/tonymillion/Reachability.git', :tag => 'v3.1.0' }
# spec.module_name = 'Rich'
# spec.swift_version = '4.0'
#
# spec.ios.deployment_target = '9.0'
# spec.osx.deployment_target = '10.10'
#
# spec.source_files = 'Reachability/common/*.swift'
# spec.ios.source_files = 'Reachability/ios/*.swift', 'Reachability/extensions/*.swift'
# spec.osx.source_files = 'Reachability/osx/*.swift'
#
# spec.framework = 'SystemConfiguration'
# spec.ios.framework = 'UIKit'
# spec.osx.framework = 'AppKit'
#
# spec.dependency 'SomeOtherPod'
# end
#
module DSL
extend Pod::Specification::DSL::AttributeSupport
# Deprecations must be required after include AttributeSupport
require 'cocoapods-core/specification/dsl/deprecations'
#-----------------------------------------------------------------------#
# @!group Root specification
#
# A ‘root’ specification stores the information about the specific
# version of a library.
#
# The attributes in this group can only be written to on the ‘root’
# specification, **not** on the ‘sub-specifications’.
#
# ---
#
# The attributes listed in this group are the only one which are
# required by a podspec.
#
# The attributes of the other groups are offered to refine the podspec
# and follow a convention over configuration approach. A root
# specification can describe these attributes either directly of
# through ‘[sub-specifications](#subspec)’.
#-----------------------------------------------------------------------#
# @!method name=(name)
#
# The name of the Pod.
#
# @example
#
# spec.name = 'AFNetworking'
#
# @param [String] name
# the name of the pod.
#
attribute :name,
:required => true,
:inherited => false,
:multi_platform => false
#------------------#
# @!method version=(version)
#
# The version of the Pod. CocoaPods follows
# [semantic versioning](http://semver.org).
#
# @example
#
# spec.version = '0.0.1'
#
# @param [String] version
# the version of the Pod.
#
root_attribute :version,
:required => true
#------------------#
# @!method swift_versions=(version)
#
# The versions of Swift that the specification supports. A version of '4' will be treated as
# '4.0' by CocoaPods and not '4.1' or '4.2'.
#
# **Note** The Swift compiler mostly accepts major versions and sometimes will honor minor versions.
# While CocoaPods allows specifying a minor or patch version it might not be honored fully by the Swift compiler.
#
# @example
#
# spec.swift_versions = ['3.0']
#
# @example
#
# spec.swift_versions = ['3.0', '4.0', '4.2']
#
# @example
#
# spec.swift_version = '3.0'
#
# @example
#
# spec.swift_version = '3.0', '4.0'
#
# @param [String, Array<String>] swift_versions
#
root_attribute :swift_versions,
:container => Array,
:singularize => true
#-----------------------------------------------------------------------#
# @!method cocoapods_version=(cocoapods_version)
#
# The version of CocoaPods that the specification supports.
#
# @example
#
# spec.cocoapods_version = '>= 0.36'
#
# @param [String] cocoapods_version
# the CocoaPods version that the specification supports.
# CocoaPods follows [semantic versioning](http://semver.org).
#
root_attribute :cocoapods_version
#------------------#
# @!method authors=(authors)
#
# The name and email addresses of the library maintainers, not the
# Podspec maintainer.
#
# @example
#
# spec.author = 'Darth Vader'
#
# @example
#
# spec.authors = 'Darth Vader', 'Wookiee'
#
# @example
#
# spec.authors = { 'Darth Vader' => 'darthvader@darkside.com',
# 'Wookiee' => 'wookiee@aggrrttaaggrrt.com' }
#
# @param [String, Hash{String=>String}] authors
# the list of the authors of the library and their emails.
#
root_attribute :authors,
:types => [String, Array, Hash],
:container => Hash,
:required => true,
:singularize => true
#------------------#
# @!method social_media_url=(social_media_url)
#
# The URL for the social media contact of the Pod, CocoaPods web
# services can use this.
#
# For example, the @CocoaPodsFeed notifications will include the
# Twitter handle (shortening the description) if the URL is relative to
# Twitter. This does **not** necessarily have to be a Twitter URL, but
# only those are included in the Twitter @CocoaPodsFeed notifications.
#
# @example
#
# spec.social_media_url = 'https://twitter.com/cocoapods'
#
# @example
#
# spec.social_media_url = 'https://groups.google.com/forum/#!forum/cocoapods'
#
# @param [String] social_media_url
# the social media URL.
#
root_attribute :social_media_url
#------------------#
# The keys accepted by the license attribute.
#
LICENSE_KEYS = [:type, :file, :text].freeze
# @!method license=(license)
#
# The license of the Pod.
#
# ---
#
# Unless the source contains a file named `LICENSE.*` or `LICENCE.*`,
# the path of the license file **or** the integral text of the notice
# commonly used for the license type must be specified.
# If a license file is specified, it either must be without a file
# extensions or be one of `txt`, `md`, or `markdown`.
#
# This information is used by CocoaPods to generate acknowledgement
# files (markdown and plist) which can be used in the acknowledgements
# section of the final application.
#
# @example
#
# spec.license = 'MIT'
#
# @example
#
# spec.license = { :type => 'MIT', :file => 'MIT-LICENSE.txt' }
#
# @example
#
# spec.license = { :type => 'MIT', :text => <<-LICENSE
# Copyright 2012
# Permission is granted to...
# LICENSE
# }
#
# @param [String] license
# The type of the license
#
# @overload license=(license)
# @param [String, Hash{Symbol=>String}] license
# @option license [String] :type license type
# @option license [String] :file file containing full license text. Supports txt, md, and markdown
# @option license [String] :text full license text
#
root_attribute :license,
:container => Hash,
:keys => LICENSE_KEYS,
:required => true
#------------------#
# @!method homepage=(homepage)
#
# The URL of the homepage of the Pod.
#
# @example
#
# spec.homepage = 'http://www.example.com'
#
# @param [String] homepage
# the URL of the homepage of the Pod.
#
root_attribute :homepage,
:required => true
#------------------#
# @!method readme=(readme)
#
# The URL for the README markdown file for this pod version.
#
# @example
#
# spec.readme = 'https://www.example.com/Pod-1.5-README.md'
#
# @param [String] readme
# the readme markdown URL.
#
root_attribute :readme
#------------------#
# @!method changelog=(changelog)
#
# The URL for the CHANGELOG markdown file for this pod version.
#
# @example
#
# spec.changelog = 'https://www.example.com/Pod-1.5-CHANGELOG.md'
#
# @param [String] changelog
# the changelog markdown URL.
#
root_attribute :changelog
#------------------#
# The keys accepted by the hash of the source attribute.
#
SOURCE_KEYS = {
:git => [:tag, :branch, :commit, :submodules].freeze,
:svn => [:folder, :tag, :revision].freeze,
:hg => [:revision].freeze,
:http => [:flatten, :type, :sha256, :sha1, :headers].freeze,
}.freeze
# @!method source=(source)
#
# The location from where the library should be retrieved.
#
# @example Specifying a Git source with a tag. This is how most OSS Podspecs work.
#
# spec.source = { :git => 'https://github.com/AFNetworking/AFNetworking.git',
# :tag => spec.version.to_s }
#
# @example Using a tag prefixed with 'v' and submodules.
#
# spec.source = { :git => 'https://github.com/typhoon-framework/Typhoon.git',
# :tag => "v#{spec.version}", :submodules => true }
#
# @example Using Subversion with a tag.
#
# spec.source = { :svn => 'http://svn.code.sf.net/p/polyclipping/code', :tag => '4.8.8' }
#
# @example Using Mercurial with the same revision as the spec's semantic version string.
#
# spec.source = { :hg => 'https://bitbucket.org/dcutting/hyperbek', :revision => "#{s.version}" }
#
# @example Using HTTP to download a compressed file of the code. It supports zip, tgz, bz2, txz and tar.
#
# spec.source = { :http => 'http://dev.wechatapp.com/download/sdk/WeChat_SDK_iOS_en.zip' }
#
# @example Using HTTP to download a file using a hash to verify the download. It supports sha1 and sha256.
#
# spec.source = { :http => 'http://dev.wechatapp.com/download/sdk/WeChat_SDK_iOS_en.zip',
# :sha1 => '7e21857fe11a511f472cfd7cfa2d979bd7ab7d96' }
#
#
# @overload source=(git)
# @param [Hash] git
# @option git [String] :git git source URI
# @option git [String] :tag version tag
# @option git [Boolean] :submodules Whether to checkout submodules
# @option git [String] :branch branch name
# @option git [String] :commit commit hash
#
# @overload source=(svn)
# @param [Hash] svn
# @option svn [String] :svn svn source URI
# @option svn [String] :tag version tag
# @option svn [String] :folder folder
# @option svn [String] :revision revision
#
# @overload source=(hg)
# @param [Hash] hg
# @option hg [String] :hg mercurial source URI
# @option hg [String] :revision revision
#
# @overload source=(http)
# @param [Hash] http
# @option http [String] :http compressed source URL
# @option http [String] :type file type. Supports zip, tgz, bz2, txz and tar
# @option http [String] :sha1 SHA hash. Supports SHA1 and SHA256
#
root_attribute :source,
:container => Hash,
:keys => SOURCE_KEYS,
:required => true
#------------------#
# @!method summary=(summary)
#
# A short (maximum 140 characters) description of the Pod.
#
# ---
#
# The description should be short, yet informative. It represents the
# tag line of the Pod and there is no need to specify that a Pod is a
# library (they always are).
#
# The summary is expected to be properly capitalised and containing the
# correct punctuation.
#
# @example
#
# spec.summary = 'Computes the meaning of life.'
#
# @param [String] summary
# A short description of the Pod.
#
root_attribute :summary,
:required => true
#------------------#
# @!method description=(description)
#
# A description of the Pod more detailed than the summary.
#
# @example
#
# spec.description = <<-DESC
# Computes the meaning of life.
# Features:
# 1. Is self aware
# ...
# 42. Likes candies.
# DESC
#
# @param [String] description
# A longer description of the Pod.
#
root_attribute :description
#------------------#
# @!method screenshots=(screenshots)
#
# A list of URLs to images showcasing the Pod. Intended for UI oriented
# libraries. CocoaPods recommends the usage of the `gif` format.
#
# @example
#
# spec.screenshot = 'http://dl.dropbox.com/u/378729/MBProgressHUD/1.png'
#
# @example
#
# spec.screenshots = [ 'http://dl.dropbox.com/u/378729/MBProgressHUD/1.png',
# 'http://dl.dropbox.com/u/378729/MBProgressHUD/2.png' ]
#
# @param [String] screenshots
# An URL for the screenshot of the Pod.
#
root_attribute :screenshots,
:singularize => true,
:container => Array
#------------------#
# @!method documentation_url=(documentation_url)
#
# An optional URL for the documentation of the Pod which will be honoured by
# CocoaPods web properties. Leaving it blank will default to a CocoaDocs
# generated URL for your library.
#
# @example
#
# spec.documentation_url = 'http://www.example.com/docs.html'
#
# @param [String] documentation_url
# The link of the web documentation of the Pod.
#
root_attribute :documentation_url
#------------------#
# @!method prepare_command=(command)
#
# A bash script that will be executed after the Pod is downloaded. This
# command can be used to create, delete and modify any file downloaded
# and will be ran before any paths for other file attributes of the
# specification are collected.
#
# This command is executed before the Pod is cleaned and before the
# Pods project is created. The working directory is the root of the
# Pod.
#
# If the pod is installed with the `:path` option this command will not
# be executed.
#
# @example
#
# spec.prepare_command = 'ruby build_files.rb'
#
# @example
#
# spec.prepare_command = <<-CMD
# sed -i 's/MyNameSpacedHeader/Header/g' ./**/*.h
# sed -i 's/MyNameOtherSpacedHeader/OtherHeader/g' ./**/*.h
# CMD
#
# @param [String] command
# the prepare command of the pod.
#
root_attribute :prepare_command
#------------------#
# @!method static_framework=(flag)
#
# Indicates, that if use_frameworks! is specified, the
# pod should include a static library framework.
#
# @example
#
# spec.static_framework = true
#
# @param [Boolean] flag
# Indicates, that if use_frameworks! is specified, the
# pod should include a static library framework.
#
root_attribute :static_framework,
:types => [TrueClass, FalseClass],
:default_value => false
#------------------#
# @!method deprecated=(flag)
#
# Whether the library has been deprecated.
#
# @example
#
# spec.deprecated = true
#
# @param [Boolean] flag
# whether the library has been deprecated.
#
root_attribute :deprecated,
:types => [TrueClass, FalseClass],
:default_value => false
# @!method deprecated_in_favor_of=(deprecated_in_favor_of)
#
# The name of the Pod that this one has been deprecated in favor of.
#
# @example
#
# spec.deprecated_in_favor_of = 'NewMoreAwesomePod'
#
# @param [String] deprecated_in_favor_of
# the name of the Pod that this one has been deprecated in
# favor of.
#
root_attribute :deprecated_in_favor_of
#-----------------------------------------------------------------------#
# @!group Platform
#
# A specification should indicate the platform and the correspondent
# deployment targets on which the library is supported.
#
# If not defined in a subspec the attributes of this group inherit the
# value of the parent.
#-----------------------------------------------------------------------#
# The names of the platforms supported by the specification class.
#
PLATFORMS = [:osx, :ios, :tvos, :visionos, :watchos].freeze
# @todo This currently is not used in the Ruby DSL.
#
attribute :platforms,
:container => Hash,
:keys => PLATFORMS,
:multi_platform => false,
:inherited => true
# The platform on which this Pod is supported. Leaving this blank
# means the Pod is supported on all platforms. When supporting multiple
# platforms you should use deployment_target below instead.
#
# @example
#
# spec.platform = :osx, '10.8'
#
# @example
#
# spec.platform = :ios
#
# @example
#
# spec.platform = :osx
#
# @param [Array<Symbol, String>] args
# A tuple where the first value is the name of the platform,
# (either `:ios` or `:osx`) and the second is the deployment
# target.
#
def platform=(args)
name, deployment_target = args
name = :osx if name.to_s == 'macos'
attributes_hash['platforms'] = if name
{ name.to_s => deployment_target }
else
{}
end
end
#------------------#
# The minimum deployment targets of the supported platforms.
#
# As opposed to the `platform` attribute, the `deployment_target`
# attribute allows to specify multiple platforms on which this pod
# is supported — specifying a different deployment target for each.
#
# @example
#
# spec.ios.deployment_target = '6.0'
#
# @example
#
# spec.osx.deployment_target = '10.8'
#
# @param [String] _args
# The deployment target of the platform.
#
def deployment_target=(*_args)
raise Informative, 'The deployment target can be declared only per ' \
'platform.'
end
#-----------------------------------------------------------------------#
# @!group Build settings
#
# In this group are listed the attributes related to the configuration
# of the build environment that should be used to build the library.
#
# If not defined in a subspec the attributes of this group inherit the
# value of the parent.
#-----------------------------------------------------------------------#
# @todo This currently is not used in the Ruby DSL.
#
attribute :dependencies,
:container => Hash,
:inherited => true
# Any dependency on other Pods or to a ‘sub-specification’.
#
# ---
#
# Dependencies can specify versions requirements. The use of the optimistic
# version indicator `~>` is recommended because it provides good
# control over the version without being too restrictive. For example,
# `~> 1.0.1` is equivalent to `>= 1.0.1` combined with `< 1.1`. Similarly,
# `~> 1.0` will match `1.0`, `1.0.1`, `1.1`, but will not upgrade to `2.0`.
#
# Pods with overly restrictive dependencies limit their compatibility with
# other Pods.
#
# @example
# spec.dependency 'AFNetworking', '~> 1.0'
#
# @example
# spec.dependency 'AFNetworking', '~> 1.0', :configurations => ['Debug']
#
# @example
# spec.dependency 'AFNetworking', '~> 1.0', :configurations => :debug
#
# @example
# spec.dependency 'RestKit/CoreData', '~> 0.20.0'
#
# @example
# spec.ios.dependency 'MBProgressHUD', '~> 0.5'
#
def dependency(*args)
name, *version_requirements = args
if name == self.name
raise Informative, "A specification can't require itself as a " \
'subspec'
end
if @parent
composed_name = ''
@parent.name.split('/').each do |component|
composed_name << component
if name == composed_name
raise Informative, "A subspec can't require one of its " \
'parents specifications'
else
composed_name << '/'
end
end
end
configurations_option = version_requirements.find { |option| option.is_a?(Hash) && option.key?(:configurations) }
whitelisted_configurations = if configurations_option
version_requirements.delete(configurations_option)
Array(configurations_option.delete(:configurations)).map { |c| c.to_s.downcase }
end
dependency_options = version_requirements.reject { |req| req.is_a?(String) }
dependency_options.each do |dependency_option|
if dependency_option.is_a?(Hash)
if !dependency_option[:path].nil?
raise Informative, 'Podspecs cannot specify the source of dependencies. The `:path` option is not supported.'\
' `:path` can be used in the Podfile instead to override global dependencies.'
elsif !dependency_option[:git].nil?
raise Informative, 'Podspecs cannot specify the source of dependencies. The `:git` option is not supported.'\
' `:git` can be used in the Podfile instead to override global dependencies.'
end
end
raise Informative, "Unsupported version requirements. #{version_requirements.inspect} is not valid."
end
attributes_hash['dependencies'] ||= {}
attributes_hash['dependencies'][name] = version_requirements
unless whitelisted_configurations.nil?
if (extras = whitelisted_configurations - %w(debug release)) && !extras.empty?
raise Informative, "Only `Debug` & `Release` are allowed under configurations for dependency on `#{name}`. " \
"Found #{extras.map { |configuration| "`#{configuration}`" }.to_sentence}."
end
attributes_hash['configuration_pod_whitelist'] ||= {}
attributes_hash['configuration_pod_whitelist'][name] = whitelisted_configurations
end
end
def dependency=(args)
joined = args.join('\', \'')
arguments = "\'#{joined}\'"
raise Informative, "Cannot assign value to `dependency`. Did you mean: `dependency #{arguments}`?"
end
#------------------#
# @!method info_plist=(info_plist)
#
# Key-Value pairs to add to the generated `Info.plist`.
#
# The values will be merged with the default values that
# CocoaPods generates, overriding any duplicates.
#
# For library specs, the values will be merged into the generated Info.plist
# for libraries that are integrated using frameworks. It will have no effect
# for static libraries.
#
# Subspecs (other than app and test specs) are not supported.
#
# For app specs, the values will be merged into the application host's `Info.plist`.
#
# For test specs, the values will be merged into the test bundle's `Info.plist`.
#
# @example
#
# spec.info_plist = {
# 'CFBundleIdentifier' => 'com.myorg.MyLib',
# 'MY_VAR' => 'SOME_VALUE'
# }
#
# @param [Hash] info_plist
# The Info.plist values for the Pod.
#
attribute :info_plist,
:container => Hash,
:inherited => false
#------------------#
# @!method requires_arc=(flag)
#
# `requires_arc` allows you to specify which source_files use ARC.
# This can either be the files which support ARC, or true to indicate
# all of the source_files use ARC.
#
# Files which do not use ARC will have the `-fno-objc-arc` compiler
# flag.
#
# The default value of this attribute is `true`.
#
# @example
#
# spec.requires_arc = false
#
# @example
#
# spec.requires_arc = 'Classes/Arc'
#
# @example
#
# spec.requires_arc = ['Classes/*ARC.m', 'Classes/ARC.mm']
#
# @param [Bool, String, Array<String>] flag
# whether the source files require ARC.
#
attribute :requires_arc,
:types => [TrueClass, FalseClass, String, Array],
:file_patterns => true,
:default_value => true,
:inherited => true
#------------------#
# @!method frameworks=(*frameworks)
#
# A list of system frameworks that the user’s target needs to link
# against.
#
# @example
#
# spec.ios.framework = 'CFNetwork'
#
# @example
#
# spec.frameworks = 'QuartzCore', 'CoreData'
#
# @param [String, Array<String>] frameworks
# A list of framework names.
#
attribute :frameworks,
:container => Array,
:singularize => true,
:inherited => true
#------------------#
# @!method weak_frameworks=(*frameworks)
#
# A list of frameworks that the user’s target needs to **weakly** link
# against.
#
# @example
#
# spec.weak_framework = 'Twitter'
#
# @example
#
# spec.weak_frameworks = 'Twitter', 'SafariServices'
#
# @param [String, Array<String>] weak_frameworks
# A list of frameworks names.
#
attribute :weak_frameworks,
:container => Array,
:singularize => true,
:inherited => true
#------------------#
# @!method libraries=(*libraries)
#
# A list of system libraries that the user’s target (application) needs to
# link against.
#
# @example
#
# spec.ios.library = 'xml2'
#
# @example
#
# spec.libraries = 'xml2', 'z'
#
# @param [String, Array<String>] libraries
# A list of library names.
#
attribute :libraries,
:container => Array,
:singularize => true,
:inherited => true
#------------------#
# @!method compiler_flags=(flags)
#
# A list of flags which should be passed to the compiler.
#
# @example
#
# spec.compiler_flags = '-DOS_OBJECT_USE_OBJC=0', '-Wno-format'
#
# @param [String, Array<String>] flags
# A list of flags.
#
attribute :compiler_flags,
:container => Array,
:singularize => true,
:inherited => true
#------------------#
# @!method pod_target_xcconfig=(value)
#
# Any flag to add to the final __private__ pod target xcconfig file.
#
# @example
#
# spec.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-lObjC' }
#
# @param [Hash{String => String}] value
# Key-value pairs representing build settings.
#
attribute :pod_target_xcconfig,
:container => Hash,
:inherited => true
# @!method user_target_xcconfig=(value)
#
# Specifies flags to add to the final aggregate target xcconfig file,
# which propagates to non-overridden and inheriting build settings to
# the integrated user targets.
#
# ---
#
# This attribute is __not recommended__ as Pods should not pollute the
# build settings of the user project and this can cause conflicts.
#
# Multiple definitions for build settings that take multiple values
# will be merged. The user is warned on conflicting definitions for
# custom build settings and build settings that take only one value.
#
# Typically clang compiler flags or precompiler macro definitions go
# in here if they are required when importing the pod in the user
# target. Note that, this influences not only the compiler view of the
# public interface of your pod, but also all other integrated pods
# alongside to yours. You should always prefer [`pod_target_xcconfig`](
# http://guides.cocoapods.org/syntax/podspec.html#pod_target_xcconfig),
# which can contain the same settings, but only influence the
# toolchain when compiling your pod target.
#
# @example
#
# spec.user_target_xcconfig = { 'MY_SUBSPEC' => 'YES' }
#
# @param [Hash{String => String}] value
# Key-value pairs representing build settings.
#
attribute :user_target_xcconfig,
:container => Hash,
:inherited => true
#------------------#
# @!method prefix_header_contents=(content)
#
# Any content to inject in the prefix header of the pod project.
#
# ---
#
# This attribute is __not recommended__ as Pods should not pollute the
# prefix header of other libraries or of the user project.
#
# @example
#
# spec.prefix_header_contents = '#import <UIKit/UIKit.h>'
#
# @example
#
# spec.prefix_header_contents = '#import <UIKit/UIKit.h>', '#import <Foundation/Foundation.h>'
#
# @param [String] content
# The contents of the prefix header.
#
attribute :prefix_header_contents,
:types => [Array, String],
:inherited => true
#------------------#
# @!method prefix_header_file=(path)
#
# A path to a prefix header file to inject in the prefix header of the
# pod project.
# `false` indicates that the default CocoaPods prefix header should not
# be generated.
# `true` is the default and indicates that the default CocoaPods prefix
# header should be generated.
#
# ---
#
# The file path options is __not recommended__ as Pods should not
# pollute the prefix header of other libraries or of the user project.
#
#
# @example
#
# spec.prefix_header_file = 'iphone/include/prefix.pch'
#
# @example
#
# spec.prefix_header_file = false
#
# @param [Bool, String] path
# The path to the prefix header file or whether to disable
# prefix_header generation.
#
attribute :prefix_header_file,
:types => [TrueClass, FalseClass, String],
:inherited => true
#------------------#
# @!method module_name=(name)
#
# The name to use for the framework / clang module which
# will be generated for this specification instead of the
# default (header_dir if set, otherwise the specification
# name).
#
# @example
#
# spec.module_name = 'Three20'
#
# @param [String] name
# the module name.
#
root_attribute :module_name
#------------------#
# @!method header_dir=(dir)
#
# The directory where to store the headers files so they don't break
# includes.
#
# @example
#
# spec.header_dir = 'Three20Core'
#
# @param [String] dir
# the headers directory.
#
attribute :header_dir,
:inherited => true
#------------------#
# @!method header_mappings_dir=(dir)
#
# A directory from where to preserve the folder structure for the
# headers files. If not provided the headers files are flattened.
#
# @example
#
# spec.header_mappings_dir = 'src/include'
#
# @param [String] dir
# the directory from where to preserve the headers namespacing.
#
attribute :header_mappings_dir,
:inherited => true
#------------------#
SCRIPT_PHASE_REQUIRED_KEYS = [:name, :script].freeze
SCRIPT_PHASE_OPTIONAL_KEYS = [:shell_path, :input_files, :output_files, :input_file_lists, :output_file_lists,
:show_env_vars_in_log, :execution_position, :dependency_file, :always_out_of_date].freeze
EXECUTION_POSITION_KEYS = [:before_compile, :after_compile, :before_headers, :after_headers, :any].freeze
ALL_SCRIPT_PHASE_KEYS = (SCRIPT_PHASE_REQUIRED_KEYS + SCRIPT_PHASE_OPTIONAL_KEYS).freeze
# @!method script_phases=(*script_phases)
#
# This attribute allows to define a script phase to execute as part of compilation of the Pod.
# Unlike a prepare command, script phases execute as part of `xcodebuild` they can also utilize all environment
# variables that are set during compilation.
#
# A Pod can provide multiple script phases to execute and they will be added in the order they were
# declared and after taking into consideration their execution position setting.
#
# **Note** In order to provide visibility and awareness of the contents of all script phases,
# a warning will be presented to the user upon installing your pod if it includes any script phases.
#
# @example
#
# spec.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"' }
#
# @example
#
# spec.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"', :execution_position => :before_compile }
#
# @example
#
# spec.script_phase = { :name => 'Hello World', :script => 'puts "Hello World"', :shell_path => '/usr/bin/ruby' }
#
# @example
#
# spec.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"',
# :input_files => ['/path/to/input_file.txt'], :output_files => ['/path/to/output_file.txt']
# }
#
# @example
#
# spec.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"',
# :input_file_lists => ['/path/to/input_files.xcfilelist'], :output_file_lists => ['/path/to/output_files.xcfilelist']
# }
#
# @example
#
# spec.script_phases = [
# { :name => 'Hello World', :script => 'echo "Hello World"' },
# { :name => 'Hello Ruby World', :script => 'puts "Hello World"', :shell_path => '/usr/bin/ruby' },
# ]
#
# @param [Array<Hash{Symbol=>String}>] script_phases
# An array of hashes where each hash represents a single script phase.
#
attribute :script_phases,
:types => [Hash],
:container => Array,
:singularize => true
#-----------------------------------------------------------------------#
# @!group File patterns
#
# Podspecs should be located at the **root** of the repository, and paths
# to files should be specified **relative** to the root of the repository
# as well. File patterns do not support traversing the parent directory ( `..` ).
# File patterns may contain the following wildcard patterns:
#
# ---
#
# ### Pattern: *
#
# Matches any file. Can be restricted by other values in the glob.
#
# * `*` will match all files
# * `c*` will match all files beginning with `c`
# * `*c` will match all files ending with `c`
# * `*c*` will match all files that have `c` in them (including at the
# beginning or end)
#
# Equivalent to `/.*/x` in regexp.
#
# **Note** this will not match Unix-like hidden files (dotfiles). In
# order to include those in the match results, you must use something
# like `{*,.*}`.
#
# ---
#
# ### Pattern: **
#
# Matches directories recursively.
#
# ---
#
# ### Pattern: ?
#
# Matches any one character. Equivalent to `/.{1}/` in regexp.
#
# ---
#
# ### Pattern: [set]
#
# Matches any one character in set.
#
# Behaves exactly like character sets in Regexp, including set negation
# (`[^a-z]`).
#
# ---
#
# ### Pattern: {p,q}
#
# Matches either literal `p` or literal `q`.
#
# Matching literals may be more than one character in length. More than
# two literals may be specified.
#
# Equivalent to pattern alternation in regexp.
#
# ---
#
# ### Pattern: \
#
# Escapes the next meta-character.
#
# ---
#
# ### Examples
#
# Consider these to be evaluated in the source root of
# [JSONKit](https://github.com/johnezang/JSONKit).
#
# "JSONKit.?" #=> ["JSONKit.h", "JSONKit.m"]
# "*.[a-z][a-z]" #=> ["CHANGELOG.md", "README.md"]
# "*.[^m]*" #=> ["JSONKit.h"]
# "*.{h,m}" #=> ["JSONKit.h", "JSONKit.m"]
# "*" #=> ["CHANGELOG.md", "JSONKit.h", "JSONKit.m", "README.md"]
#-----------------------------------------------------------------------#
# @!method source_files=(source_files)
#
# The source files of the Pod.
#
# @example
#
# spec.source_files = 'Classes/**/*.{h,m}'
#
# @example
#
# spec.source_files = 'Classes/**/*.{h,m}', 'More_Classes/**/*.{h,m}'
#
# @param [String, Array<String>] source_files
# the source files of the Pod.
#
attribute :source_files,
:container => Array,
:file_patterns => true
#------------------#
# @!method public_header_files=(public_header_files)
#
# A list of file patterns that should be used as public headers.
#
# ---
#
# These patterns are matched against the source files to include headers
# that will be exposed to the user’s project and
# from which documentation will be generated. When the library is built,
# these headers will appear in the build directory. If no public headers
# are specified then **all** the headers in source_files are considered
# public.
#
# @example
#
# spec.public_header_files = 'Headers/Public/*.h'
#
# @param [String, Array<String>] public_header_files
# the public headers of the Pod.
#
attribute :public_header_files,
:container => Array,
:file_patterns => true
#------------------#
# @!method project_header_files=(project_header_files)
#
# A list of file patterns that should be used to mark project headers.
#
# ---
#
# These patterns are matched against the public headers (or all the
# headers if no public headers have been specified) to exclude those
# headers which should not be exposed to the user project and which
# should not be used to generate the documentation. When the library
# is built, these headers will _not_ appear in the build directory.
#
#
# @example
#
# spec.project_header_files = 'Headers/Project/*.h'
#
# @param [String, Array<String>] project_header_files
# the project headers of the Pod.
#
attribute :project_header_files,
:container => Array,
:file_patterns => true
#------------------#
# @!method private_header_files=(private_header_files)
#
# A list of file patterns that should be used to mark private headers.
#
# ---
#
# These patterns are matched against the public headers (or all the
# headers if no public headers have been specified) to exclude those
# headers which should not be exposed to the user project and which
# should not be used to generate the documentation. When the library
# is built, these headers will appear in the build directory.
#
# Header files that are not listed as neither public nor project or private will
# be treated as private, but in addition will not appear in the build
# directory at all.
#
#
# @example
#
# spec.private_header_files = 'Headers/Private/*.h'
#
# @param [String, Array<String>] private_header_files
# the private headers of the Pod.
#
attribute :private_header_files,
:container => Array,
:file_patterns => true
#------------------#
# @!method vendored_frameworks=(*frameworks)
#
# The paths of the framework bundles that come shipped with the Pod. Supports both `.framework` and `.xcframework` bundles.
# The frameworks will be made available to the Pod and to the consumers of the pod.
#
# @example
#
# spec.ios.vendored_frameworks = 'Frameworks/MyFramework.framework'
#
# @example
#
# spec.vendored_frameworks = 'MyFramework.framework', 'TheirFramework.xcframework'
#
# @param [String, Array<String>] vendored_frameworks
# A list of framework bundles paths.
#
attribute :vendored_frameworks,
:container => Array,
:file_patterns => true,
:singularize => true
#------------------#
# @!method vendored_libraries=(*frameworks)
#
# The paths of the libraries that come shipped with the Pod. The libraries will be available to the Pod and the
# consumers of the Pod.
#
# @example
#
# spec.ios.vendored_library = 'Libraries/libProj4.a'
#
# @example
#
# spec.vendored_libraries = 'libProj4.a', 'libJavaScriptCore.a'
#
# @param [String, Array<String>] vendored_libraries
# A list of library paths.
#
attribute :vendored_libraries,
:container => Array,
:file_patterns => true,
:singularize => true
#------------------#
# The keys accepted by the category attribute for each on demand resource entry.
#
ON_DEMAND_RESOURCES_CATEGORY_KEYS = [:download_on_demand, :prefetched, :initial_install].freeze
# @!method on_demand_resources=(on_demand_resources)
#
# A hash of on demand resources that should be copied into the target bundle. Resources specified here
# will automatically become part of the resources build phase of the target this pod is integrated into.
#
# If no category is specified then `:download_on_demand` is used as the default.
#
# @note
#
# Tags specified by pods are _always_ managed by CocoaPods. If a tag is renamed, changed or deleted then
# CocoaPods will update the tag within the targets the pod was integrated into. It is highly recommended not to
# share the same tags for your project as the ones used by the pods your project consumes.
#
# @example
#
# s.on_demand_resources = {
# 'Tag1' => 'file1.png'
# }
#
# @example
#
# s.on_demand_resources = {
# 'Tag1' => ['file1.png', 'file2.png']
# }
#
# @example
#
# s.on_demand_resources = {
# 'Tag1' => { :paths => ['file1.png', 'file2.png'], :category => :download_on_demand }
# }
#
# @example
#
# s.on_demand_resources = {
# 'Tag1' => { :paths => ['file1.png', 'file2.png'], :category => :initial_install }
# }
#
# @param [Hash{String=>String}, Hash{String=>Array<String>}, Hash{String=>Hash}] on_demand_resources
# The on demand resources shipped with the Pod.
#
attribute :on_demand_resources,
:types => [String, Array, Hash],
:container => Hash,
:file_patterns => true,
:singularize => true
#------------------#
# @!method resource_bundles=(*resource_bundles)
#
# This attribute allows to define the name and the file of the resource
# bundles which should be built for the Pod. They are specified as a
# hash where the keys represent the name of the bundles and the values
# the file patterns that they should include.
#
# For building the Pod as a static library, we strongly **recommend**
# library developers to adopt resource bundles as there can be name
# collisions using the resources attribute.
#
# The names of the bundles should at least include the name of the Pod
# to minimise the chance of name collisions.
#
# To provide different resources per platform namespaced bundles *must*
# be used.
#
# @example
#
# spec.ios.resource_bundle = { 'MapBox' => 'MapView/Map/Resources/*.png' }
#
# @example
#
# spec.resource_bundles = {
# 'MapBox' => ['MapView/Map/Resources/*.png'],
# 'MapBoxOtherResources' => ['MapView/Map/OtherResources/*.png']
# }
#
# @param [Hash{String=>String}, Hash{String=>Array<String>}] resource_bundles
# A hash where the keys are the names of the resource bundles
# and the values are their relative file patterns.
#
attribute :resource_bundles,
:types => [String, Array],
:container => Hash,
:file_patterns => true,
:singularize => true
#------------------#
# @!method resources=(resources)
#
# A list of resources that should be copied into the target bundle.
#
# For building the Pod as a static library, we strongly **recommend**
# library developers to adopt [resource bundles](http://guides.cocoapods.org/syntax/podspec.html#resource_bundles)
# as there can be name collisions using the resources attribute.
# Moreover, resources specified with this attribute are copied
# directly to the client target and therefore they are not
# optimised by Xcode.
#
# @example
#
# spec.resource = 'Resources/HockeySDK.bundle'
#
# @example
#
# spec.resources = ['Images/*.png', 'Sounds/*']
#
# @param [String, Array<String>] resources
# The resources shipped with the Pod.
#
attribute :resources,
:container => Array,
:file_patterns => true,
:singularize => true
#------------------#
# @!method exclude_files=(exclude_files)
#
# A list of file patterns that should be excluded from the other
# file patterns.
#
# @example
#
# spec.ios.exclude_files = 'Classes/osx'
#
# @example
#
# spec.exclude_files = 'Classes/**/unused.{h,m}'
#
# @param [String, Array<String>] exclude_files
# the file patterns that the Pod should ignore.
#
attribute :exclude_files,
:container => Array,
:file_patterns => true
#------------------#
# @!method preserve_paths=(preserve_paths)
#
# Any file that should **not** be removed after being downloaded.
#
# ---
#
# By default, CocoaPods removes all files that are not matched by any
# of the other file pattern.
#
# @example
#
# spec.preserve_path = 'IMPORTANT.txt'
#
# @example
#
# spec.preserve_paths = 'Frameworks/*.framework'
#
# @param [String, Array<String>] preserve_paths
# the paths that should be not cleaned.
#
attribute :preserve_paths,
:container => Array,
:file_patterns => true,
:singularize => true
#------------------#
# @!method module_map=(module_map)
#
# The module map file that should be used when this pod is integrated as
# a framework.
#
# `false` indicates that the default CocoaPods `modulemap` file should not
# be generated.
#
# `true` is the default and indicates that the default CocoaPods
# `modulemap` file should be generated.
#
# ---
#
# By default, CocoaPods creates a module map file based upon the public
# headers in a specification.
#
# @example
#
# spec.module_map = 'source/module.modulemap'
#
# @example
#
# spec.module_map = false
#
# @param [String, Bool] module_map
# the path to the module map file that should be used
# or whether to disable module_map generation.
#
attribute :module_map,
:types => [TrueClass, FalseClass, String],
:root_only => true
#-----------------------------------------------------------------------#
# @!group Subspecs
#
# A library can specify a dependency on either another library, a
# subspec of another library, or a subspec of itself.
#-----------------------------------------------------------------------#
# Represents specification for a module of the library.
#
# ---
#
# Subspecs participate on a dual hierarchy.
#
# On one side, a specification automatically inherits as a dependency all
# it children ‘sub-specifications’ (unless a default subspec is
# specified).
#
# On the other side, a ‘sub-specification’ inherits the value of the
# attributes of the parents so common values for attributes can be
# specified in the ancestors.
#
# Although it sounds complicated in practice it means that subspecs in
# general do what you would expect:
#
# pod 'ShareKit', '2.0'
#
# Installs ShareKit with all the sharers like `ShareKit/Evernote`,
# `ShareKit/Facebook`, etc, as they are defined as subspecs.
#
# pod 'ShareKit/Twitter', '2.0'
# pod 'ShareKit/Pinboard', '2.0'
#
# Installs ShareKit with only the source files for `ShareKit/Twitter`,
# `ShareKit/Pinboard`. Note that, in this case, the ‘sub-specifications’
# to compile need the source files, the dependencies, and the other
# attributes defined by the root specification. CocoaPods is smart enough
# to handle any issues arising from duplicate attributes.
#
# @example Subspecs with different source files.
#
# subspec 'Twitter' do |sp|
# sp.source_files = 'Classes/Twitter'
# end
#
# subspec 'Pinboard' do |sp|
# sp.source_files = 'Classes/Pinboard'
# end
#
# @example Subspecs referencing dependencies to other subspecs.
#
# Pod::Spec.new do |s|
# s.name = 'RestKit'
#
# s.subspec 'Core' do |cs|
# cs.dependency 'RestKit/ObjectMapping'
# cs.dependency 'RestKit/Network'
# cs.dependency 'RestKit/CoreData'
# end
#
# s.subspec 'ObjectMapping' do |os|
# end
# end
#
# @example Nested subspecs.
#
# Pod::Spec.new do |s|
# s.name = 'Root'
#
# s.subspec 'Level_1' do |sp|
# sp.subspec 'Level_2' do |ssp|
# end
# end
# end
#
def subspec(name, &block)
subspec = Specification.new(self, name, &block)
@subspecs << subspec
subspec
end
# The list of the test types currently supported.
#
SUPPORTED_TEST_TYPES = [:unit, :ui].freeze
# The test type this specification supports. This only applies to test specifications.
#
# ---
#
# @example
#
# test_spec.test_type = :unit
#
# @example
#
# test_spec.test_type = 'unit'
#
# @param [Symbol, String] type
# The test type to use.
#
attribute :test_type,
:types => [Symbol, String],
:multi_platform => false,
:spec_types => [:test]
# @!method requires_app_host=(flag)
#
# Whether a test specification requires an app host to run tests. This only applies to test specifications.
#
# @example
#
# test_spec.requires_app_host = true
#
# @param [Boolean] flag
# whether a test specification requires an app host to run tests.
#
attribute :requires_app_host,
:types => [TrueClass, FalseClass],
:default_value => false,
:spec_types => [:test]
# @!method app_host_name=(name)
#
# The app specification to use as an app host, if necessary.
#
# @note
#
# You must depend on that app spec using `test_spec.dependency 'PodName'`.
#
# @example
#
# Pod::Spec.new do |spec|
# spec.name = 'NSAttributedString+CCLFormat'
#
# spec.test_spec do |test_spec|
# test_spec.source_files = 'NSAttributedString+CCLFormatTests.m'
# test_spec.requires_app_host = true
# test_spec.app_host_name = 'NSAttributedString+CCLFormat/App'
# test_spec.dependency 'NSAttributedString+CCLFormat/App'
# end
#
# spec.app_spec 'App' do |app_spec|
# app_spec.source_files = 'NSAttributedString+CCLFormat.m'
# app_spec.dependency 'AFNetworking'
# end
# end
#
# @param [String] name
# The app specification to use as an app host, if necessary.
#
attribute :app_host_name,
:types => [String],
:spec_types => [:test]
SCHEME_KEYS = [:launch_arguments, :environment_variables, :code_coverage, :parallelizable, :build_configurations].freeze
# @!method scheme=(flag)
#
# Specifies the scheme configuration to be used for this specification.
#
# ---
#
# @example
#
# spec.scheme = { :launch_arguments => ['Arg1'] }
#
# @example
#
# spec.scheme = { :launch_arguments => ['Arg1', 'Arg2'], :environment_variables => { 'Key1' => 'Val1'} }
#
# @param [Hash] scheme
# the scheme configuration to be used for this specification.
#
attribute :scheme,
:types => [Hash],
:container => Hash,
:keys => SCHEME_KEYS
# Represents a test specification for the library. Here you can place all
# your tests for your podspec along with the test dependencies.
#
# ---
#
# @example
#
# Pod::Spec.new do |spec|
# spec.name = 'NSAttributedString+CCLFormat'
#
# spec.test_spec do |test_spec|
# test_spec.source_files = 'NSAttributedString+CCLFormatTests.m'
# test_spec.dependency 'Expecta'
# end
# end
#
def test_spec(name = 'Tests', &block)
subspec = Specification.new(self, name, true, &block)
@subspecs << subspec
subspec
end
# Represents an app specification for the library. Here you can place all
# your app source files for your podspec along with the app dependencies.
#
# ---
#
# @example
#
# Pod::Spec.new do |spec|
# spec.name = 'NSAttributedString+CCLFormat'
#
# spec.app_spec do |app_spec|
# app_spec.source_files = 'NSAttributedString+CCLFormat.m'
# app_spec.dependency 'AFNetworking'
# end
# end
#
def app_spec(name = 'App', &block)
appspec = Specification.new(self, name, :app_specification => true, &block)
@subspecs << appspec
appspec
end
#------------------#
# @!method default_subspecs=(subspec_array)
#
# An array of subspecs names that should be used as preferred dependency.
# If not specified, a specification requires all of its subspecs as
# dependencies.
#
# You may use the value `:none` to specify that none of the subspecs are
# required to compile this pod and that all subspecs are optional.
#
# ---
#
# A Pod should make available the full library by default. Users can
# fine tune their dependencies, and exclude unneeded subspecs, once
# their requirements are known. Therefore, this attribute is rarely
# needed. It is intended to be used to select a default if there are
# ‘sub-specifications’ which provide alternative incompatible
# implementations, or to exclude modules rarely needed (especially if
# they trigger dependencies on other libraries).
#
# @example
#
# spec.default_subspec = 'Core'
#
# @example
#
# spec.default_subspecs = 'Core', 'UI'
#
# @example
#
# spec.default_subspecs = :none
#
# @param [Array<String>, String, Symbol] subspec_names
# An array of subspec names that should be inherited as
# dependency.
#
root_attribute :default_subspecs,
:container => Array,
:types => [Array, String, Symbol],
:singularize => true
#-----------------------------------------------------------------------#
# @!group Multi-Platform support
#
# A specification can store values which are specific to only one
# platform.
#
# ---
#
# For example one might want to store resources which are specific to
# only iOS projects.
#
# spec.resources = 'Resources/**/*.png'
# spec.ios.resources = 'Resources_ios/**/*.png'
#-----------------------------------------------------------------------#
# Provides support for specifying iOS attributes.
#
# @example
# spec.ios.source_files = 'Classes/ios/**/*.{h,m}'
#
# @return [PlatformProxy] the proxy that will set the attributes.
#
def ios
PlatformProxy.new(self, :ios)
end
# Provides support for specifying OS X attributes.
#
# @example
# spec.osx.source_files = 'Classes/osx/**/*.{h,m}'
#
# @return [PlatformProxy] the proxy that will set the attributes.
#
def osx
PlatformProxy.new(self, :osx)
end
alias macos osx
# Provides support for specifying tvOS attributes.
#
# @example
# spec.tvos.source_files = 'Classes/tvos/**/*.{h,m}'
#
# @return [PlatformProxy] the proxy that will set the attributes.
#
def tvos
PlatformProxy.new(self, :tvos)
end
# Provides support for specifying visionOS attributes.
#
# @example
# spec.visionos.source_files = 'Classes/visionos/**/*.{h,m}'
#
# @return [PlatformProxy] the proxy that will set the attributes.
#
def visionos
PlatformProxy.new(self, :visionos)
end
# Provides support for specifying watchOS attributes.
#
# @example
# spec.watchos.source_files = 'Classes/watchos/**/*.{h,m}'
#
# @return [PlatformProxy] the proxy that will set the attributes.
#
def watchos
PlatformProxy.new(self, :watchos)
end
end
end
end