小言_互联网的博客

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

383人阅读  评论(0)

静态库.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类型的静态库
  2. 新建一个文件Student,一个方法:- (void)study;
    方法实现为一个简单的打印
#import "Student.h"

@implementation Student

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

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

  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 平级的目录下
  2. 设置 Mach-O Type :Static Library
  3. 添加Aggregate
    在Targets下面,点击左下角的“+”,选择添加一个“Aggregate” Target

    在Cross-platform中的other中,名字:build_myFramework(随便起)
  4. 给集合类build_myFramework添加依赖

在Targets下面选中我们新建的集合类,然后Build Phases --> Target Dependencies 下面添加我们需要编译的静态库,如下图所示。

  1. 添加脚本

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

然后设置我们运行的脚本的所在位置,如下图所示。将脚本拉到箭头位置。注意框2 的参数名字:为工程名字。MyFramework 写错编译时会报错。

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

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

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

lipo -info xxx

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

制作Static Library

  1. 打开Xcode->Project->Cocoa Touch Static Library 建一个名为:My LibraryStatic Library类型的静态库

  2. 重复上面步骤 2:新建一个文件Student,一个方法:- (void)study;
    同时将公开的头文件#import "Student.h"添加到Copy Files中

  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 设置

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

测试demo

1.测试MyFramework.framework

非常简单,直接把MyFramework.framework拉到工程中即可引用。

2.测试libMyLibrary.a

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

  1. 添加libMyLibrary.a到Link Binary With Libraries中
  2. 把静态库头文件路径添加到 Header Search Paths
  3. 导入“Student.h”使用

    打出来的Framework 36KB 磁盘占用66KB
    打出来的static.a 11KB 磁盘占用16KB
    本教程demo
    完结!

参考

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


转载:https://blog.csdn.net/shifang07/article/details/102508608
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场