打包静态库(源码中包含其他静态库以及开源库)

因为公司最近要把某一个功能模块提供给第三方使用,所以就需要将涉及到的源码打包成静态库(.a文件),但是。。。怎么打包呢,从来没做过啊!谷歌了一上午,找到很多文章,写的都很好,但是很少能有一篇,让你看到就能彻底搞懂的。比如自己源码中包含第三方静态库怎么办?用到的图片资源,Xib资源怎么办?自己源码依赖的第三方库怎么处理才能不影响第三方对相同库的升级及使用?这都是需要考虑的问题。关于静态库的介绍我就不普及了,直接一步步进行.a库的创建:

#一、创建静态库工程

这一步应该是很简单的,比如项目名称取为 YJEChatSDK。


Paste_Image.png

建好之后大概就是这个样子:


Paste_Image.png

把工程里默认添加的类删除(移到废纸篓)就可以了,整个工程很干净!

Paste_Image.png
#二、对工程进行必要的设置

1、支持的系统这里要选择IOS哦(虽然默认就是)。。。

Paste_Image.png

2、Build Active Architecture Only选项,当它设置为Yes时,是为了debug的时候编译速度更快,此时它只编译当前的architecture版本。 而设置为No时,会编译所有的版本。这里我们要设置为NO。

Paste_Image.png

3、如果你的源码中使用了类别(category),就要在 Other Linker Flags 中添加 -ObjC或者-all_load 。

Paste_Image.png

Unix的标准静态库实现和Objective-C的动态特性之间有一些冲突:Objective-C没有为每个函数(或者方法)定义链接符号,它只为每个类创建链接符号。这样当在一个静态库中使用类别来扩展已有类的时候,链接器不知道如何把类原有的方法和类别中的方法整合起来,就会导致你调用类别中的方法时,出现"selector not recognized",也就是找不到方法定义的错误。为了解决这个问题,引入了-ObjC标志,它的作用就是将静态库中所有的和对象相关的文件都加载进来。

本来这样就可以解决问题了,不过在64位的Mac系统或者iOS系统下,链接器有一个bug,会导致只包含有类别的静态库无法使用-ObjC标志来加载文件,变通方法就是使用-all_load 。

4、选择release


Paste_Image.png
Paste_Image.png

到此为止对于工程的基本设置算是完了,当然根据自己的需求也许还有其他的设置。

#三、添加代码文件

注意下,打包静态库的时候并不能包含资源文件,即使我们将资源文件(.png文件或者Xib文件)拷贝到静态库工程中,但实际上这些资源是不会添加到target的,也就是说编译结果中并不包含这些资源,因此如果有人调用你制作的这个静态库,所有的资源(图片、Xib)都是缺失的。

针对这种情况,我们将代码文件和资源文件分开考虑,首先是代码文件的打包:
1、添加自己的代码和私有库
把自己的源码以及私有库(不包括第三方开源库,因为开源库谁都可以去下载使用,没必要也不应该打包进去)放到工程中。

如果你的源码或者私有库又使用了第三方的静态库,打包的时候并不能静态库中包含静态库,所以只需要把第三方静态库的头文件放进我们的工程就好,而不需要将.a文件也添加进来。需要注意的是,最后使用时,要把我们的.a库和第三方的这个.a库一起放进项目。

Paste_Image.png

2、添加依赖的开源库
如果我们的源码依赖一些开源库,比如AFNetWorking,Mansory等,就需要将它们打包进来,不过这样一来,容易给使用者带来问题,比如开源库的冲突,版本不兼容等。

所以我的处理办法是,只添加这些开源库的头文件,然后告诉使用者我们的静态库是依赖这些开源库的,让他们自己下载相应的框架。这样做的好处是,方便第三方使用者随意升级自己的开源库而不用担心会跟静态库中的开源库引起冲突,而且就算使用者升级了开源库的版本,也一般不会改变头文件里面的接口(高版本总会兼容低版本),所以不会影响我们的静态库。

Paste_Image.png

3、暴露出相应的接口(头文件),供第三方使用
我们打包静态库肯定是要给人用的,所以需要暴露出设计好的头文件供别人使用。静态工程里需要编译的所有源文件都会包含在Compile Source中,如下图所示:

Paste_Image.png

而需要暴露出来的头文件添加在Copy Files选项中,如下图所示:

Paste_Image.png

到此为止基本上完成了打包的准备工作,下面开始编译。

#四、编译生成静态库

根据需要,如果要在模拟器下使用静态库,编译时就选择模拟器,在真机中使用,编译时就选择真机。


Paste_Image.png
Paste_Image.png

这里我在模拟器和真机下分别运行了一次,得到两个.a文件,真机和模拟器:

Paste_Image.png

一般将静态库给别人使用时,要同时给真机版和模拟器版,给两个文件肯定是不方便的,所以要把两个版本合并为一个.a文件,这样不管真机还是模拟器,都可以运行。

打开终端,可以先查看下.a库支持的架构,输入 lipo -info 静态库路径,静态库路径这里直接把文件拖进来就好。

Paste_Image.png

很显然,armv7和arm64表示32位和64位真机,i386和x86_64表示32位和64位模拟器(mac的架构)。下面使用命令将真机版和模拟器版本合并:
lipo -create 静态库路径1 静态库路径2 -output /Users/yangjie/Desktop/YJEChatSDK.a

Paste_Image.png

最终得到需要的YJEChatSDK.a文件。

#处理资源文件(图片.png和Xib文件)

*首先仅考虑图片
如果代码中使用了一些图片资源,怎么样才能正确读取这些图片呢?我的做法是(我不太清楚是不是还有其他办法):在桌面新建一个文件夹,将用到的所有图片放进去,然后把文件夹的名字改为:文件名称.Bundle。比如我这里就改为YJsdkBundle.Bundle。这样在使用静态库时,直接将该Bundle文件一起放进工程就可以了。

Paste_Image.png

然而这样还是不行的,因为静态库中的代码依然找不到图片资源的路径,所以还是不能正确加载。我们需要重新返回代码,在代码中添加两个宏定义:

define BUNDLE_PATH [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"YJsdkBundle.Bundle"]
define YJImageNamed(imageName)  ([UIImage imageNamed:[NSString stringWithFormat:@"%@/%@",BUNDLE_PATH,imageName]])

将所有加载图片的方法[UIImage imageNamed:]替换为我们定义的宏,比如我这里是YJImageNamed(图片名称),需要注意的是,图片名称要跟Bundle文件中图片名称对应(后缀@2x或者@3x不用加)。我这里的Bundle文件内并没有子文件夹,所以宏定义中,stringWithFormat:@"%@/%@",BUNDLE_PATH,imageName这么写,如果你的Bundle文件下还有子文件夹,应该这么写:
stringWithFormat:@"%@/文件夹名称/%@",BUNDLE_PATH,imageName

这样,图片就可以正确加载了!

关于Xib文件
对于Xib文件,我并没有亲自尝试,所以。。。没有发言权了,大家可以谷歌一下。(
__*)

打包好之后,使用时编译连接错误问题:

Paste_Image.png
Paste_Image.png

类似这种奇怪的错误,我遇到了,原因是,1、没有引入必要的系统框架。2、静态库已经包含了某些文件,使用的时候,又引入了这些文件,造成duplicate错误。

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

推荐阅读更多精彩内容