iOS如何将业务插件打包成动态库

449 阅读3分钟

工程组件化的需要解决两个问题:一,组件间通信;二,业务依赖其他插件(功能插件或业务插件)时,如何构建开发工程。

其中,将业务插件打包为动态库,再将所需功能、业务动态库集成在工程中,是解决问题二的有效手段。

构建动态库前的设置

第一步

选中打包Framework对应Target,找到Build Setting,搜索iOS,修改对应版本,必要操作 设置支持版本

第二步

找到Dead Code Stripping 选项,设置为NO,非必要操作,建议修改 Dead Code Stripping

第三步

修改Link With Standard Libraries选项,设置为NO,非必要操作,建议修改 3.png

第四步

修改Mach-O Type选项,设置为动态库。必要操作 设置为静态库

第五步

设置Build Active Architecture Only选项,修改为NO必要操作 5.png

第六步

设置Architecture支持armv7s,非必要操作,看Framework是否需要支持对应架构机型 6.png

第七步

设置对外开放的.h头文件,不对外开放的.h头文件,放到Private或者Project选项下面。注意Compile Sources选项,看看是否有对应头文件的.m文件,如果没有需要添加进去,不然打包出来Framework会报错,必要操作 7.png

第八步

切换到Framework对应Target.h文件,导入需要暴露的.h头文件,非必要操作 11.png

Aggregate工程的设置

第一步

  • 业务代码开发完成后,在该target下新建Aggregate工程。 截屏2022-12-20 13.11.12.png
  • Aggregate工程可以通过脚本帮助我们更方便的构建动态库。
  • 按以下路径设置Aggregate工程对应的Target Dependencies:
TARGETS-->Aggregate工程-->Build Phases-->Target Dependencies 

第二步

  • 添加脚本Phase
TARGETS-->Aggregate工程-->Build Phases-->Run Script 

10.png

第三步

  • 加入脚本,脚本中的target名称需要根据自己新建的Framework打包Targrt填写
  • 脚本的核心代码是通过xcodebuild命令分别编译支持模拟器和真机的framework,然后再使用lipo命令将两个文件合并成一个。如果是线上包,则只需要打真机framework
  • 可以通过lipo -info xxx.framework命令查看库支持的架构。
#!/bin/sh
#要build的target名
TARGET_NAME="xxxFramework"
if [[ $1 ]]
then
TARGET_NAME=$1
fi
UNIVERSAL_OUTPUT_FOLDER="${SRCROOT}/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}"
复制代码

第四步 使用Shell打包Framework

选中Shell脚本对应的Target,选择通用,运行代码,选择机型的时候,一定要选择通用,这样才会包含模拟器和真机。 image.png

使用动态库

  • 将动态库拖入工程,在Generalframeworks里面,可以看见新添加的动态库,embed & sign表示编译时会将动态库拷贝到可执行文件的frameworks文件夹内,并且会做签名校验。 242ccaf8591a48ebb02af9fc8e17e63c_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png
  • 还需要设置copy files image.png

参考

dyld: Library not loaded: @rpath/xxx.framework 动态库

动态库插件demo PiaoJinFrameWorkDemo