本文为博主原创文章,未经博主允许不得转载
上一次,我们尝试建立了自己的私有pod库,但是例子相对简单,这次我们详细的解析一下podspec的使用。
一、官方文档地址:
首先,官方文档最为官方:
https://guides.cocoapods.org/syntax/podspec.html
二、spec是什么
spec描述了一个pod库的版本。它包括有关应从何处获取源、使用什么文件、要应用的构建设置以及其他一般元数据(如其名称、版本和描述)的详细信息。
可以通过pod spec create命令创建。
可以简单到:
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
也可以稍微复杂一点:
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
三、Root specification
root spec存储关于库的特定版本的信息,一些属性只能写在root上,而一些细节规范则可以只写在sub spec上面,用于约束细节。
如下为root spec才可以使用的字段(required为必须存在的字段):
- name(required)
- version(required)
pod的版本信息,遵循 semantic versioning.规则,具体规则可参考https://semver.org - swift_version
- authors(required)
- social_media_url
社交联系url - license(required)
- homepage(required)
- source(required)
- summary(required)
- description
- screenshots
- documentation_url
- prepare_command
在pod被清理之前和pod项目被创建之前执行的命令。从pod的根目录作为相对路径 - static_framework
如果用了use_frameworks!,则应该声明为true - deprecated
是否library被弃用 - deprecated_in_favor_of
被弃用库的名字
四、Platform
- platform
指定支持的平台和版本,不写则默认支持所有的平台,如果支持多个平台,则使用下面的deployment_target定义,example:
spec.platform = :osx, '10.8'
spec.platform = :ios
spec.platform = :osx
- deployment_target
支持的平台的最小目标,和platform字段相反,他分别指定了不同平台的支持版本
spec.ios.deployment_target = '6.0'
spec.osx.deployment_target = '10.8'
五、Build settings
在这个组中列出了与构建库的配置相关的属性,这些构建环境应该用于构建库。
如果未在子规范中定义,则该组的属性继承父值。
- dependency
可以依赖其他的pod库,或者一个subspec,可以是自己建立的subspec
spec.dependency 'AFNetworking', '~> 1.0'
spec.dependency 'RestKit/CoreData', '~> 0.20.0'
spec.ios.dependency 'MBProgressHUD', '~> 0.5'
spec.dependency '自己的主spec/subspec'
- requires_arc
设置是否使用ARC,哪些文件使用ARC,默认是true
spec.requires_arc = false
spec.requires_arc = 'Classes/Arc'
spec.requires_arc = ['Classes/*ARC.m', 'Classes/ARC.mm']
如果我们想指定某些文件不使用ARC,我们可以将这些文件放在一个spec.requires_arc = false的subspec里面:
non_arc_files = 'xxx/xxx.{h,m}'
s.subspec 'no-arc' do |mrc|
mrc.source_files = non_arc_files
mrc.requires_arc = false
end
- frameworks
用户的target需要用到的framework
spec.ios.framework = 'CFNetwork'
spec.frameworks = 'QuartzCore', 'CoreData'
- weak_frameworks
弱连接的framework
spec.weak_framework = 'Twitter'
spec.weak_frameworks = 'Twitter', 'SafariServices'
- libraries
应用或者target需要使用的library,注意名字为去掉前面lib和后面的类型字段剩下的部分:
spec.ios.library = 'xml2'
spec.libraries = 'xml2', 'z'
- compiler_flags
编译器的flags
spec.compiler_flags = '-DOS_OBJECT_USE_OBJC=0', '-Wno-format'
- pod_target_xcconfig
添加到最终私有pod目标xcconfig文件的flag
spec.pod_target_xcconfig = { 'OTHER_LDFLAGS' => '-lObjC' }
- user_target_xcconfig
用户的target设置,不建议使用,因为pod的设置不应该污染用户的设置,这可能会导致设置冲突,并且影响其他的pod设置
spec.user_target_xcconfig = { 'MY_SUBSPEC' => 'YES' }
- prefix_header_contents
在pod项目的头文件中注入的任何内容。
不推荐使用此属性,因为pod不应该污染其他库或用户项目的头文件。
spec.prefix_header_contents = '#import <UIKit/UIKit.h>'
spec.prefix_header_contents = '#import <UIKit/UIKit.h>', '#import <Foundation/Foundation.h>'
- prefix_header_file
在pod项目的头文件中注入头文件的路径。false指示不应生成默认的CocoaPods头文件。默认为true,并指示应该生成默认的CocoaPods头文件。
不推荐文件路径选项,因为POD不应该污染其他库或用户项目的前缀标头。
spec.prefix_header_file = 'iphone/include/prefix.pch'
spec.prefix_header_file = false
- module_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).
spec.module_name = 'Three20'
- header_dir 没用过,直接给官方解释
The directory where to store the headers files so they don’t break includes.
spec.header_dir = 'Three20Core'
- header_mappings_dir 没用过,直接给官方解释
A directory from where to preserve the folder structure for the headers files. If not provided the headers files are flattened.
spec.header_mappings_dir = 'src/include'
六、文件模式
podspec应位于存储库的根目录中,并且应针对存储库的根指定文件路径。文件模式不支持遍历父目录(…)文件模式可以包含以下通配符模式:
- 符号:
*
*
匹配所有文件c*
匹配所有c开头的文件*c
匹配所有c结尾的文件*c*
匹配所有包含c的文件
- 符号:
**
递归路径 - 符号:
?
匹配任意一个字符 - 符号:
[set]
匹配任意set中的一个字符,和正则规则类似,例如否集[^a-z]
- 符号:
{p,q}
包含p和q的集合 - 符号:
\
跳出下一个元字符。
例如在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"]
(1)source_files
pod的源文件:
spec.source_files = 'Classes/**/*.{h,m}'
spec.source_files = 'Classes/**/*.{h,m}', 'More_Classes/**/*.{h,m}'
(2)public_header_files
应用作公共头文件的的文件模式列表。
这些头文件将暴露给用户的工程,当这个库被建立的时候,这些文件也将出现在build目录下,如果没有设定头文件,那么所有source的头文件都将被暴露。
spec.public_header_files = 'Headers/Public/*.h'
(3)private_header_files
私有的头文件。
如果没有设定公有头文件,所有文件被暴露的情况下,设定私有头文件,则这部分文件将不会暴露出来。
没有被私有和公有头文件设定的文件,将被视作私有的。
spec.private_header_files = 'Headers/Private/*.h'
(4)vendored_frameworks
路径下的framework将与pod一同使用
spec.ios.vendored_frameworks = 'Frameworks/MyFramework.framework'
spec.vendored_frameworks = 'MyFramework.framework', 'TheirFramework.framework'
(5)vendored_libraries
路径下的Library将与pod一同使用
spec.ios.vendored_library = 'Libraries/libProj4.a'
spec.vendored_libraries = 'libProj4.a', 'libJavaScriptCore.a'
(6)resource_bundles
该方式会建立name和file对应的bundle文件
强烈建议使用该方式,将所需的资源打成bundle,这样可以避免文件名的冲突,在命名的时候建议加上pod库的相关名称以避免bundle名字的冲突。
spec.ios.resource_bundle = { 'MapBox' => 'MapView/Map/Resources/*.png' }
spec.resource_bundles = {
'MapBox' => ['MapView/Map/Resources/*.png'],
'OtherResources' => ['MapView/Map/OtherResources/*.png']
}
(7)resources
copy至target的资源列表。
强烈建议使用上述的resource_bundles
方式,来避免命名冲突,并且该方式是直接拷贝到客户端,没有xcode对相关资源的优化措施。
spec.resource = 'Resources/HockeySDK.bundle'
spec.resources = ['Images/*.png', 'Sounds/*']
(8)exclude_files
应该从其他文件模式中排除的文件模式列表。
spec.ios.exclude_files = 'Classes/osx'
spec.exclude_files = 'Classes/**/unused.{h,m}'
(9)preserve_paths
下载后不应删除的文件。
默认情况下,CocoaPods将移除所有其他文件模式不匹配的文件。
spec.preserve_path = 'IMPORTANT.txt'
spec.preserve_paths = 'Frameworks/*.framework'
(10)module_map
当这个pod集成为framework时所需要使用的模块映射文件。
默认情况下,CocoaPods根据spec中的公共头文件创建模块映射文件。
spec.module_map = 'source/module.modulemap'
(11)script_phases
这个属性允许定义一个脚本,作为编译pod的一部分来执行。与prepare command不同,脚本阶段作为xcodebuild的一部分执行,它们还可以利用编译期间设置的所有环境变量。
一个pod可以提供多个脚本来执行,它们将按照声明的顺序来执行
注意,为了提供可见性和意识到执行内容的情况,如果用户安装了你的pod,如果包含任何脚本,将向用户发出警告。
spec.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"' }
spec.script_phase = { :name => 'Hello World', :script => 'echo "Hello World"', :execution_position => :before_compile }
spec.script_phase = { :name => 'Hello World', :script => 'puts "Hello World"', :shell_path => '/usr/bin/ruby' } }
spec.script_phases = [
{ :name => 'Hello World', :script => 'echo "Hello World"' },
{ :name => 'Hello Ruby World', :script => 'puts "Hello World"', :shell_path => '/usr/bin/ruby' } },
]
七、Subspecs
一个library可以指定对另一个library的依赖性,另一个library的subspec或自身的subspec。
- subspec
表明库的一个子模块的spec
一般来说,subspec集成父类的值,并且有自己的设定,比如我们在使用如下库时,当我们庄ShareKit,会将她所有的subspec都安装上,有些我们并不需要
pod 'ShareKit', '2.0'
而我们可以指定安装的subspec来安装我们想要的库
pod 'ShareKit/Twitter', '2.0'
pod 'ShareKit/Pinboard', '2.0'
而这样做的前提是我们设定了ShareKit的诸多subspec。
例如:
- subspec含有不同的source文件
subspec 'Twitter' do |sp|
sp.source_files = 'Classes/Twitter'
end
subspec 'Pinboard' do |sp|
sp.source_files = 'Classes/Pinboard'
end
- 子模块对其子模块的依赖:
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
- 嵌套subspec
Pod::Spec.new do |s|
s.name = 'Root'
s.subspec 'Level_1' do |sp|
sp.subspec 'Level_2' do |ssp|
end
end
end
- requires_app_host
测试spec是否要求应用程序主机运行测试。这仅适用于测试spec。
test_spec.requires_app_host = true
- test_spec
表示库的测试spec规范。在这里,可以为podspec提供所有的测试以及测试依赖项。
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
- default_subspecs
一个subspec的数组,该数组将作为优先依赖的subspec进行提供,如果没有指定,则spec要求全部subspec为依赖项。
默认情况下,pod应该可以提供完整的库。当用户的要求是已知的,用户可以微调他们的依赖关系,并排除不需要的subspec。因此,很少需要这种属性。它是用来选择默认subspec的,例如有subspec提供替代一些subspec不兼容的实现,或很少需要的模块(特别是如果它们依赖于其他库)
spec.default_subspec = 'Core'
spec.default_subspecs = 'Core', 'UI'
八、多平台支持
为不同的平台不同的代码,例如:
spec.resources = 'Resources/**/*.png'
spec.ios.resources = 'Resources_ios/**/*.png'
不同的平台将拥有不同的资源。
- ios
spec.ios.source_files = 'Classes/ios/**/*.{h,m}'
- osx
spec.osx.source_files = 'Classes/osx/**/*.{h,m}'
- macos
spec.osx.source_files = 'Classes/osx/**/*.{h,m}'
- tvos
spec.tvos.source_files = 'Classes/tvos/**/*.{h,m}'
- watchos
spec.watchos.source_files = 'Classes/watchos/**/*.{h,m}'