Xcode 自动创建全系列静态库
一.背景
Xcode 静态库项目,每次运行只会创建一个体系结构.比如真机版的.a 不能在模拟器下链接运行.
这样会给使用者带来很大麻烦,使用项目无法用模拟器版本了. 一般做法是生成x86(模拟器)和ARM版本的.a,然后用lipo这个命令行格式合并两个库成一个.
命令格式如下:
lipo -create libBLEsim.a libBLEarm.a -output libBLE.a
但每次编译后这样把不同路径库拷贝,再发布是一个很麻烦的过程,有人会想到用脚本简化,http://devonios.com/xcode-lipo-framework.html
但是还是有点复杂,直接发现有人写文章说xcode是自动支持合并的
一.五: xcode8 更新
今天更新xcode8 后发现 xcodebuild 无法编译通过.后面介绍的方法需要调整一下. 即由xcode 来完成编译,再由Aggregate 合并.
编译时,需要注意,
在 valid Architecures 加入全部需要的 arch
arm64 armv7 armv7s x86_64 i386
Build Active Acrchitercture Only 要为 No,这样才会把新手机不支持的指令,armv7s i386 才能被加进去.
xcode 编译选项这样分别用在模拟器和真机状态编译一次,分别生成
Release-iphoneos 和Release-iphonesimulator
然后在调用Aggregate target 合成一个完整的 lib
# define output folder environment variable
LIB_TARGET_NAME=${PROJECT_NAME}
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
OUTPUT_DIR=${UNIVERSAL_OUTPUTFOLDER}
# make sure the output directory exists
mkdir -p ${UNIVERSAL_OUTPUTFOLDER}
# Step 2. Create universal binary file using lipo
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${PROJECT_NAME}.a"
# Last touch. copy the header files. Just for convenience
mkdir -p ${OUTPUT_DIR}
cp -v -f -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${OUTPUT_DIR}"
二.使用xcode合并静态库
这是原文:http://www.raywenderlich.com/41377/creating-a-static-library-in-ios-tutorial
这是翻译稿:http://www.cocoachina.com/industry/20131204/7468.html
这里提到使用Aggregate来调用lipo合并方法,方法如下:
2.1新建一个Aggregate target
Xcode中一个集合目标可以一次构建多个目标,包括命令行脚本。在Xcode菜单中选择File/New/Target,选择iOS/Other并点击Aggregate,如图:
Aggregate取个target名称
target name2.2 增加编译后脚本:
切换Aggregate到Build Phases标签;在这里设置构建目标时将要执行的动作。
点击Add Build Phase按钮,在弹出的菜单中选择New Run Script Phase,如下图:
New Run Script Phase展开Run Script模块,在Shell行下粘贴如下代码:
Shell脚本内容如下,注意这里要把 LIB_TARGET_NAME设为你真正的名字
# define output folder environment variable
LIB_TARGET_NAME=${PROJECT_NAME}
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
OUTPUT_DIR=${UNIVERSAL_OUTPUTFOLDER}
# Step 1. Build Device and Simulator versions
xcodebuild -target ${LIB_TARGET_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
xcodebuild -target ${LIB_TARGET_NAME} -arch x86_64 -sdk iphonesimulator -configuration ${CONFIGURATION} BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"
# make sure the output directory exists
mkdir -p ${UNIVERSAL_OUTPUTFOLDER}
# Step 2. Create universal binary file using lipo
lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${PROJECT_NAME}.a"
# Last touch. copy the header files. Just for convenience
mkdir -p ${OUTPUT_DIR}
cp -v -f -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${OUTPUT_DIR}"
代码并不十分复杂,它是这样工作的:
**UNIVERSAL_OUTPUTFOLDER **包括了通用二进制包将要被存放的文件夹:“Debug-universal”
**Step 1. **第2行执行了xcodebuild并命令它构建ARM架构的二进制文件。(你可以看到这行中的-sdk iphoneos参数)
下一行再次执行了xcodebuild命令并在另一个文件夹中构建了一个针对Inter架构的iPhone模拟器的二进制文件,在这里关键参数是-sdk iphonesimulator -arch i386。(如果感兴趣,你可以在man page了解更多关于xcodebuild的资料)
Step 2. 现在已经有了2个.a文件分别对应两个架构。执行lipo -create,用它们创建出一个通用二进制。
最后一行的作用是复制头文件到桌面的指定目录。(用cp命令)
2.3 设定需要输出的头文件
在原来
的库的Build Phases 中Copy Files中设定要导出的头文件,注意这里subpath 的缺省值是include/${PROJECT_NAME} 这里直接改成include,否则脚本拷贝位置不对.
2.4 编译库
首先把原项目静态库用真机版本编译一次,用来触发拷贝头文件的动作
在target选中的任意选一个设备来触发编译脚本
打开静态库的产品目录,把Debug-universal 目录整个拷给使用者即可,非常方便
Paste_Image.png