代码日志《Carthage》

268 阅读6分钟

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 image.png

私有库支持Carthage

1、创建私有库项目

可以最直接创建一个APP项目,而不是一个Framework项目,因为你可以考虑到后面可能要是使用项目进行拓展

2、创建Framework项目

在第一步的基础上,new一个Target,选择Framework image.png

3、在Framework项目中添加代码

这里的步骤和创建Framework和.a文件做法是一样的,不做过多赘述。

4、调整Scheme

选择项目Manage Schemes,调整如下: image.png

5、校验能否构建

cd到项目目录执行 carthage build --no-skip-current 如果能成功构建,那说明OK了。可以上传到远端,使用Carthage拉取构建,如上面Carthage使用方法一致 ** 大致目录如下** image.png

框架的更新

不管是否是更新 --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 image.png

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 image.png

踩坑

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