關於Xcode12靜態庫打包的一些心得

最近在玩靜態庫打包,時不時遇到如下這種報錯,可能是Xcode升級的緣故,之前是沒有遇到過,故此總結了一波...

Building for iOS Simulator, but the linked library 'libxxx.a' was built for iOS.

這個問題是因爲模擬器編譯的那個.a沒有合併,只是打了真機的.a,運行到模擬器而模擬器是x86_64的架構,如果不需要模擬器調試,直接真機的即可

另: 模擬器打包與真機的包無法合併,出現arm64重複,無法合併爲fat的問題
Build settings->Excluded Architectures裏忽略當前SDK不支持的架構
模擬器SDK下可以忽略真機的架構arm64,arm64e,其實不適配5s以下的話直接把i386也去掉也是可以的,同樣真機也可去掉armv7和armv7s,這樣做的好處是可以減小包體積

現在新iPhone X以上iPhone 11 iPhone12等支持新架構得加一個arm64e,在Architectures裏的other裏手動添加即可

所以目前解決辦法就是打多個版本的靜態庫
比如:

  • 全量包 i386,x86_64,armv7,armv7s,arm64,arm64e
  • 拆分包
    • 真機和模擬器的拆分
      • 模擬器 i386,x86_64
      • 真機 armv7,armv7s,arm64,arm64e
    • 每一種架構單獨拎出來,lipo命令自己按需合併

一般來說,開發調試的話就用全量包,發佈上線用真機包

講道理,一些舊設備都被系統所淘汰了,iOS10起步支持iPhone 5s以上,那就大可不必支持i386和armv7,直接arm64和x86_64即可,上線打包可以剔除x86_64,這樣纔是最優解

編譯.a的腳本如下(採用手動編譯+腳本合成):

ps: 自動編譯在Xcode12.3不知道出了什麼鬼,xcodebuild一直死循環就是編譯不過,無奈之下采取半自動了,不過配合say語音提示也是可以的

#! /bin/sh
# 先在工程根目錄創建好SDK文件夾
mkdir -p ${PROJECT_NAME}_SDK
cd ${PROJECT_NAME}_SDK
mkdir -p ${PROJECT_NAME}
cd ${PROJECT_NAME}
mkdir -p include
mkdir -p lib

#回到工程目錄
cd ./../../
#真機build生成的.a文件路徑
DEVICE_DIR_A=${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${PROJECT_NAME}.a
#模擬器build生成的.a文件路徑
SIMULATOR_DIR_A=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${PROJECT_NAME}.a

if [[ -f "${DEVICE_DIR_A}" ]]; then
	say "真機編譯完成"
fi

if [[ -f "${SIMULATOR_DIR_A}" ]]; then
	say "模擬器編譯完成"
fi

if [[ -f "${DEVICE_DIR_A}" ]] ; then
	if [[ -f "${SIMULATOR_DIR_A}" ]]; then
		lipo -create ${DEVICE_DIR_A} ${SIMULATOR_DIR_A} -output ./${PROJECT_NAME}_SDK/${PROJECT_NAME}/lib/lib${PROJECT_NAME}.a
		#頭文件轉移大法
		HEADER_FOLDER="${BUILD_DIR}/${CONFIGURATION}-iphoneos/include/${PROJECT_NAME}"
		cp -a ${HEADER_FOLDER}/. ./${PROJECT_NAME}_SDK/${PROJECT_NAME}/include
		open ./
		say "靜態庫合併成功"
	fi
fi

編譯framework與.a類似

#! /bin/sh
#創建存放目錄
mkdir -p ${PROJECT_NAME}.framework
INSTALL_DIR=./${PROJECT_NAME}.framework

#真機編譯產物
DEVICE_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
#模擬器編譯產物
SIMULATOR_DIR=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework

#.framework是目錄是文件夾 所以用-d判斷 文件用-f
if [[ -d "$DEVICE_DIR" ]]; then
	say "真機編譯完成"
fi

if [[ -d "$SIMULATOR_DIR" ]]; then
	say "模擬器編譯完成"
fi

if [[ -d "${DEVICE_DIR}" ]] ; then
	if [[ -d "${SIMULATOR_DIR}" ]]; then
		cp -R ${DEVICE_DIR}/ ${INSTALL_DIR}/
		lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}"
		open ./
		say "靜態庫合併成功"
	fi
fi

一些相關文章

解決-Xcode-11-4-以來模擬器編譯報錯-Building-for-iOS-Simulator-but-the-linked-library-was-built-for-iOS-的正確姿勢
Xcode 12 - Architecture相關問題
iOS CPU架構(ARM指令集)
iOS 打包移除 i386 和 x86_64 平臺動態庫
Python小工具: 去除iOS靜態庫(.a或.framework)模擬器架構代碼

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章