静态库.framework脚本化打包打包已经在iOS架构-静态库.framework手动打包及脚本化打包(5)中讲过。这里补充是通过Xcode
配置Aggregate
自动执行脚本打包Framework
或者static library(.a)静态库的操作。以及检验支持的架构。
Architectures与Valid Architectures指令集
在Xcode6.1.1及以上Architectures 设置里, 默认为 Standard architectures(armv7,arm64),如果想改可以通过other添加指令集:armv7s。
Architectures : Strandard architectures - $(ARCHS_STANDARD)
ARCHS_STANDARD //相当于arm64 armv7 x_86_64 i386
Valid Architectures : arm64e arm64 armv7s armv7
arm64:iPhone 5s及以后iPhone 、iPad Air、iPad mini2
armv7s:iPhone5、iPhone5c、iPad4
armv7:iPhone4、iPad1/2/3、iPad mini
模拟器32位处理器测试需要i386架构,
模拟器64位处理器测试需要x86_64架构,
真机32位处理器需要armv7,或者armv7s架构,
真机64位处理器需要arm64架构。
所有指令集原则上都是向下兼容的,如iPhone4S的CPU默认指令集为armv7指令集,但它同时也兼容armv6指令集,只是使用armv6指令集时无法充分发挥其性能,即无法使用armv7指令集中的新特性,同理,iPhone5的处理器标配armv7s指令集,同时也支持armv7指令集,只是无法进行相关的性能优化,从而导致程序的执行效率没那么高。
支持的指令集越多,就会编译出包含多个指令集代码的数据包,对应生成二进制包就越大,也就是ipa包会变大。所以我们要根据需求合理选择支持的指令集。
Build Active Architecture Only
指定是否只对当前连接设备所支持的指令集编译
当其值设置为YES,这个属性设置为yes,是为了debug的时候编译速度更快,它只编译当前的architecture
版本,而设置为NO
时,会编译所有的版本。 所以,一般debug的时候可以选择设置为YES
,release的时候要改为NO
,以适应不同设备。
制作静态库.a是指令集选择
通过以上信息了解到,当我们做App的时候,为了追求高效率,并且减小包的大小,Build Active Architecture Only
设置成YES,Architectures按Xcode默认配置就可以,因为arm64向前兼容。但制作.a静态库就不同了,因为要保证兼容性,包括不同iOS设备以及模拟器运行不出错,所以结合当前行业情况,要做到最大的兼容性。
ValidArchitectures设置为:armv7|armv7s|arm64|i386|x86_64
Architectures设置不变(或根据你需要): armv7|arm64
然后分别选择iOS设备和模拟器进行编译,最后找到相关的.a进行合包:
制作Framework
- 打开Xcode->Project->Cocoa Touch Framework 建一个名为:
MyFramework
的Framework
类型的静态库
- 新建一个文件Student,一个方法:- (void)study;
方法实现为一个简单的打印
#import "Student.h"
@implementation Student
- (void)study {
NSLog(@"我爱学习!!!");
}
@end
同时将公开的头文件#import "Student.h"导入到MyFramework.h
- 准备编译framework的shell脚本
Script.sh
#!/bin/sh
#要build的target名
TARGET_NAME=${PROJECT_NAME}
if [[ $1 ]]
then
TARGET_NAME=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}_Products/"
#创建输出目录,并删除之前的framework文件
mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
rm -rf "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework"
#分别编译模拟器和真机的Framework
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${TARGET_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
#拷贝framework到univer目录
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework" "${UNIVERSAL_OUTPUT_FOLDER}"
#合并framework,输出最终的framework到build目录
lipo -create -output "${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${TARGET_NAME}.framework/${TARGET_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${TARGET_NAME}.framework/${TARGET_NAME}"
#删除编译之后生成的无关的配置文件
dir_path="${UNIVERSAL_OUTPUT_FOLDER}/${TARGET_NAME}.framework/"
for file in ls $dir_path
do
if [[ ${file} =~ ".xcconfig" ]]
then
rm -f "${dir_path}/${file}"
fi
done
#判断build文件夹是否存在,存在则删除
if [ -d "${SRCROOT}/build" ]
then
rm -rf "${SRCROOT}/build"
fi
rm -rf "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator" "${BUILD_DIR}/${CONFIGURATION}-iphoneos"
#打开合并后的文件夹
open "${UNIVERSAL_OUTPUT_FOLDER}"
- 把脚本放到
MyFramework.xcodeproj
平级的目录下
- 设置 Mach-O Type :Static Library
- 添加Aggregate
在Targets下面,点击左下角的“+”,选择添加一个“Aggregate” Target
在Cross-platform中的other中,名字:build_myFramework(随便起)
- 给集合类build_myFramework添加依赖
在Targets下面选中我们新建的集合类,然后Build Phases --> Target Dependencies 下面添加我们需要编译的静态库,如下图所示。
- 添加脚本
在Targets下面选中我们新建的集合类,然后在Build Phases下,点击左上角的“+”,选择"New Run Script Phase"选项,如下图。
然后设置我们运行的脚本的所在位置,如下图所示。将脚本拉到箭头位置。注意框2 的参数名字:为工程名字。MyFramework 写错编译时会报错。
…/scripts/build-framework.sh 表示脚本的位置在当前工程的上一个目录下的scripts文件夹下. 当然"…/“也可以用”${SRCROOT}/…/"来代替.
- 选择我们创建的集合类的target,然后编译
编译成功之后,我们会看到在我们的当前Xcode工程所在的目录下会新创建一个文件,名称为"projectName_Products",projectName是指我们工程的名称。里面就是真机和模拟器合并之后的版本的了。可以通过
lipo -info xxx
命令来产看,一般结果显示为支持"i386 armv7 x86_64 arm64"这四种架构。
制作Static Library
-
打开Xcode->Project->Cocoa Touch Static Library 建一个名为:
My Library
的Static Library
类型的静态库 -
重复上面步骤 2:新建一个文件Student,一个方法:- (void)study;
同时将公开的头文件#import "Student.h"添加到Copy Files中
-
准备编译.a的shell脚本
Script_library.sh
编译library的脚本
#!/bin/sh
#要build的target名
target_Name=${PROJECT_NAME}
if [[ $1 ]]
then
target_Name=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/${PROJECT_NAME}_Products"
# 创建输出目录,并删除之前的文件
rm -rf "${UNIVERSAL_OUTPUT_FOLDER}"
mkdir -p "${UNIVERSAL_OUTPUT_FOLDER}"
# 分别编译真机和模拟器版本
xcodebuild -target "${target_Name}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
xcodebuild -target "${target_Name}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
#复制头文件到目标文件夹
HEADER_FOLDER="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/include/${target_Name}"
if [[ -d "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/usr/local/include" ]]
then
HEADER_FOLDER="${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/usr/local/include"
fi
cp -R "${HEADER_FOLDER}" "${UNIVERSAL_OUTPUT_FOLDER}"
#合成模拟器和真机.a包
lipo -create "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${target_Name}.a" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${target_Name}.a" -output "${UNIVERSAL_OUTPUT_FOLDER}/lib${target_Name}.a"
# 判断build文件夹是否存在,存在则删除
if [ -d "${SRCROOT}/build" ]
then
rm -rf "${SRCROOT}/build"
fi
#打开目标文件夹
open "${UNIVERSAL_OUTPUT_FOLDER}"
- 把脚本放到
My Library.xcodeproj
平级的目录下
然后
Deployment Info 设置
- 选择Targets->编译目标:执行脚本。
测试demo
1.测试MyFramework.framework
非常简单,直接把MyFramework.framework
拉到工程中即可引用。
2.测试libMyLibrary.a
把.a 和头文件拉到工程中
- 添加
libMyLibrary.a
到Link Binary With Libraries中
- 把静态库头文件路径添加到
Header Search Paths
中
- 导入“Student.h”使用
打出来的Framework 36KB 磁盘占用66KB
打出来的static.a 11KB 磁盘占用16KB
本教程demo
完结!
参考
Xcode Build Setting中指令集相关选项释义
iOS 制作静态库自动编译脚本
转载:https://blog.csdn.net/shifang07/article/details/102508608