Carthage
日常开发项目大都使用cocoapods,而近年来慢慢有开发往Carthage转移(iOS8+),Carthage是什么?和cocoapods一样是相关管理框架,但是他更轻便,与cocoapods不一样的是Carthage基本无侵入,设置与与项目的结构都不干预,那他干吗?
Carthage优缺
Carthage可以将依赖库二进制化(现在支持使用XCFrameWork),以提供项目使用,cocoapods也可以二进制化,但是要依赖额外方式(比如:cocoapods-imy-bin)。二进制的编译可以大大的缩短编译时间,但是同时反映出一个问题,Carthage二进制化后的库,不能直接修改调整,而cocoapods可以,可以直接在项目调整调试,还有就是项目设置问题,cocoapods项目添加库会在做好设置,虽然侵入项目设置,但是方便了开发者。除此之外,在使用的过程中,Carthage因为需要二进制化,所以会消耗一定时间(第三方库挺久的)。
Carthage使用
和cocoapods类似,可以支持不同Git平台,但是对GitHub很友好
首先第一步:创建Cartfile,可以使用命令
touch Cartfile
第二步:添加依赖库
使用远程仓库:
如果你的依赖库放在GitHub上,那么你可以使用
github "AFNetworking/AFNetworking"
或者
git "https://github.com/AFNetworking/AFNetworking.git"
但是如果不是在GitHub上,那就只能使用
git "git@gitee.com:chenyinhai/ZLPhotoBrowser.git"
其实没什么影响。
除了支持Git仓库链接,还支持JSON文件,如:
A binary only framework
binary "https://my.domain.com/release/MyFramework.json" ~> 2.3
A binary only framework via file: url
binary "file:///some/local/path/MyFramework.json" ~> 2.3
A binary only framework via local relative path from Current Working Directory to binary project specification
binary "relative/path/MyFramework.json" ~> 2.3
A binary only framework via absolute path to binary project specification
binary "/absolute/path/MyFramework.json" ~> 2.3
json格式如下:
{
"1.0": "https://my.domain.com/release/1.0.0/framework.zip",
"1.0.1": "https://my.domain.com/release/1.0.1/MyFramework.framework.zip?alt=https://my.domain.com/release/1.0.1/MyFramework.xcframework.zip"
}
但是使用JSON下载framework.zip的方式并不常用,而已必要性也不大,毕竟已经生成framework,直接下载便可,JSON文件也就起到版本引导作用。
还以使用本地仓库的项目
Use a local project
git "file:///directory/to/project"
在使用Git仓库的方式,同时还是可以指定分支和版本的如下:
Require version 2.3.1 or later
github "git@gitee.com:chenyinhai/ZLPhotoBrowser.git" >= 2.3.1
Require version 1.x
github "AFNetworking/AFNetworking" ~> 1.0 # (1.0 or later, but less than 2.0)
Require exactly version 0.4.1
github "AFNetworking/AFNetworking" == 0.4.1
github "AFNetworking/AFNetworking" "branch"
使用git带链接写法,类同
第三步:生成framework
在第二步的基础上,cd到项目目录下,执行命令,
carthage update
carthage update是最基础的,直接使用会产生多个平台,架构的framework,也同时很大概率出现构建失败,因为有些项目并不支持全部架构。
所以在iOS项目中一般使用的是
carthage update --use-xcframeworks --platform iOS
使用以前framework合并为通用的版后,已经不适用新版本的Xcode的构建方式,所以推荐使用xcframework,在这个基础上在选择一个开发平台为iOS,避免生成其他平台架构,而撑大xcframework的体积。
第四步:导入项目
在第三步执行完后,会在项目目录下找到Carthage文件夹,Carthage文件夹内包含两个子文件夹,Build与Checkouts。
找到Build文件夹内的xcframework,拖入项目中General--》Framework
私有库支持Carthage
1、创建私有库项目
可以最直接创建一个APP项目,而不是一个Framework项目,因为你可以考虑到后面可能要是使用项目进行拓展
2、创建Framework项目
在第一步的基础上,new一个Target,选择Framework
3、在Framework项目中添加代码
这里的步骤和创建Framework和.a文件做法是一样的,不做过多赘述。
4、调整Scheme
选择项目Manage Schemes,调整如下:
5、校验能否构建
cd到项目目录执行 carthage build --no-skip-current
如果能成功构建,那说明OK了。可以上传到远端,使用Carthage拉取构建,如上面Carthage使用方法一致
** 大致目录如下**
框架的更新
不管是否是更新 --use-xcframeworks --platform iOS切勿忘记
carthage update --use-xcframeworks --platform iOS frameworkName
或者
carthage update --new-resolver --use-xcframeworks --platform iOS frameworkName
极端一点,把Checkouts和Build都删除,重新update,就是费时间
与cocoapods一起用?
没有错,cocoapods一起用,可行性按理说是没问题的,因为Carthage就对项目基本无侵入,所以并不会出现冲突。
经实测,使用cocoapods集成了SDWebImage,纯swift项目,可以完美结合(先cocoapods后Carthage,先Carthage后cocoapods)。OC与混编未尝试,但按理说也可以正常执行。
Others&踩坑
疑问点
不使用xcframework可以吗,继续使用framework? ——是可以的,但是针对Xcode12+版本而言,要麻烦一些,而且对后续版本的Xcode来说,可能并不能完全适用,比较Xcode越来越弱智了。弱智到可能有一天你要纯手写代码。
Carthage给出了一套Xcode12后的适配方案:
Building platform-specific framework bundles (default for Xcode 11 and below)
Xcode 12+ incompatibility: Multi-architecture platforms are not supported when building framework bundles in Xcode 12 and above. Prefer building with XCFrameworks. If you need to build discrete framework bundles, use a workaround xcconfig file.
现在说是推荐使用XCFrameworks。如果你要继续使用framework,那么用这一套配置方案:
大致如下:
1、进入/usr/local/bin中建立一个sh脚本,叫carthage.sh
2、给予权限,chmod +x /usr/local/bin/carthage.sh
3、给carthage.sh加入指令:
# carthage.sh
# Usage example: ./carthage.sh build --platform iOS
set -euo pipefail
xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX)
trap 'rm -f "$xcconfig"' INT TERM HUP EXIT
# For Xcode 12 make sure EXCLUDED_ARCHS is set to arm architectures otherwise
# the build will fail on lipo due to duplicate architectures.
CURRENT_XCODE_VERSION="$(xcodebuild -version | grep "Xcode" | cut -d' ' -f2 | cut -d'.' -f1)00"
CURRENT_XCODE_BUILD=$(xcodebuild -version | grep "Build version" | cut -d' ' -f3)
echo "EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_${CURRENT_XCODE_VERSION}__BUILD_${CURRENT_XCODE_BUILD} = arm64 arm64e armv7 armv7s armv6 armv8" >> $xcconfig
echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_'${CURRENT_XCODE_VERSION}' = $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_$(XCODE_VERSION_MAJOR)__BUILD_$(XCODE_PRODUCT_BUILD_VERSION))' >> $xcconfig
echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig
export XCODE_XCCONFIG_FILE="$xcconfig"
carthage "$@"
4、cd到项目目录中使用 carthage.sh bootstrap --platform iOS --cache-builds
执行
官方解释道:This script has a known limitation - it will remove arm64 simulator architecture from compiled framework, so frameworks compiled using it cannot be used on Macs running Apple Silicon.
脚本会通过移除掉framework的 arm64 simulator架构来适应新版本Xcode的构建,否则可能会报 "Building for iOS, but the linked and embedded framework '.framework' was built for iOS + iOS Simulator。"类似的错误
5、frameWork需要添加脚本
经实测,如果使用了carthage.sh bootstrap --platform iOS,其实并不需要这一步,添加了反而出毛病,这一步从网上的帖子来看,是适合以前版本的做法
a、项目设置中添加一个脚本New Run Script Phase
b、添加/usr/local/bin/carthage copy-frameworks
c 、创建一个input.xcfilelist文件和output.xcfilelist文件
d、在input.xcfilelist加入要导进来的framework,如下:
$(SRCROOT)/Carthage/Build/iOS/Result.framework
$(SRCROOT)/Carthage/Build/iOS/ReactiveSwift.framework
$(SRCROOT)/Carthage/Build/iOS/ReactiveCocoa.framework
e、在output.xcfilelist中加入要导进来的framework,如下
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/Result.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/ReactiveSwift.framework
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/ReactiveCocoa.framework
f、 将nput.xcfilelist加入到Input File Lists中,output.xcfilelist加入到Output File Lists
踩坑
1、carthage update,直接用就是傻,所以平台都出来,iOS,watch,Mac。。。,体积10来M,直接到了上百M,而且速度真的很慢,M1表示都很头疼
2、导入后出现找不到文件XXXX.framework/XXXX' (no such file),这个是framework导入问题其实和carthage没太多关系,我这里调整了framework的Embed为Embed&Sign:
这个是动静态库问题,动态库用Embed,静态库用Do not embed,Signing用于动态库,判断是否是动态库和是否签名:
file xxxx.framework/xxxxx
返回Mach-O dynamically为动态,current ar archive为静态
codesign -dv xxxxxx.framwork
返回code object is not signed at all或者adhoc,则需要sign,选择Embed&Sign,否则without sign,因为已经不需要sign