Carthage和CocoaPods是目前业界广泛使用的两个依赖管理工具,几乎所有的知名开源项目,都会选择同时支持这两种工具。这两天在将自己的一个开源项目支持Carthage的过程中,对此工具有了更深的理解,在此记录一下过程和遇到的一些小坑。
原理
Carthage的工作原理和步骤如下:
- 通过Cartfile的内容,去指定的源码仓库,拉取指定的版本的代码。
拉取指定版本是通过Tag这一功能,所以需要对源码仓库打上Tag。除非在Cartfile里指定版本为"master",这时会取最新代码。 - 代码拉取后存放在Carthage/Checkouts目录。遍历仓库中的xcodeproj文件,查找出类型为Cocoa Touch Framework(动态库),且scheme为Shared的target,进行编译。
- 生成动态库,位置在Carthage/Build/iOS目录。
由于iOS是从8.0才开始支持动态库,所以如果要在项目中使用Carthage管理第三方库的依赖,那么要求你的项目的deployment target必须大于等于8.0。
对自己的开源项目添加Carthage支持
明白了上述原理,那么要想使我们自己的开源项目支持Carthage,那么其实也很简单,步骤如下:
1. 创建framework target
在已有的Xcode工程里,添加一个target,创建的时候选择类型为Cocoa Touch Framework,在弹出的界面中填写Product Name, Embed in Application选None。
Product Name应该填开源项目的名字,例如AFNetworking, SDWebImage这样的。target创建以后,会产生一个umbrella header file,名字和Product Name完全一样。
2.编辑umbrella header file
在这个文件里,import所有public的头文件。
3.配置framework target
选择 framework target,选中Build Phases,将所有的.m文件拖拽到Compile sources 里面。
注意:
如果使用了Category,那么你需要在Build Settings的Linking的Other Linker Flags里加上-all_load
如果工程支持bitcode,需要在Other C Flags 里加上-fembed-bitcode
4.设置framework target的scheme为Shared
进入到Manage Schemes...里面,勾选Shared复选框。
5.本地验证framework target
在终端里,键入carthage build --no-skip-current
,对framework target进行build,此过程能够验证配置是否有误。
执行结果会保存在工程的 Carthage/Build 文件夹下。
如果没有任何错误信息,那么说明配置是正确的。
6.对仓库打tag
第5步中,验证完没有问题,就可以提交代码,然后打tag,例如1.0.0。
至此,你的开源项目就完美支持Carthage了。可以新建一个测试工程,再次验证。
遇到的一些问题
在配置的过程中,可能遇到如下问题,附解决办法。
Dependency "xxx" has no shared framework schemes for any of the platforms: iOS
在carthage update 时,如遇到错误提示Dependency "xxx" has no shared framework schemes 说明工程的scheme没有被标记为shared,原因可能是git忽略了对应的工程文件。检查gitignore
确保此文件未被忽略 xxx.xcodeproj/xcshareddata/xcschemes/xxx.xcschemeFailed to read file or folder
如果遇到如下的错误:
Failed to read file or folder at /Users/sulirong/Library/Developer/Xcode/DerivedData/xxx-bcpyggvdymcfpsfaqhmhaddmjptp/Build/Products/Release-iphoneos/xxx.framework,是因为framework target的Info.plist文件中,缺少了CFBundleExecutable这一项,添加上,设为$(EXECUTABLE_NAME)。使用@import导入三方库时,有警告,说umbrella header file中没有import某些头文件
这是因为在制作framework target时不太规范,没有使用umbrella header file来导入所有public的头文件。
但如果使用普通的import方式,则也不会有此警告。