SDK自动打包

2017-08-08

背景: 由于iOS Framework打包出来是分CPU指令集的,所以需要每个CPU指令集都打包一个Framework,然后使用lipo -create命令将所有CPU指令集合并,才能形成一个兼容所有设备和模拟器的Framework。这样的打包流程复杂而繁琐,对于需要经常打包测试的需求来说明显是不合适的。

解决方案

使用xcode Aggregate工具中的Run Script自动进行不同CPU指令集打包,并自动合并所有CPU指令集

处理器指令集介绍

  • ARM处理器 - armv7 - armv7s - arm64
  • Mac处理器
    • i386
    • x86_64
指令集 设备 支持设备
arm64 真机64位 iPhone6s、iphone6s plus、iPhone6、iPhone6 plus、iPhone5S、iPad Air、 iPad mini2
armv7s 真机32位 iPhone5、iPhone5C、iPad4(iPad with Retina Display)
armv7 真机32位 iPhone4、iPhone4S、iPad、iPad2、iPad3(The New iPad)、iPad mini、iPod Touch 3G、iPod Touch4
i386 模拟器32位 针对intel通用微处理器32位处理器
x86_64 模拟器64位 针对x86架构的64位处理器

添加 Aggregate

  • 使用Xcode打开打包工程
  • FileNewTargetCross-platformAggregate
  • 命名为AvidlyAdsSDKArchive(自由命名)

添加 Run Script

  • 打开AvidlyAdsSDKArchiveAggregate
  • BuildPhasesNew+Cross-platformNew Run Script Phase
  • 打开新建的Run Script,在shell中键入打包代码

shell编写打包代码

2017-08-08更新 适用于Xcode10 and before

# 工程名称
# 如果工程名称和Framework的Target名称不一样的 话,要自定义FMKNAME
# 例如: FMK_NAME = "MyFramework"
FMK_NAME=${PROJECT_NAME}

# 工程Info.list路径
InfoPlist=${SRCROOT}/${PROJECT_NAME}/Info.plist

# 工程Version
Version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" $InfoPlist)
Version=${Version//./}

# 工程Build
Build=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $InfoPlist)

# SDK文件夹名称
SDKFilePath=${SRCROOT}/${PROJECT_NAME}_${Version}_${Build}

# 文件路径是否存在
if [ -d "${SDKFilePath}" ]
then
rm -rf "${SDKFilePath}"
fi
mkdir -p "${SDKFilePath}"

# 当前时间
updataDate=`date +%F`

# 将信息写入文件
updataFileName=${SDKFilePath}/version.md
touch ${updataFileName}
echo 版本:${Version} >> ${updataFileName}
echo 编译:${Build} >> ${updataFileName}
echo 时间:${updataDate} >> ${updataFileName}
echo 更新: >> ${updataFileName}

# SDK目录
INSTALL_DIR=${SDKFilePath}/${FMK_NAME}.framework

# Working dir will be deleted after the framework creation.
WRK_DIR=build
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework

# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build

# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"

# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
open "${SRCROOT}"


2019-06-10更新 适用于Xcode11

因Xcode11更新Bulid的目录,将Simulator和真机的编译目录修改为同一个地址,之前的脚本对导致出错,下边是修改后的sh脚本


# Sets the target folders and the final framework product.
# 如果工程名称和Framework的Target名称不一样的 话,要自定义FMKNAME
# 例如: FMK_NAME = "MyFramework"
FMK_NAME=${PROJECT_NAME}

PROJECT_PATH=$(cd "$(dirname "$0")";pwd)

# 工程Info.list路径
InfoPlist=${PROJECT_PATH}/${FMK_NAME}/Info.plist

# 工程Version
Version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" $InfoPlist)
Version=${Version//./}

# 工程Build
Build=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $InfoPlist)

# SDK文件夹名称
SDKFilePath=${PROJECT_PATH}/${FMK_NAME}_${Version}_${Build}

if [ -d "${SDKFilePath}" ]
then
rm -rf "${SDKFilePath}"
fi
mkdir -p "${SDKFilePath}"

updataDate=`date +%F`
#updataMessage=版本:${Version}\\n编译:${Build}\\n时间:${updataDate}\\n更新:

updataFileName=${SDKFilePath}/version.md
touch ${updataFileName}
echo 版本:${Version} >> ${updataFileName}
echo 编译:${Build} >> ${updataFileName}
echo 时间:${updataDate} >> ${updataFileName}
echo 更新: >> ${updataFileName}

# SDK目录
INSTALL_DIR=${SDKFilePath}/${FMK_NAME}.framework

# Working dir will be deleted after the framework creation.
WRK_DIR=build
WRK_DIR_iphone=build_Release-iphoneos
WRK_DIR_iphonesimulator=build_Release-iphonesimulator

DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework

DEVICE_DIR1=${WRK_DIR_iphone}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR1=${WRK_DIR_iphonesimulator}/Release-iphonesimulator/${FMK_NAME}.framework

# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build

# Cleaning the oldest.
if [ -d "${DEVICE_DIR1}" ]
then
rm -rf "${DEVICE_DIR1}"
fi
mkdir -p "${DEVICE_DIR1}"
cp -R "${DEVICE_DIR}/" "${DEVICE_DIR1}/"


xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build

# Cleaning the oldest.
if [ -d "${SIMULATOR_DIR1}" ]
then
rm -rf "${SIMULATOR_DIR1}"
fi
mkdir -p "${SIMULATOR_DIR1}"
cp -R "${SIMULATOR_DIR}/" "${SIMULATOR_DIR1}/"

# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR1}/" "${INSTALL_DIR}/"

# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.
lipo -create "${DEVICE_DIR1}/${FMK_NAME}" "${SIMULATOR_DIR1}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
rm -r "${WRK_DIR_iphone}"
rm -r "${WRK_DIR_iphonesimulator}"

open "${SRCROOT}"


2020-9-15更新 适用于Xcode12

因Xcode12模拟器Release编译的时候,编译出来的Framework自带arm64架构,和真机编译出来的Framework的arm64架构冲突,合并不了,导致之前的脚本对导致出错。修改方案,是模拟器先移除arm64架构,再合并,下边是修改后的sh脚本


# Sets the target folders and the final framework product.
# 如果工程名称和Framework的Target名称不一样的 话,要自定义FMKNAME
# 例如: FMK_NAME = "MyFramework"
FMK_NAME=TraceAnalysisSDK

PROJECT_PATH=$(cd "$(dirname "$0")";pwd)

# 工程Info.list路径
InfoPlist=${PROJECT_PATH}/${FMK_NAME}/Info.plist

# 工程Version
Version=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" $InfoPlist)
Version=${Version//./}

# 工程Build
Build=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" $InfoPlist)

# SDK文件夹名称
SDKFilePath=${PROJECT_PATH}/${FMK_NAME}_${Version}_${Build}

if [ -d "${SDKFilePath}" ]
then
rm -rf "${SDKFilePath}"
fi
mkdir -p "${SDKFilePath}"

updataDate=`date +%F`
#updataMessage=版本:${Version}\\n编译:${Build}\\n时间:${updataDate}\\n更新:

updataFileName=${SDKFilePath}/version.md
touch ${updataFileName}
echo 版本:${Version} >> ${updataFileName}
echo 编译:${Build} >> ${updataFileName}
echo 时间:${updataDate} >> ${updataFileName}
echo 更新: >> ${updataFileName}

# SDK目录
INSTALL_DIR=${SDKFilePath}/${FMK_NAME}.framework

# Working dir will be deleted after the framework creation.
WRK_DIR=build
WRK_DIR_iphone=build_Release-iphoneos
WRK_DIR_iphonesimulator=build_Release-iphonesimulator

DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework

DEVICE_DIR1=${WRK_DIR_iphone}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR1=${WRK_DIR_iphonesimulator}/Release-iphonesimulator/${FMK_NAME}.framework

# -configuration ${CONFIGURATION}
# Clean and Building both architectures.
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build

# Cleaning the oldest.
if [ -d "${DEVICE_DIR1}" ]
then
rm -rf "${DEVICE_DIR1}"
fi
mkdir -p "${DEVICE_DIR1}"
cp -R "${DEVICE_DIR}/" "${DEVICE_DIR1}/"


xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build

# Cleaning the oldest.
if [ -d "${SIMULATOR_DIR1}" ]
then
rm -rf "${SIMULATOR_DIR1}"
fi
mkdir -p "${SIMULATOR_DIR1}"
cp -R "${SIMULATOR_DIR}/" "${SIMULATOR_DIR1}/"

# Cleaning the oldest.
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
cp -R "${DEVICE_DIR1}/" "${INSTALL_DIR}/"

# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.

lipo -remove arm64 "${SIMULATOR_DIR1}/${FMK_NAME}" -output "${WRK_DIR}/${FMK_NAME}"
lipo -create "${DEVICE_DIR1}/${FMK_NAME}" "${WRK_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"


#lipo -create "${DEVICE_DIR1}/${FMK_NAME}" "${SIMULATOR_DIR1}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
rm -r "${WRK_DIR}"
rm -r "${WRK_DIR_iphone}"
rm -r "${WRK_DIR_iphonesimulator}"

open "${SRCROOT}"