美文网首页iOS开发技巧iOS ReviewiOS技术专题
ios打包静态库,看这篇就够了

ios打包静态库,看这篇就够了

作者: 夜_阑珊 | 来源:发表于2016-10-21 11:06 被阅读13604次

一、前言

前段时间看的一本书上说:“隔着一段距离看,很多有趣的知识看起来都很唬人。”比如说这篇我要总结的“静态库知识”,在我初出茅庐的时候着实觉得那些后缀名为“.frameworke”、“.a”、“.dylib”的文件很神秘,很高冷。那时我虽然知道只要导入一个库就能引用库里面很多封装好的东西,但对这个“库”究竟是什么“鬼”,一直都是云里雾里。好了废话不多说,看下去就知道它是个什么“鬼”。

二 、一些概念的补充

1、 什么是库?

所谓库就是程序代码的集合,是共享程序代码的一种方式。

2、 库的分类

根据程序代码的开源情况,库可以分为两类

  • 开源库
    源代码是公开的,你可以看到具体实现。比如GitHub上比较出名的第三方框架AFNetworking、SDWebImage。
  • 闭源库
    不公开源代码,只公开调用的接口,看不到具体的实现,是一个编译后的二进制文件。这种常见于一些公司的SDK包,比如高德地图SDK、环信即时通讯SDK等等。而闭源库又分为两类:静态库和动态库。本篇重点要讲的便是其中的静态库。

3、静态库和动态库的存在形式和使用区别

存在形式:

  • 静态库
    以".a"或者“.framework”为文件后缀名
  • 动态库
    以".dylib"或者“.framework”为文件后缀名

使用区别:

  • 静态库链接时会被完整的复制到可执行文件中,被多次使用就有多份拷贝。
静态库被程序使用时
  • 动态库链接时不复制,程序运行时由系统动态加载到内存,供程序调用。而且系统只加载一次,多个程序共用,节省内存。
动态库被程序使用时

4、iOS 设备的CPU架构

  • 模拟器:
    4s-5: i386
    5s-7 Plus: x86_64

  • 真机(iOS设备):
    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的架构上运行)
    arm64: iPhone 5s、iPhone 6、iPhone 6 Plus、iPhone 6s、iPhone 6s Plus、iPad Air、iPad Air2、iPad mini2、iPad mini3

:真机iPhone7、iPhone7 Plus A10处理器到底是什么架构暂时不得而知,没查到相关资料,貌似还没公布,但是模拟器是x86_64。

三、打包静态库

因为静态库存在两种形式,我们先看.a静态库的打包

  • .a文件静态库打包

1、打开Xcode创建一个新的工程,这里以Xcode8为例,选择工程如下:

创建一个新的工程

2、创建工程完毕后,再创建一个工具类StaticLibTool,添加一个方法用于测试


创建一个工具类,添加测试方法

StaticLibTool.m文件实现如下

taticLibTool.m文件实现

3、运行工程进行打包

运行工程打包

运行完毕后,我们会看到工程中Products文件夹下的libStaticLib.a文件由红色变成了黑色。右键show in finder可以在其目录下找到它。这就是我们打包好的.a静态文件了。

打包好的.a静态文件

但是这样就完了吗?当然没有,我们知道静态库存在的最大意义是隐藏代码的具体实现,但是这也隐藏的太彻底了,总要公开些接口或者头文件供人调用吧。

4、公开接口头文件

targets->Build Phases->Copy Files->"+"你需要公开的头文件

这里我们把新建的测试类StaticLibTool.h公开


公开接口头文件

公开头文件后,我们再按上述1、2、3流程重新运行打包,我们会得到一个头文件和一个.a静态库(如下图),而这正是我们所需要的。

重新运行打包

5、新建一个可运行的工程,把这两个打包好的文件拖入项目测试

测试

选择Iphone7模拟器运行,程序正常运行,点击模拟器屏幕,打印日志如下:

日志输出

我们可以看到输出没有问题,打包.a静态库大功告成。

但是,别高兴的太早。当我把模拟器切换成Iphone5运行时,编译直接不通过,报错如下:

iPhone 5模拟器运行时的编译错误

上图“Undefined symbols for architecture i386”是什么意思呢?意思是我们的libStaticLib.a静态库不支持i386架构。那i386又是什么鬼?不清楚的可以拉上去看“iOS 设备的CPU架构”,这里就不多做解释了。

iPhone 5模拟器正好是i386架构,而我们打包的静态库不支持。但是iPhone 7模拟器运行却没有问题,这说明我们打包的静态库正好支持iPhone 7模拟器 的cpu架构 x86_64。如何查看静态库所支持的架构,请看下一步。

6、终端查看静态库所支持的架构

终端->cd进入库文件路径->lipo -info 库名


终端查看静态库所支持的架构

上图可以看到,我们的静态库仅支持x86_64架构,也就是说此静态库只可运行在iphone5s-iphone7plus之间的模拟器设备。所以刚才我们运行iphone5模拟器时,编译会报错。

到这里就可以进一步解释下,打包静态库时,你用什么模拟器运行,打包出来的静态库就支持什么模拟器的架构,而刚才我打包时是用iPhone7运行,所以仅支持架构x86_64。那么这就太麻烦了,可以打包一个静态库支持多种架构的模拟器吗?答案是肯定的,请看下一步。

7、设置适配所有模拟器架构

project -> buildSeting -> Build Active Architecture Only 设为NO

设置适配所有模拟器架构

设置完成后,我们重新运行打包静态库文件(这时你可随便选一个模拟器),按照上述第6步终端查看其支持的架构,我们可以看到终端输出的结果是同时支持 i386和x86_64,这也就意味着同时支持所有模拟器。

到这里打包.a静态库已经告一段落,但是按上述流程打包的只能在模拟器上跑,真机是不能运行的,因为ios真机设备跟模拟器的架构又不一样(怎么不一样自己拉上去看),所以还没完(我也不想啊 ),请看下一步

8、打包支持真机架构的静态库

所有流程都跟上面的一样,只是我们运行打包时要选择真机运行,如下图你可以选择自己插上去的真机,也可以选择Generic ios Devices。当然不要忘记了设置支持所有真机机型架构: Build Active Architecture Only 设为NO。


打包支持真机架构的静态库

我们可以看下打包出来的终端查看结果如下:

终端输出结果

上图可以看到同时支持armv7和arm64,也就是支持所有ios设备。好了到此打包.a静态库算是告一段落。

  • .frameworke文件静态库打包

1、依然Xcode创建一个新的工程FrameworkeLib,选择工程如下:

创建一个新的工程

创建完成后我们可以看到,工程本身自带一个FrameworkeLib.h文件,这是类似一个主头文件一样的东西

FrameworkeLib.h文件

2、创建需要测试的类,为了方便我把上述打包.a的测试类StaticLibTool直接拖来使用。

3、设置支持所有模拟器架构或真机架构(和打包.a第7步骤一样)

4、公开头文件

target-Build Phases - Headers -把需要公开的头文件从project拖入Public

暴露头文件

5、设置打包的是静态库。因为动态库也可以是以framework形式存在,所以需要设置,否则默认打出来的是动态库

target->BuildSetting ->搜索关键字mach->Mach-o Type 设为Static Library(这个默认选项是动态的)

设置打包的是静态库

6、选中真机或模拟器运行设备打包(与打包.a一样),完成后Products文件夹下的FrameworkeLib.framework文件由红色变成了黑色,右键show in finder 显示如下:

打包结果

FrameworkeLib.framework拖入项目便可直接使用,这里就不再进行测试了。此外还要补充的一点是,打包静态库的时候还需注意打包的是测试版(Debug)还是发布版(Release),这个根据你自己的需求决定,而如何进行设置请下一步骤。

7、设置打包静态库的测试版和发布版(.a和.frameworke)

product -> scheme -> Edit scheme -> Run->选择Debug或Release

设置版本

三 、END

相关文章

网友评论

  • KeyboardLife:你们的教程都是没有用cocopod情况,请问cocoapod引入第三方改如何打包,我发现跟你这个有点不一样
  • 沃小沃:亲问下,我打包的一个静态库包括bundle,然后集成一个demo里 bundle里的图片是可以显示的,当我二次打包静态库,这个静态库包含第一次打包的.a和bunle 再次集成到demo 但是原来bundle里的图片就不显示了,请问下这个该怎么解决
  • 须臾以北____:如何将一个带有.a的工程打包进静态库呢,头文件暴露不出来的
  • f170d29955a5::sob: 大神,我生产了支持模拟器的.a文件和支持真机的.啊文件,然后合并成一个,拖入工程中真机和模拟器都行,但是点菜单栏的Product - Archive打包的时候失败了,也不出现红色的报错信息,直接提示失败,这是咋回事啊?
  • 瞬间看见永远:可以把整个工程打成静态包,抛出一个接口让别人用吗
    刀神:层主 你实现了吗 我现在也有一个这样的需求
  • LD_左岸:图片资源怎么引用
  • LD_左岸:如果我的frameWork工程里需要用到AFNetworking
    我外界的工程里也用到了AFNetworking
    这样我把frameWork导入我的工程 是不是报错 link错误
    这有办法解决吗....
  • 热血足球2016:设置了Build Active Architecture Only 设为NO relase版本,然后检测包里还是没有armv7,求指点卡主了
  • 一一雪液一一:看到的写的最有逻辑,语义和步骤最通俗易懂的一篇,,,,不错.
    天山雪莲_38324:图文并茂,很详细,非常好,按照文中的操作步骤来,success! :blush:
    夜_阑珊:哈哈,谢谢肯定!其实打赏大可不必,喜欢点个赞就好了!我也想不到这篇文章后会进入百度搜索“ios打包静态库”排在第一的位置,其实没啥技术含量,只不过是我用了比较清晰的逻辑把它表达出来了而已。:smile:
  • 维维豆奶1991:只要吧.a 导入到项目就一直报错link command错误,怎么回事
  • Hello_kid:Mach-o type 只能选择静态库吗, 不是说苹果允许用动态库了吗? header 里的Project选项可以添加头文件吗
  • ba22fb5d4bdb:.a 文件里面如何设置pch文件呢? 主要是想SDK里面也可以像工程一样
  • 乐视薯片:怎么给sdk设置版本号啊?
  • 双湾:用lipo -info 查看framework已经有armv7和arm64,但是在其他项目中使用时还是出现Undefined symbols for architecture arm64错误。
  • 芷依儿:我编译成功,可是.a一直是红色的。。。
    陨之希留leo:我也是,虽然也可以在 show in finder 里找到,不过好像不大对.
  • 沃小沃:您好,我现在也需要打包.a 文件,但是打包.a文件里包含其他的第三方的.a文件,请问能打包吗,能的话怎么打包
    b57bc247097e:@陨之希留leo 有解决么
    陨之希留leo:我最近也是这个需求,请问你现在解决了嘛~
  • 再剪开一夜风雨:合并操作:bogon:~ zhangzhen$ lipo -create /所在路径/Release-iphoneos/libMyStaticLibraryDemo.a /所在路径/Release-iphonesimulator/libMyStaticLibraryDemo.a -output /Users/zhangzhen/Desktop/libUniversal.a
    bogon:~ zhangzhen$
  • 风语随风:包含第三方库文件怎么打包?
    b57bc247097e:@沃小沃 有解决么
    沃小沃:您好,请问你解决了码,我现在也需要打包.a 文件,但是打包.a文件里包含其他的第三方的.a文件
  • Amor瑾年v:话说我是个小白,我有个很幼稚的我呢提想问一下,希望楼主能仔细给我说一下。ios打包成静态库或者动态库有什么用啊,或者说什么时候需要打包。还有OC 和Swift有什么区别。谢谢楼主了
    Amor瑾年v:@夜_阑珊 非常感谢楼主的认真回复 你写的文章很好 不光是技术文章,还有一些学习方法,读书笔记,我很喜欢
    夜_阑珊:如果你们公司是搞SDK开发的,那么这个太有用了。或者你想写一些自己的代码库又不想别人看到你的代码实现,可以打包静态库,再或者有些代码库文件数量巨大,直接拖入工程总归不好,也最好是打包成静态库,方便使用。OC 和Swift的最大区别是oc是基于运行时的一门动态语言,swift是一门静态语言。其他的详细区别那就够写本书了,这里也没法说。但是swift很多框架还是照搬oc的,比如Fundation、UIKit等等。你有oc的基础学swift就跟切菜一样
  • 70f4a494c3db:请楼主看到后尽快回复。谢谢
    MrZombie:@玉随风 那就把那个自定义的头文件也暴露出来试试?
    70f4a494c3db:@夜_阑珊 都是自己的,自定义的其他类的头文件
    夜_阑珊:@玉随风 其他被隐藏的头文件是指其他库公开的头文件吗
  • 70f4a494c3db:我要暴露的头文件里面有其他被已经隐藏的头文件,这样打的包移动到新工程会报错啊,怎么解决
  • 晓折:写的真好,感谢楼主。刚大致看了一下,晚上回去细细品味一下。也试着做几个试试。
  • DDingDreams:逻辑清晰易懂,不错
  • 九林:赞一个👍
  • 白水灬煮一切:很不错的博文
  • 游泳帽:请问一下楼主,模拟器生成的只支持模拟器,真机生成的只支持真机吗?这样的话在开发项目的时候用到静态库在模拟器调试阶段,真机调试阶段,真机发布阶段都应该引用哪个版本的静态库?谢谢啦
    夜_阑珊:@游泳帽 是的,模拟器跟真机的CPU架构不一样,打出来的静态库也就只能支持各自的。当然你也可以把他们分别打出来的静态库用终端进行合并,这样的话就能支持两种,但是不推荐,因为没必要,合并后的库的大小是原来的两倍,对于有些很大的库来说是致命的。真机调试和真机发布切换成对应的Debug和release打包就好了,文中已经写清楚了。
  • 管家頗:顶一波
  • 暴走大牙:第七步不推荐,如果调试每次也打多个平台浪费时间。打包应该是build里面选择打包,还会做strip,
  • 践行者:framework打包可以用聚合
  • ldldlkdldld:不错 很详细
  • 对歌当酒:非常好!👍
    夜_阑珊:@对歌当酒 :smile:谢谢夸奖
  • de1455ab66d4:写的很好噢~补充一下,把模拟器的包和真机的包合成可以用这个命令:
    lipo -creat deskTop/xxx.a deskTop/yyy.a -output destTop/new.a
    upcode:因为我在想,把四者打成一个包,岂不是在哪种环境都可以用了。
    upcode:那如何将 debug 版本模拟器的包和真机的包,还有release 版本模拟器和真机的包 四者同时打成一个包呢?
    夜_阑珊:@Wayhouse 哈哈,谢谢补充!当时嫌麻烦,就没写合并这一块了:smile:
  • soulDxl:很详细 :+1: ,准备试试看。
    夜_阑珊:@soul1993 嗯,一定要动手操作才更深刻哦:blush:
  • iOS撒旦:准备试验一下
    夜_阑珊:@iOS撒旦 oc的话肯定用静态库,因为使用动态库的话貌似审核不能通过。但swift必须使用动态库
    iOS撒旦:@夜_阑珊 刚玩了一下,谢谢你的分享,想问楼主一个问题,我现在想把以前工程里的友盟分享和第三方登录的打包,应该选用静态库还是动态库呢?
    夜_阑珊:@iOS撒旦 嗯,最好是亲自动手试试
  • f680dfb8c555:写的很好:+1:🏻
    夜_阑珊:@_silenceZ 谢谢肯定:blush:
  • 酷酷的哀殿:“库就是程序代码的集合” 这里的“库”对应的英文单词是什么?
    夜_阑珊:@酷酷的哀殿 相信这个单词或者它的缩写Lib你不会陌生
    酷酷的哀殿:@夜_阑珊 嗯嗯
    夜_阑珊:@酷酷的哀殿 library
  • DrunkenMouse:写的很详细,楼主辛苦了。
    夜_阑珊:@DrunkenMouse 谢谢支持 :smile:
  • 海浪萌物:写的不错,很详细
    夜_阑珊:@海浪萌物 谢谢支持
  • 随心吧:不错,楼主费心了
    夜_阑珊:@iOS开发学习与分享zwj :blush:
  • LeoZzz:最近也用到.a库 lz 写的不错
    夜_阑珊:@GlKing :stuck_out_tongue_winking_eye:谢谢肯定

本文标题:ios打包静态库,看这篇就够了

本文链接:https://www.haomeiwen.com/subject/qnzzyttx.html