在APP项目中使用的静态库有两种,一是.a静态库,另一种是framework静态库。下面分布介绍这2中静态库的创建过程,以及通过脚本工具做自动化打包的2种方式。
 
Framework静态库生成
如果APP项目和SDK项目都使用了pod第三方库,那么podfile文件设置如下:
# App项目的Podfile文件
target 'StaticFramework' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for StaticFramework
pod 'FMDB'
end # SDK项目的Podfile文件
target 'StaticFramework' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for StaticFramework
pod 'FMDB'
end post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end
1.创建一个Static Framework工程,将Build Setting中的MachO Type设置成Static静态库形式
2.将项目文件和资源文件(切图,xib等)导入到Framework制作工程中,并添加依赖的第三方库库frameworks, libararies项下选择嵌入。注意在添加第三方库时不用选择添加到Target。
3.Build Phases阶段 修改
移动Header阶段内添加静态库里的.h头文件,把需要暴露外面的放到public下面(包括:SDK的集成h文件和包含的内部h文件)。
检查Copy Bundle Resources 阶段,查看png,xib等资源文件是否在里面,
查看Compile Sources中编译.m文件是否都在里面,
查看Link Binary With Libaray下需要链接的其他静态库库是否都在里面。
4.Build Settings 修改, 搜索linking进行链接过程设置
Dead Code Stripping 设置为NO,完全包含framework里的代码,拒绝剪裁,修改。
Link With Standard Libraries 设置为关闭,避免重复链接
#Build Active Architecture only 设置为Yes, 使其编译时只生成当前机器的架构。
Other Linker Flags选项设置为-ObjC
另外,Other Linker Flags选项的其他常用设置
-ObjC: 强制加载所有用Objective-C类和分类实现的目标文件
-all_load: 强制加载所有的目标文件
-force_load[path]: 强制加载[path]指定路径的静态库中的所有目标文件
-l[xxx]: 告诉链接器,在搜索路径下查找lib[xxx].dylib 或 lib[xxx].a
-framework [xxx]: 告诉链接器在framework搜索路径下,查找`xxx.framework/xxx'
-F[dir]: 在frameworks搜索路径下追加一个目录[dir]
-Xlinker: 传递给链接器的其他选项,例如-Xlinker -rpath @executable_path/Frameworks/。
Dead Code Stripping是一种编译优化技术。当设置成NO时,编译器不会进行这种优化,但默认仍然只会链接使用到的分类文件。
所以即使设置为NO,仍然需要将Other Linker Flags选项设置为“-ObjC ”才能将所有的分类文件链接进去。

5.framework合并

lipo -create xxxx/ProjectName.framework/ProjcetName xxxx/ProjectName.framework/ProjcetName -output xxxx/ProjectName.framework
lipo -create \
~/Library/Developer/Xcode/DerivedData/StaticFramework-cjzeucukluzhhscxruhakzuohbtp/Build/Products/Debug-iphoneos/StaticFramework.framework/StaticFramework \
~/Library/Developer/Xcode/DerivedData/StaticFramework-cjzeucukluzhhscxruhakzuohbtp/Build/Products/Debug-iphonesimulator/StaticFramework.framework/StaticFramework \
~/Library/Developer/Xcode/DerivedData/StaticFramework-cjzeucukluzhhscxruhakzuohbtp/Build/Products/Release-iphoneos/StaticFramework.framework/StaticFramework \
~/Library/Developer/Xcode/DerivedData/StaticFramework-cjzeucukluzhhscxruhakzuohbtp/Build/Products/Release-iphonesimulator/StaticFramework.framework/StaticFramework \
-output ~/Desktop/app/StaticFramework.framework
.a静态库生成
.a文件
1.创建一个Static Libaray工程
2.将项目文件和资源文件(切图,xib等)导入到SDK制作工程中
3.在Build Phases项目下,添加New Header Phases, 在Header阶段内添加静态库里的.h头文件,把需要暴露外面的放到public下面(包括:SDK的集成h文件和包含的内部h文件)。
bundle文件
4.静态库打包bundle文件,这里把静态库中需要的png,xib打包进去。在Targets下点击“+”,增加新的bundle target。从macOS下现在Bundle工程。因为iOS下没有这个项目
5.选中bundle target项目下的Build Phases Tab项 ,然后选择Copy Bundle Resources, 把SDK项目里的xib, png放到其中。
6.选中bundle target项目下的Build Settings Tab项, 
设置Base SDK 为 iOS,
设置COMBINE_HIDPI_IMAGES为NO,否则Bundle中的图片会变成tiff格式,
设置Skip install为YES,
删除Installation Directory对应的值

7.运行xcode项目,生成产物bundle文件和.a文件, 默认在目录~/Library/Developer/Xcode/DerivedData下

8.从中复制出libStaticLib.a文件,StaticLibResource.bundle,和所有暴露的.h头文件导入到项目中使用(在移动到APP项目时,.a和.bundle文件会自动添加到General->Frameworks,Libraries,and Embedded Content)。
9.合并静态库真机和模拟器文件
lipo -create XXX/模拟器.a路径 XXX/真机.a路径 -output 合并后的文件名称.a
lipo -create \
~/Library/Developer/Xcode/DerivedData/StaticLib-hhthxcjblbfkvzcguwyduhlkkvei/Build/Products/Debug-iphoneos/libStaticLib.a \
~/Library/Developer/Xcode/DerivedData/StaticLib-hhthxcjblbfkvzcguwyduhlkkvei/Build/Products/Debug-iphonesimulator/libStaticLib.a \
-output ~/Desktop/app/libStaticLib.a

10.APP中对资源文件的读取要指定对应的bundle,写名bundle的名称。

 
 
在SDK项目的target中加脚本做framework半自动打包
由于每次合并都要打开终端,执行lipo命令是很麻烦的,这里使用xcode提供的工具,编译阶段执行脚本,自动进行合并。
在SDK项目的target中加脚本做framework自动合并,不同架构的framework要自己手动运行项目生成。
在SDK项目下,依次进行点击Project -> Targets -> Build Phases + -> New Run Script Phases
# Type a script or drag a script file from your workspace to insert its path.
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 "${DEVICE_DIR}" ] || [ ! -d "${SIMULATOR_DIR}" ]
then
exit 0
fi # 如果合并包已经存在,则替换
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi mkdir -p "${INSTALL_DIR}" cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/" # 使用lipo命令将其合并成一个通用framework
# 最后将生成的通用framework放置在工程根目录下新建的Products目录下
lipo -create "${DEVICE_DIR}/${PROJECT_NAME}" "${SIMULATOR_DIR}/${PROJECT_NAME}" -output "${INSTALL_DIR}/${PROJECT_NAME}" #合并完成后打开目录
open "${SRCROOT}/Products" fi
 
通过新建aggregate合计工程做framework脚本完全自动合并
1.创建aggregate项目,添加Targets下面的“+”, 选择other -> aggregate项目,进行创建。
2.在aggregate项目下,依次进行点击Project -> Targets -> Build Phases + -> New Run Script Phases, 在里面添加执行脚本
3.运行项目,生成framework
# 取得项目名字(get project name)
FMK_NAME=${PROJECT_NAME}
# 取得生成的静态库文件路径 (get framework path)
INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework
# 设置真机和模拟器生成的静态库路径 (set devcie framework and simulator framework path)
WRK_DIR=${BUILD_ROOT}
DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework
SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework
# 模拟器和真机编译 (device and simulator build)
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build
xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build
# 删除临时文件 (delete temp file)
if [ -d "${INSTALL_DIR}" ]
then
rm -rf "${INSTALL_DIR}"
fi
mkdir -p "${INSTALL_DIR}"
# 拷贝真机framework文件到生成路径下 (copy device file to product path)
cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"
# 合并生成,替换真机framework里面的二进制文件,并且打开 (merger and open)
lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"
echo "${DEVICE_DIR}/${FMK_NAME}"
echo "${SIMULATOR_DIR}/${FMK_NAME}"
rm -rf "${WRK_DIR}"
echo "${INSTALL_DIR}"
Xcode13打包.a静态库报错问题
真机和模拟器静态库都包含了 (arm64)架构,导致无法合并成胖子库。
/usr/bin/lipo: Release-iphoneos/libGPUImage.a and Release-iphonesimulator/libGPUImage.a have the same architectures (arm64) and can't be in the same fat output file
原因为:
Xcode12之前
Xcode编译出来的模拟器静态库只包含i386, x86_64架构
xcode编译出来的真机静态库只包含armv7, arm64架构
所以,当这两种用途的库打包出来后,通过lipo create -output xxx 就可以顺利的生成同时包含i386, x86_64, armv7, arm64这四种架构,同时支持模拟器和真机的静态库了。
Xcode12之后
模拟器也支持了arm64架构,导致打出来的模拟器静态库中也包含了arm64架构,导致合并胖子库时架构冲突,报错。
解决方法为:
在Xcode的Build Settings - Architectures - Excluded Architectures - Release - Any iOS Simlator SDK 设置 arm64
这样在模拟器静态库中就不包含arm64架构了。
然后又可以快乐的打包了。
另外: 如果没有Xcode工程,可以用命令行工具手动去除重复的架构: 
lipo XXX.a -remove arm64 -output XXX.a
如何选择嵌入静态库或动态库的策略
项目依赖的第三方库有2种,动态库和静态库。动态库的形式有.framework和.dylib。静态库的形式有:.a和.framework
静态库的使用方式
1.通过直接拖到项目中,以嵌入的方式引入项目(选择非嵌入,非签名时,只保存framwork的使用信息和路径),这样静态库会被copy到ipa文件中,等APP运行时,再加载到内存使用。
2.通过Other Linker Flags的方式集成到项目中,这种方式在编译,链接时会和其他.o文件一起链接到可执行文件中,与源文件变成一个整体。
 
当项目以Linker的方式使用静态库时:在链接阶段,APP会将使用到的静态库和其他.o文件链接在一起,成为一个整体。
项目对动态库的使用方式:在运行阶段,APP在启动是,会根据mach-o文件中使用的动态库,按里面包含的动态库地址去加载,如果内存有了,就使用内存中的缓存。因为APP启动要加载这个动态库,所以ipa包中要包含用到的动态库(通常是使用iOS系统自带的动态库如:UIKit, Foundation, 用户在APP中包含自己的动态库通常没有多大意义)。
在项目中添加第三方库时会有三种嵌入方式:
Do Not Embed:不嵌入,选择linker链接到IPA中
Embed & Sign:嵌入并签名,签名是使用苹果公钥对第三方库加加密,在iOS系统运行时,使用iOS系统证书进行验证,是否是安全的第三方库。
Embed Without Signing:嵌入但不签名。
验证动态库和静态库的方式是使用file命令
file GPUImage.framework/GPUImage
打印结果
current ar archive:说明是静态库,选择Do not embed
Mach-0 dynamically:说明是动态库,选择Embed
是否对动态库进行Sign
通过查询当前动态库是否已经做了签名,如果做了就不能再做签名了
codesign -dv GPUImage.framwork
code object is not signed at all 或者 adhoc 。则选择Embed and sign
其它:表示已经正确签名,选择Embed Without Signing
 
 
 
参考文章:
https://www.jianshu.com/p/e05b965672c7
 
 
 

创建framework静态库和.a静态库的更多相关文章

  1. (一〇四)使用Xcode6创建framework动态静态库

    在Xcode6以前,创建framework可以使用iOS-Universal-Framework模板来创建framework,现在苹果已经提供了模板,如下图选择: 使用此模版创建的默认是动态库,方法和 ...

  2. Xcode8如何创建Framework静态SDK库

    iOS的软件开发工具包SDK,一般是以库的形式出现,从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.开发过程中,我们常常会用到第三方的SDK.尤其是微信.QQ.百度地图.支付功能等.其 ...

  3. iOS XCode7制作.Framework动态库和.a静态库的总结

    一.开发SDK时的支持情况: OC语言制作动态库时,支持iOS8+:OC语言制作静态库,支持iOS7+. Swift语言制作动态库时,支持iOS8+;Swift不支持静态库. 对于SDK来说,支持情况 ...

  4. 使用Xcode 5创建Cocoa Touch Static Library(静态库)

    转自:http://blog.csdn.net/jymn_chen/article/details/21036035 首先科普一下静态库的相关知识: 程序编译一般需经预处理.编译.汇编和链接几个步骤. ...

  5. 在Linux中创建静态库.a和动态库.so

    转自:http://www.cnblogs.com/laojie4321/archive/2012/03/28/2421056.html 在Linux中创建静态库.a和动态库.so 我们通常把一些公用 ...

  6. Qt 共享库(动态链接库)和静态链接库的创建及调用

    前言: 编译器 Qt Creator, 系统环境 win7 64 位 1.创建共享库: 新建文件或项目->选择 Library 和 c++ 库->选择共享库->下一步(工程名为 sh ...

  7. Qt动态库静态库的创建、使用、多级库依赖、动态库改成静态库等详细说明

    本文描述的是windows系统下,通过qtcreator在pro文件中添加动态库与静态库的方法: 1.添加动态库(直接添加动态库文件.dll,非子项目) 通过qtcreator创建动态库的方法就不在此 ...

  8. iOS 静态库和动态库的区别&静态库的生成

    linux中静态库和动态库的区别 一.不同 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.库分静态库和动态库两种. 1. 静态函数库 这类库的名字一般是libxxx.a:利用静态函 ...

  9. 【转】 iOS 开发之静态库.a和动态库详解 -- 不错

    原文网址:http://blog.csdn.net/lxl_815520/article/details/52154331 一, 简单介绍 1.什么是库 库是程序代码的集合,是共享程序代码的一种方式 ...

  10. Linux链接库二(动态库,静态库,库命名规则,建立个没有版本号的软连接文件)

    http://www.cppblog.com/wolf/articles/74928.html http://www.cppblog.com/wolf/articles/77828.html http ...

随机推荐

  1. 方法记录 | 文件批量导入Goodnotes

    一般来说通常资料都是用网盘下载了很多文件,想用Goodnotes来写批注,记笔记等,但是由于网盘不能直接分享.也不能批量分享到Goodnotes,给学习带来了很大的麻烦. 当然有钱的大佬们呢直接开了 ...

  2. Codeforce:131A. cAPS lOCK

    原题链接 ╮(╯▽╰)╭这题题目一开始没看明白,导致wa几次.如果全是大写或者出了首字母是小写其他为大写,则转换为第一个字母大写,其他的小写 ,如果不是以上两种情况则不作处理. ╮(╯▽╰)╭水题还错 ...

  3. Windows 10 修改环境变量不重启生效的解决方案

    # 表示 Win 键 #R 进入 cmd(不要使用 Listary 的 cmd 方式进入,设置不会生效) 键入 set PATH=C: 关闭窗口 同样方式打开 cmd 键入 echo %PATH%,会 ...

  4. 【有奖体验】AIGC小说创作大赛开启!通义千问X函数计算部署AI助手

    一个 AI 助手到底能做什么? 可以书写小说 可以解析编写代码 可以鼓舞心灵 提供职业建议 还有更多能力需要您自己去探索.接下来我们将花费 5 分钟,基于函数计算X通义千问部署一个 AI 助手,帮你撰 ...

  5. mysql 字段逗号分割行转列操作

    一.需求 某字段的值为 7654,7698,7782,7788 期望的效果:  二.实现语句 SELECT SUBSTRING_INDEX(SUBSTRING_INDEX('7654,7698,778 ...

  6. Eureka相关相关接口和代码位置

    1.服务注册:com.netflix.eureka.registry.AbstractInstanceRegistry#register(InstanceInfo registrant, int le ...

  7. webpack4.0+简要

    一.webpack简介 webpack 是当下十分流行的一款静态模块打包工具,将JS.CSS.HTML.图片等各种静态资源视为一个个模块,通过一个或者多个入口文件通过解析依赖关系生成一个依赖图,最终打 ...

  8. 去重N皇后

    题目:将上下对称.左右对称棋局.主副对角线对称棋局和旋转后重复视为重复,则要求输出去重后的N皇后问题的棋盘布局 这道题是一道作业题,我都惊到了,一向弱智的作业题中竟然冒出一道这样的题,这题最起码橙黄之 ...

  9. 使用zipFile读取文件时遇到的问题及解决(KeyError: "There is no item named 'xxx' in the archive")

    问题描述 在Windows上跑一段代码时,遇到如下问题: KeyError: "There is no item named 'CDR_Data\\\\CDR.Corpus.v010516\ ...

  10. Go-类型推导