前言
最近公司項(xiàng)目要開發(fā)一款SDK
使用,研究了一下.Framework
和.a
的制作過程以及自動(dòng)腳本打包,這里記錄一下,關(guān)于靜態(tài)庫的概念部分這里不做說明,網(wǎng)上很多文章都有介紹,本文主要介紹靜態(tài)庫的制作過程以及自動(dòng)打包.
.Framework 打包流程
創(chuàng)建項(xiàng)目
1.新建工程選擇iOS —> Cocoa Touch Framework
2.進(jìn)入項(xiàng)目,導(dǎo)入自己需要打包SDK的源代碼,別忘記并勾選"Copy item needed"選項(xiàng)
3.進(jìn)入 TARGETS —> Build Phases,設(shè)置需要對(duì)外暴露的都文件,從Project拖到Public中即可,不需要暴露的放在Project中
Xcode相關(guān)設(shè)置
1.TARGETS —> Build Settings 中設(shè)置相關(guān)項(xiàng)
設(shè)置 Build Active Architecture Only選項(xiàng)為NO, NO選項(xiàng)意思:是當(dāng)前打包的.framework支持所有的設(shè)備.否則打包時(shí)只能用當(dāng)前選擇版本的模擬器或真機(jī)運(yùn)行.
2.設(shè)置 Mach-O Type 為 StaticLibrary(靜態(tài)庫)
3. 設(shè)置framework最低支持的版本
4. 如果靜態(tài)庫需要支持 armv7s,需要在 Architectures 中手動(dòng)添加armv7s, 默認(rèn)打包的真機(jī)只有 armv7和 arm64
編譯Framework 文件
1. 不同編譯環(huán)境下編譯會(huì)生成不同的靜態(tài)庫,debug模擬器,debug真機(jī)趾断,release模擬器匆浙,release真機(jī);
我們這里設(shè)置是Release, 選擇Edit Scheme--> Buid Configuration設(shè)置為release
2. Command+B 編譯,編譯后我們可以看到 framework 文件由紅色變?yōu)榱撕谏?通過 show in Finder 即可查看編譯后的文件
3. 我們的靜態(tài)庫如果要支持模擬器和真機(jī),就需要在真機(jī)和模擬器下各自編譯一次,打開文件所在位置,我們發(fā)現(xiàn)真機(jī)和模擬器的靜態(tài)庫都在這里了.
合并文件
1.查看靜態(tài)庫所支持的架構(gòu)
-
終端->lipo -info 庫, 這里需要查看的 framework 內(nèi)部的庫文件,不是 .framework 本體
lipo -info /Users/liuchuan/Library/Developer/Xcode/DerivedData/TestSDK-hkydpbtrsnfiegdptvmaviikkiuf/Build/Products/Release-iphoneos/TestSDK.framework/TestSDK
輸出結(jié)果如下圖:
上圖可以看到當(dāng)前庫只能支持真機(jī)運(yùn)行,如果需要支持真機(jī)和模擬器都可以運(yùn)行,需要將2個(gè)庫文件進(jìn)行合并
2.文件合并
- lipo -create 真機(jī)文件 模擬器文件 -output 目標(biāo)文件
lipo -create /Users/liuchuan/Library/Developer/Xcode/DerivedData/TestSDK-hkydpbtrsnfiegdptvmaviikkiuf/Build/Products/Release-iphonesimulator/TestSDK.framework/TestSDK /Users/liuchuan/Library/Developer/Xcode/DerivedData/TestSDK-hkydpbtrsnfiegdptvmaviikkiuf/Build/Products/Release-iphoneos/TestSDK.framework/TestSDK -output TestSDK
合并后查看:
此時(shí)文件可以支持模擬器和真機(jī)了;
最后我們將合并后的文件替換掉原有.framework 中的目標(biāo)文件即可; 然后拖入需要使用的工程即可;
腳本自動(dòng)打包
上面我們大致知道怎么通過手動(dòng)合并來進(jìn)行打包,實(shí)際開發(fā)中,如果使用手動(dòng)打包,每次修改了源代碼,需要手動(dòng)編譯真機(jī)和模擬器,然后合并,浪費(fèi)很多時(shí)間.接下來我們看下如果使用自動(dòng)腳本來進(jìn)行編譯合并打包的
建立一個(gè)Aggregate target
1. 添加一個(gè)target
2. 選擇Aggregate,并添加工程名字,隨便寫即可
3. 新建運(yùn)行腳本
4. 添加腳本語言
具體腳本如下:
#
if [ "${ACTION}" = "build" ]
then
#要build的target名
target_Name=${PROJECT_NAME}
#build之后的文件夾路徑
build_DIR=${SRCROOT}/build
#真機(jī)build生成的framework文件路徑
DEVICE_DIR_Framework=${build_DIR}/Release-iphoneos/${PROJECT_NAME}.framework
#模擬器build生成的framework文件路徑
SIMULATOR_DIR_Framework=${build_DIR}/Release-iphonesimulator/${PROJECT_NAME}.framework
#目標(biāo)文件夾路徑
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}
#判斷build文件夾是否存在刃泌,存在則刪除
if [ -d "${build_DIR}" ]
then
rm -rf "${build_DIR}"
fi
#判斷目標(biāo)文件夾是否存在昧穿,存在則刪除該文件夾
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
#創(chuàng)建目標(biāo)文件夾
mkdir -p "${INSTALL_DIR}"
#build之前clean一下
xcodebuild -target ${target_Name} clean
#真機(jī)build
xcodebuild -target ${target_Name} -configuration Release -sdk iphoneos
#模擬器build
xcodebuild -target ${target_Name} -configuration Release -sdk iphonesimulator
#復(fù)制頭文件到目標(biāo)文件夾
cp -R "${DEVICE_DIR_Framework}" "${INSTALL_DIR}"
#合成模擬器和真機(jī)包
lipo -create "${DEVICE_DIR_Framework}/${PROJECT_NAME}" "${SIMULATOR_DIR_Framework}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}.framework/${PROJECT_NAME}"
#打開目標(biāo)文件夾
open "${INSTALL_DIR}"
fi
5. 運(yùn)行腳本自動(dòng)打包
- 選中我們剛才創(chuàng)建的TestSDK_Script這個(gè)target勺远,然后運(yùn)行
- 運(yùn)行完畢會(huì)自動(dòng)在根目錄創(chuàng)建合并后的.framework 文件,并且會(huì)自動(dòng)打開文件夾所在位置
通過上面的腳本,我們可以很方便的實(shí)現(xiàn)一鍵打包功能了,再也不用挨個(gè)編譯然后合并了;
報(bào)錯(cuò)相關(guān):
使用了打包好的靜態(tài)庫, 在項(xiàng)目打包.IPA文件上傳到App Store的, 可能會(huì)遇到如下錯(cuò)誤 ,存在支持bitcode的問題
ld: bitcode bundle could not be generated because '/Users/liuchuan/Desktop/medeng/Demo/ZYAuthSDKDemo/ZYAuthSDKDemo/ZYAuthSDK/ZYAuthSDK.framework/ZYAuthSDK(ZYAuthSDK.o)' was built without full bitcode. All object files and libraries for bitcode must be generated from Xcode Archive or Install build for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
解決辦法,在我們打包靜態(tài)庫的時(shí)候添加以下內(nèi)容
在target->build Setting-> Add User-Defined Setting 添加選項(xiàng) BITCODE_GENERATION_MODE -> bitcode
.a 打包流程
.a 靜態(tài)庫打包方式基本和.framework 類似,下來主要對(duì)一些不同之處進(jìn)行說明
創(chuàng)建項(xiàng)目
- 新建工程選擇iOS —> Cocoa Touch Static Library
- 需要公開的頭文件放在此處
- .a 自動(dòng)打包腳本
if [ "${ACTION}" = "build" ]
then
#要build的target名
target_Name=${PROJECT_NAME}
#build之后的文件夾路徑
build_DIR=${SRCROOT}/build
#真機(jī)build生成的頭文件的文件夾路徑
DEVICE_DIR_INCLUDE=${build_DIR}/Release-iphoneos/include/${PROJECT_NAME}
#真機(jī)build生成的.a文件路徑
DEVICE_DIR_A=${build_DIR}/Release-iphoneos/lib${PROJECT_NAME}.a
#模擬器build生成的.a文件路徑
SIMULATOR_DIR_A=${build_DIR}/Release-iphonesimulator/lib${PROJECT_NAME}.a
#目標(biāo)文件夾路徑
INSTALL_DIR=${SRCROOT}/Products/${PROJECT_NAME}
#目標(biāo)頭文件文件夾路徑
INSTALL_DIR_Headers=${SRCROOT}/Products/${PROJECT_NAME}/Headers
#目標(biāo).a路徑
INSTALL_DIR_A=${SRCROOT}/Products/${PROJECT_NAME}/lib${PROJECT_NAME}.a
#判斷build文件夾是否存在,存在則刪除
if [ -d "${build_DIR}" ]
then
rm -rf "${build_DIR}"
fi
#判斷目標(biāo)文件夾是否存在时鸵,存在則刪除該文件夾
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
#創(chuàng)建目標(biāo)文件夾
mkdir -p "${INSTALL_DIR}"
#build之前clean一下
xcodebuild -target ${target_Name} clean
#模擬器build
xcodebuild -target ${target_Name} -configuration Release -sdk iphonesimulator
#真機(jī)build
xcodebuild -target ${target_Name} -configuration Release -sdk iphoneos
#復(fù)制頭文件到目標(biāo)文件夾
cp -R "${DEVICE_DIR_INCLUDE}" "${INSTALL_DIR_Headers}"
#合成模擬器和真機(jī).a包
lipo -create "${DEVICE_DIR_A}" "${SIMULATOR_DIR_A}" -output "${INSTALL_DIR_A}"
#打開目標(biāo)文件夾
open "${INSTALL_DIR}"
fi