MacOS开发 技术集锦iOS开发 技术集锦移动开发

Xcode 自动创建全系列静态库

2016-07-13  本文已影响872人  蓝点工坊

一.背景

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 name

2.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,否则脚本拷贝位置不对.

Paste_Image.png

2.4 编译库

首先把原项目静态库用真机版本编译一次,用来触发拷贝头文件的动作

在target选中的任意选一个设备来触发编译脚本

打开静态库的产品目录,把Debug-universal 目录整个拷给使用者即可,非常方便

Paste_Image.png
上一篇下一篇

猜你喜欢

热点阅读