用Run Script脚本为Framework打交叉包

最近开发SDK时在项目中使用静态库的时候都会有两个版本,一个用于模拟器,一个用于真机,这样就比较麻烦。为了模拟器与真机之间切换调试的方便,需要制作通用版的Framework交叉包。

根据Build时选择的机器类型,会分为模拟器Framework和真机Framework,两者是不能混用的。此时可以通过配置一个Run Script,在Script中使用lipo命令来合并两个版本的Framework,重新生成一个新的Framework,这个Framework将同时支持在模拟器和真机上运行。

1、检查Framework包信息

截图.png

这个两个目录下包含了生成的Framework文件夹,第一个是真机、第二个是模拟器(当前使用的是Debug模式,也可以使用Release模式)。按照预期:真机的包是显示armv7 arm64 架构的,模拟器的包是显示x86_64架构的。

现在我们分别对这两个目录中的Framework进行检测:
1)、Debug-iphoneos(真机)目录下的Framework:

MiniPC:~ lijl$ lipo -info /Users/lijl/Library/Developer/Xcode/DerivedData/SwiftCommon-dyhotzllcfgqjibahyytumthguvh/Build/Products/Debug-iphoneos/SwiftCommon.framework/SwiftCommon 
Architectures in the fat file: /Users/lijl/Library/Developer/Xcode/DerivedData/SwiftCommon-dyhotzllcfgqjibahyytumthguvh/Build/Products/Debug-iphoneos/SwiftCommon.framework/SwiftCommon are: armv7 arm64 
MiniPC:~ lijl$ 
//注:Framework是文件夹,命令再往下一层,使用SDK的二进制文件

真机Framework的结果是:armv7 arm64。可见,如果把这个Framework运行在模拟器中,肯定会报错,因为模拟器架构是x86_64的。
2)、Debug-iphonesimulator(模拟器)目录下的Framework:

MiniPC:~ lijl$ lipo -info /Users/lijl/Library/Developer/Xcode/DerivedData/SwiftCommon-dyhotzllcfgqjibahyytumthguvh/Build/Products/Debug-iphonesimulator/SwiftCommon.framework/SwiftCommon 
Non-fat file: /Users/lijl/Library/Developer/Xcode/DerivedData/SwiftCommon-dyhotzllcfgqjibahyytumthguvh/Build/Products/Debug-iphonesimulator/SwiftCommon.framework/SwiftCommon is architecture: x86_64
MiniPC:~ lijl$ 

模拟器Framework的结果是x86_64。可见这个库只能运行在模拟器中,真机设备是无法运行的。

2、创建脚本打交叉包

接下来,我们要对这2个库(其实是Framework目录下2个可执行文件)进行合并。
在项目的Build Phases中,新建一个Run Script,输入下面内容:

if [ "${ACTION}" = "build" ]
then
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}.framework

DEVICE_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework

SIMULATOR_DIR=${BUILD_ROOT}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework


if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi

mkdir -p "${INSTALL_DIR}"

cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
#ditto "${DEVICE_DIR}/Headers" "${INSTALL_DIR}/Headers"

lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"

#open "${DEVICE_DIR}"
#open "${SRCROOT}/Products"
fi

经过很多测试,下面这个修改后的Run Script会更加通用,不会出错,唯一报错的原因是对应目录下的包没有生成,这段shell代码其实很简单,前面一大部分是申明一些目录路径,最后使用lipo命令进行合并操作。

3、创建聚合Target生成的交叉包

1、创建target,选择Other下的Aggregate
2、嵌入脚本。选中刚刚创建的Aggregate,然后选中右侧的Build Phases,点击左下方加号,选择New Run Script Phase。
3、新建脚本:

# define output folder environment variable
CONFIGURATION=Release
UNIVERSAL_OUTPUTFOLDER_NATIVE=${SRCROOT}/${CONFIGURATION}-build/${PROJECT_NAME}.framework

#build support native API
# Step 1. Build Device and Simulator versions
cd "${SRCROOT}/.."
xcodebuild build -workspace ${PROJECT_NAME}.xcworkspace -scheme ${PROJECT_NAME} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION_RN} -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"

xcodebuild  build -workspace ${PROJECT_NAME}.xcworkspace -scheme ${PROJECT_NAME} -configuration ${CONFIGURATION} -sdk iphonesimulator VALID_ARCHS="i386 x86_64" BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}"

# make sure the output directory exists
rm -rf "${SRCROOT}/${CONFIGURATION}-build"
mkdir -p "${SRCROOT}/${CONFIGURATION}-build"

cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/" "${UNIVERSAL_OUTPUTFOLDER_NATIVE}/"

# Step 2. Create universal binary file using lipo
lipo -create "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}"  -output "${UNIVERSAL_OUTPUTFOLDER_NATIVE}/${PROJECT_NAME}"

# Last touch. copy the header files. Just for convenience

补充更新,兼容xcode13:

# Type a script or drag a script file from your workspace to insert its path.
# 1、定义输出变量
### 定义workspace名称
WORKSPACE= xxx1
### 定义输出SDK名称
SDKTARGET=xxxSDK
### 定义输出资源包名称
BUNDLETARGET=xxxResources
### 定义编译模式
CONFIGURATION=Release 
### 定义输出文件夹
PRODUCTS_OUTPUTFOLDER=${SRCROOT}/../Products

# 2、 先清理 TARGETS
#xcodebuild clean -target ${SDKTARGET}
#xcodebuild clean -target ${BUNDLETARGET}

cd "${SRCROOT}/.."
# 3、 执行编译SDK TARGETS
xcodebuild   -workspace ${WORKSPACE}.xcworkspace -scheme ${SDKTARGET} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" -UseModernBuildSystem=NO


xcodebuild  -workspace ${WORKSPACE}.xcworkspace -scheme ${SDKTARGET} -configuration ${CONFIGURATION} -sdk iphonesimulator VALID_ARCHS="i386 x86_64" BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" -UseModernBuildSystem=NO

# 4、 执行编译资源 TARGETS
xcodebuild   -workspace ${WORKSPACE}.xcworkspace -scheme ${BUNDLETARGET} ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" -UseModernBuildSystem=NO


xcodebuild  -workspace ${WORKSPACE}.xcworkspace -scheme ${BUNDLETARGET} -configuration ${CONFIGURATION} -sdk iphonesimulator  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" -UseModernBuildSystem=NO

# 5、 清空输出指定文件夹、创建新文件夹
rm -rf "${PRODUCTS_OUTPUTFOLDER}"
mkdir -p "${PRODUCTS_OUTPUTFOLDER}"

# 6、 将编译好的SDK和资源BUNDLE拷贝到指定输出文件夹
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${SDKTARGET}.framework" "${PRODUCTS_OUTPUTFOLDER}/"
cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${BUNDLETARGET}.bundle" "${PRODUCTS_OUTPUTFOLDER}/"
rm "${PRODUCTS_OUTPUTFOLDER}/${BUNDLETARGET}.bundle/${BUNDLETARGET}"
rm "${PRODUCTS_OUTPUTFOLDER}/${BUNDLETARGET}.bundle/Info.plist"

# 7、 合成真机和摸机器指令包
lipo -create "${BUILD_DIR}/${CONFIGURATION}-iphoneos/${SDKTARGET}.framework/${SDKTARGET}" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${SDKTARGET}.framework/${SDKTARGET}"  -output "${PRODUCTS_OUTPUTFOLDER}/${SDKTARGET}.framework/${SDKTARGET}"

# 8、 打开输出文件夹
open ${PRODUCTS_OUTPUTFOLDER}

4、验证脚本生成的交叉包

现在,当项目再次Build时,就会在项目目录下面出现Products目录,里面包含了合并后的Framework文件夹。使用lipo -info来检测下:

1、打开终端,进入到你的FrameWork,cd xxxx/xxx.framework
2、查看架构支持,lipo -info xxxx/xxx.framework/xxx (注意:xxx是你的FrameWork名称)

MiniPC:~ lijl$ lipo -info /Users/lijl/Documents/Self\ Project/Cocoa\ Touch\ Framework/SwiftCommon/Products/SwiftCommon.framework/SwiftCommon 
运行之后:
Architectures in the fat file: /Users/lijl/Documents/Self Project/Cocoa Touch Framework/SwiftCommon/Products/SwiftCommon.framework/SwiftCommon are: x86_64 armv7 arm64 
MiniPC:~ lijl$ 

信息显示成功的集成了 x86_64 armv7 arm64 ,这样就生成了真机与模拟器通用的交叉包

附指令集:

设备的CPU架构(指令集):
模拟器:

iPhone 4s~5: i386

iPhone 5s~最新: x86_64

真机(iOS设备):

armv6: iPhone、iPhone 2、iPhone 3G、iPod Touch(第一代)、iPod Touch(第二代)

armv7: iPhone 3Gs、iPhone 4、iPhone 4s、iPad、iPad 2

armv7s: iPhone 5、iPhone 5c

arm64: iPhone 5s、iPhone 6、iPhone 6 Plus、iPhone 6s、iPhone 6s Plus、iPad Air、iPad Air2、iPad mini2、iPad mini3,以及最新的机型。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容