编译器之打包动态/静态库

一、简介

I. 库的类型分类

静态库

  • .a.framework 为文件后缀名
    .a 是一个二进制文件,不能直接拿来用,使用时需要 .a文件 + 头文件 + 资源文件
    静态库打包时,只能打包代码,图片文件、本地 JSON 文件和 xib 等资源文件无法打包进去
  • 静态库 连接时 完整的复制到可执行文件中,多个文件使用,多份拷贝
  • OC 建议使用静态库,OC 使用动态库审核可能会不通过
  • 静态库无法再包含其他的 .a 静态库。只能把源码放进去一起编译

动态库

  • .dylib.framework 为文件后缀名「Xcode7 后 .dylib 变为 .tbd 文件」
    .framework 文件,能直接拿来用。.framework 文件 = 二进制文件(.a 文件 + .h 文件) + 资源文件
    .tbd 文件,只是一个文本文件,其中包含架构信息,以及在真实运行时候二进制所在的位置,以及包含了动态库的符号表还有类的一些信息,这些信息在编译阶段足够了。「减少了所有设备 SDK 二进制动态库的体积」
  • 动态库 运行时 动态加载到内存,只加载一次,多个文件公用,节省内存
  • Swift 只能使用动态库,不支持静态库
  • 大部分第三方库就是动态库,可以暴露出来,放在源码的外部引用使用
  • 动态库的特性使得软件版本实时模块升级、应用插件化、etc

II. iOS 设备的 CPU 架构

iOS 库的打包,根据 CPU 架构的不同而不同
架构不同,不能编译通过

模拟器的 CPU 架构

  • i386:iPhone 4s ~ 5
  • x86_64:iPhone 5s ~ 7 Plus

真机的 CPU 架构

  • armv6:iPhone、iPhone 2、iPhone 3G、iPod Touch「第一代」、iPod Touch「第二代」
  • armv7:iPhone 3Gs、iPhone 4、iPhone 4s、iPad、iPad 2
  • armv7s:iPhone 5、iPhone 5c 「静态库只要支持了 armv7,就可以在 armv7s 的架构上运行」
  • armv64:iPhone 5s、iPhone 6、iPhone 6 Plus、iPhone 6s、iPhone 6s Plus、iPad Air、iPad Air2、iPad mini2、iPad mini3

二、打包静态库

I. .a 文件 静态库打包

  1. 创建静态库的工程
    创建后执行 运行 或 编译 ,都可以生成静态库「保存在项目的 Products 中」
Paste_Image.png
  1. 通过在不同架构的设备下 编译/运行 生成支持不同架构的静态库
Paste_Image.png
  1. 在 编译/运行 时,所有项目 都可以设置是 Debug 还是 Release
Paste_Image.png
  1. 设置库的接口 头文件
Paste_Image.png
  1. 通过设置不仅在当前运行的 CPU 架构上,适配所有的机型号架构
    一般 debug = no,release = yes 为了 debug 的时候编译更快「只编译连接当前的 CPU 架构所用的包」
    可以控制 测试版本 和 发布版本 是否都不仅仅能在真机上使用
Paste_Image.png

II. .framework 文件 静态库打包

  1. 前三步和 在 .a 文件 打包方式一致
  2. 设置库的接口 头文件
Paste_Image.png
  1. 设置打包的是 静态库,因为动态库也可以以 framework 的形式存在
    设为Static Library「这个默认选项是动态的」
Paste_Image.png

III. 使用静态库

1. 防止项目中的文件和 静态库的同名文件在运行时会覆盖,只保留一张图片

  • 把图片文件单独的放在一个 .bundle 文件中「一般 .bundle 的名字和 .a.framework 的名字相同」
  • .bundle 文件制作方法:将文件夹,重命名为 XXX.bundle
    同理,其他资源文件也放在一个 .bundle 中

2. 在使用 category 静态库的工程中,调用方法时,会出现找不到该方法的运行时错误:selector not recognized

原因:

  • Unix 的标准静态库实现和 Objective-C 的动态特性之间有一些冲突
  • Objective-C 没有为每个函数定义链接符号,它只为每个类创建链接符号
  • 当在一个静态库中使用类别来扩展已有类的时候,链接器不知道如何把类原有的方法和类别中的方法整合起来

解决办法:

  • 在使用静态库的工程中配置 other linkerflags 的值为 -ObjC 如果还崩溃,在添加 -all_load 「或者 -force_load
  • all_load 作用于所有的库,而 -force_load 后面必须要指定具体的文件
    这样,会将静态库中所有和对象相关的文件都加载进来
Paste_Image.png

3. 避免暴露过多的 .h 文件

使用

  • 在静态库的内部创建一个 .h 文件「一般这个.h文件的名字和静态库的名字相同」
    然后把所有需要暴露出来的 .h 文件名都集中放在这个 .h 文件中,只需要把这个 .h 暴露出来
  • 一般这个总头文件内部引入其他头文件的格式为
    #import <framework名字/其他头文件.h>,这是以调用这个库的项目的角度来写的

搜索头文件

  • Header Search Paths
    系统的搜索路径,用来引入项目中没有添加的 header 文件
    通过 #import <名称.h> 来引入

  • User Header Search Paths
    用户的搜索路径,用来引入项目中的已添加的 header 文件
    通过 #import <名称.h>#import "名称.h" 来引入

  • Always Search User Paths
    Header Search Paths 作为系统级别路径一定会被搜索
    设 Always Search User Paths 为 YES,编译器会先搜索 User Header Search Paths 路径下的目录
    设 Always Search User Paths 为 NO,编译器不会搜索 User Header Search Paths 路径下的目录「默认」

  • 设置格式举例:$(SRCROOT)/项目名称/AppDelegate.h
    $(SRCROOT) 宏和 $(PROJECT_DIR) 宏都指 xxx.xcodeproj 所在的父目录,新建项目后的目录为:

Paste_Image.png
  • Project 的 Building Settings 中得设置默认并不被 Targets 继承
    只有 Targets 的设置加入了 $(inherited) 时才被继承,添加目录的时候写上 $(inherited) 就表示从 frameworks 里面读取

  • 设置查找路径的参数
    recursive:遍历该目录,编译的时候在找库的路径的时候,会遍历该目录下的所有子目录的库文件
    non-recursive:不遍历该目录「默认,推荐使用,可减少编译速度」

4. 拖拽项目/将项目当做静态库处理

  • 给当前项目在 Link Binary With Libraries 中添加拖拽项目的 库文件
  • 如果当前的 Target 需要依赖其他库文件,在 Target Dependencies 中添加所需的库文件
  • 如果库文件在 Link Binary With Libraries 中已经添加「必要」,但也可能需要在 Target Dependencies 中再次添加「非必要」
Paste_Image.png

5. 其他

  • 查看静态库所支持的 CPU 架构
    在命令行找到静态库所在的文件夹,执行 lipo -info 静态库文件名 命令

  • 合并静态库
    在命令行找到静态库所在的文件夹,执行 lipo -create 静态库1 静态库2 -output 新静态库名称.a 命令

三、打包动态库

1. 制作、编译过程与静态库相同

2. 在 Embedded Binaries 中添加动态库

Paste_Image.png

3. 合并动态库文件

合并动态库文件并非合并的是 .framework 文件,而是其中的二进制代码文件

4. 动态库的使用注意

I. 自定义的 .a 静态库,不可以包含动态库

II. 自定义的 .framework 静态库,可以包含动态库文件

绕过 Xcode 的 UI 界面来连接动态库,步骤如下

  • 项目中不需要引用连接的动态库「.tbd 的动态库」
  • 通过格式:-l<library_name> 添加动态库,例:添加 libiconv.tdb 记为 -liconv
Paste_Image.png

缺陷

  • 虽然自定义的静态库中已经导入了动态库 X.tbd ,但是,当自定义的 framework 的静态库被调用时,可能需要再次导入动态库 X.tbd 到当前项目中
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容