预备知识
这篇文章假设你已经会用swift或者oc写framework静态库了,但是还不会用脚本合并fat文件,那么用10分钟时间阅读,可以加速你以后的合并速度,以后只需要一次command + b就能自动合并出 armv7 i386 x86_64 arm64 4种格式的fat文件
项目名字的坑
我的framework项目名叫做:tdwUIView+Extension.因为中间有一个加号+,在生成Products的framework时候,自动生成的tdwUIView_Extension,用下划线替代了+,那么在脚本中,PROJECT_NAME拼接的时候就会出错
顺便一提,这个framework写的是UIView的类扩展,因为是系统的类扩展,需要调用的时候在Other linker Flag里面添加-ObjC,否则报错:
reason: ‘-[xxx]: unrecognized selector sent to instance xxxxx’
重复的arm64合并错误的坑
首先,我们点击左上角里面的Edit Scheme ->Run ->Build Configuration ->Release,如下图,这样生成的都在release的2个目录里
这时候我们,默认情况下,我们选择模拟器运行,command + b ,生成 x86_64 arm64 和 i386 然后在Products里面show in finder查看framework里面的静态库,再选一个真机或者ios设备,command + b生成 arm64和armv7 ,如下图
如果这时候我们用lipo -create 文件名1 文件名2 -output 文件名3来合并文件,就会报错::tdwUIView_Extension have the same architectures (arm64) and can’t be in the same fat output file
原因是2个文件里面都有arm64,重复了。
解决方法1(不推荐,因为要手动输入命令,而且每次运行都要手动删除一次arm64)
lipo tdwUIView_Extension -remove arm64 -output tdwUIView_Extension_1
然后再把生成的tdwUIView_Extension_1 和 另一个Release-iphoneos 或者 Release-iphonesimulator 文件夹下的tdwUIView_Extension合并起来 用 lipo -create 文件路径1 文件路径2 -output 合并后的文件名
解决方法2(推荐,一次设置永久方便)
build Settings里面搜索:excluded architectures
然后如图点击release里面 选择 Any ios simulator sdk,输入arm64
这部的操作是把模拟器生成的framework都排除arm64格式,以后模拟器生成的只包含x86_64 i386 2种格式。如下图操作
添加脚本
选择Build Phases -> 点击加号 -> NewRun Scipte Phase,然后在窗口里面写入shell脚本,如下图
脚本内容的坑
这个脚本作用是把生成的framework合并成fat文件。注意,因为项目名里PROJECT_NAME面有一个+加号,所以这里拼接目录的时候会出错,系统会把+变成_,所以这里手动设置一个变量:projectName=“tdwUIView_Extension”
这个脚本的操作是把模拟器和真机的目录复制合并,因为framework下面的Modules文件夹真机和模拟器生成不同的文件.然后把framework下面的文件合并成fat文件.最后存放在项目目录下的products文件夹下
脚本如下,这个是我写的已经能正确使用的脚本,运行结束以后会打开项目目录下的Products文件夹,里面的frameworks就是fat格式的
#这个脚本的操作是把模拟器和真机的目录复制合并,因为framework下面的Modules文件夹真机和模拟器生成不同的文件.然后把framework下面的文件合并成fat文件.最后存放在项目目录下的products文件夹下
projectName="tdwUIView_Extension"
#因为PROJECT_NAME里面有一个+加号,所以这里拼接目录的时候会出错,把+变成_,所以这里手动设置
if [ "${ACTION}" = "build" ]
then
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework
DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${projectName}.framework
#注意,因为PROJECT_NAME里面有一个+加号,所以这里拼接目录的时候会出错,把+变成_,所以这里手动设置
SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${projectName}.framework
if [ -d "${INSTALL_DIR}" ]
# -d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
#mkdir -p递归创建目录,会把子目录也创建出来
#复制真机和模拟器目录下的文件夹,合并到一起
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
cp -R "${SIMULATOR_DIR}/" "${INSTALL_DIR}/"
#cp -R 拷贝文件,对特殊文件(管道文件,块设备文件,字符设备文件)会进行创建操作,而不是拷贝
#ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"
file1="${DEVICE_DIR}/${projectName}"
file2="${SIMULATOR_DIR}/${projectName}"
file3="${INSTALL_DIR}/${projectName}"
echo "file3=${file3}"
lipo -info ${file1}
lipo -info ${file2}
lipo -create ${file1} ${file2} -output ${file3}
lipo -info ${file3}
open "${SRCROOT}/Products/"
echo "${INSTALL_DIR}/"
fi
查看脚本日志,快捷键command + 9,会看到输入的结果,下图,我用红框圈除了
ipo -info ${file1}
lipo -info ${file2}
lipo -create ${file1} ${file2} -output ${file3}
的输出结果,可以看到file3已经被合并成armv7 i386 x86_64 arm64 4种格式的fat文件了
项目目录的坑
注意,同样是上面shell脚本,但是项目路径里面有空格,结果合并出错了,因为提示找不到路径,于是我删掉路径里面的空格,合并正常