iOS架构-静态库.framework脚本化打包补充(5)

静态库.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

  1. 打开Xcode->Project->Cocoa Touch Framework 建一个名为:MyFrameworkFramework类型的静态库
    iOS架构-静态库.framework脚本化打包补充(5)_第1张图片
  2. 新建一个文件Student,一个方法:- (void)study;
    iOS架构-静态库.framework脚本化打包补充(5)_第2张图片方法实现为一个简单的打印
#import "Student.h"

@implementation Student

- (void)study {
    NSLog(@"我爱学习!!!");
}
@end

同时将公开的头文件#import "Student.h"导入到MyFramework.h

iOS架构-静态库.framework脚本化打包补充(5)_第3张图片

  1. 准备编译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}"

  1. 把脚本放到MyFramework.xcodeproj 平级的目录下
    iOS架构-静态库.framework脚本化打包补充(5)_第4张图片
  2. 设置 Mach-O Type :Static Library
    iOS架构-静态库.framework脚本化打包补充(5)_第5张图片
  3. 添加Aggregate
    在Targets下面,点击左下角的“+”,选择添加一个“Aggregate” Target
    iOS架构-静态库.framework脚本化打包补充(5)_第6张图片
    在Cross-platform中的other中,名字:build_myFramework(随便起)
    iOS架构-静态库.framework脚本化打包补充(5)_第7张图片
  4. 给集合类build_myFramework添加依赖

在Targets下面选中我们新建的集合类,然后Build Phases --> Target Dependencies 下面添加我们需要编译的静态库,如下图所示。
iOS架构-静态库.framework脚本化打包补充(5)_第8张图片

  1. 添加脚本

在Targets下面选中我们新建的集合类,然后在Build Phases下,点击左上角的“+”,选择"New Run Script Phase"选项,如下图。

iOS架构-静态库.framework脚本化打包补充(5)_第9张图片然后设置我们运行的脚本的所在位置,如下图所示。将脚本拉到箭头位置。注意框2 的参数名字:为工程名字。MyFramework 写错编译时会报错。

iOS架构-静态库.framework脚本化打包补充(5)_第10张图片

…/scripts/build-framework.sh 表示脚本的位置在当前工程的上一个目录下的scripts文件夹下. 当然"…/“也可以用”${SRCROOT}/…/"来代替.

  1. 选择我们创建的集合类的target,然后编译

编译成功之后,我们会看到在我们的当前Xcode工程所在的目录下会新创建一个文件,名称为"projectName_Products",projectName是指我们工程的名称。里面就是真机和模拟器合并之后的版本的了。可以通过

lipo -info xxx

命令来产看,一般结果显示为支持"i386 armv7 x86_64 arm64"这四种架构。

iOS架构-静态库.framework脚本化打包补充(5)_第11张图片

制作Static Library

  1. 打开Xcode->Project->Cocoa Touch Static Library 建一个名为:My LibraryStatic Library类型的静态库iOS架构-静态库.framework脚本化打包补充(5)_第12张图片

  2. 重复上面步骤 2:新建一个文件Student,一个方法:- (void)study;
    同时将公开的头文件#import "Student.h"添加到Copy Files中
    iOS架构-静态库.framework脚本化打包补充(5)_第13张图片

  3. 准备编译.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}"

  1. 把脚本放到My Library.xcodeproj 平级的目录下
    然后

Deployment Info 设置

iOS架构-静态库.framework脚本化打包补充(5)_第14张图片

  1. 选择Targets->编译目标:执行脚本。

测试demo

1.测试MyFramework.framework

非常简单,直接把MyFramework.framework拉到工程中即可引用。
iOS架构-静态库.framework脚本化打包补充(5)_第15张图片

2.测试libMyLibrary.a

把.a 和头文件拉到工程中

  1. 添加libMyLibrary.a到Link Binary With Libraries中
    iOS架构-静态库.framework脚本化打包补充(5)_第16张图片
  2. 把静态库头文件路径添加到 Header Search Paths
    iOS架构-静态库.framework脚本化打包补充(5)_第17张图片
  3. 导入“Student.h”使用
    iOS架构-静态库.framework脚本化打包补充(5)_第18张图片
    打出来的Framework 36KB 磁盘占用66KB
    打出来的static.a 11KB 磁盘占用16KB
    本教程demo
    完结!

参考

Xcode Build Setting中指令集相关选项释义
iOS 制作静态库自动编译脚本

你可能感兴趣的:(iOS,架构之路)