美文网首页
iOS区分静态库和动态库

iOS区分静态库和动态库

作者: CodingTom | 来源:发表于2018-09-03 17:06 被阅读66次
    iOS区分静态库和动态库

    Linked Frameworks and Libraries

    连接一个库(动态库 或 静态库)

    如果连接的是一个静态库

    比如libFoo.a,linker的方式会把这个静态库复制到你最终输出的二进制文件里面去,你不需要在运行时解决任何依赖关系的问题。

    如果连接的是一个动态库

    比如.dylib或者系统的framework(framework跟动态库很像,只不过还包含一些资源文件)。

    运行程序时,会认为这个库是默认就在系统里或者你工程的某个位置的,用到的库会在运行时加载进来。

    这样做的好处是,比如加载的是系统的framework,那么大家的程序在打包生成二进制时都不需要包含这个framework,因为这个framework是系统提供的。

    同样,自己程序包含的动态库,当你的程序有一些相关的扩展程序时,也可以直接使用动态库,而不需要把动态库包含到扩展程序的bundle里面。

    Embedded Binaries

    Embed是把这个库嵌入到最终输出的程序的bundle里面。

    如果连接的是第三方的动态库(比如从github上下载的,或者自己生成的),你就需要对这个库进行embed,然后在进行link。

    这样,在运行时,就会寻找你的程序的bundle,找到这个库并加载进来。

    区别

    Link 后,写代码时,可以导入库的头文件、资源啥的,但是如果没有 Embed,在 App 实际运行时,会找不到这些文件和资源,因为库没有包含到App 的 bundle 里面来。

    那还区分 Link 和 Embed 干啥,直接全部用 Embed 不就完了吗?

    有的时候我们是只需要 Link 而不需要 Embed 的,比如一个 Framework 依赖另外一个 Framework 的时候(Apple 并不提倡这种操作),比如 Framework A 依赖 Framework B,主工程依赖 Framework A,这时在 Framework A 中,只要 Link Framework B,不需要也不能( Xcode 对于 Framework 工程没有对应的操作界面) Embed Framework B,主工程中在同时 Embed Framework A 和 Framework B。

    具体可以看 Embedding Frameworks In An App 的 Apps with Dependencies Between Frameworks 片段

    项目中通过查找:

    Build Settings -> Mach-O Type

    前面提到过,静态库一般是.a文件,动态库一般是.framework文件。为什么说一般,因为静态库也可能没有后缀;.framework文件其实只是个文件夹,真正的二进制文件在.framework里面。.framework里面的二进制文件也可能是静态库,也有可能是动态库。有后缀也可能没有后缀。因此有时候不通过工具很难区分。所以这里推荐一款Mach-O格式文件浏览器:MachOView。

    MachOView下载地址:http://sourceforge.net/projects/machoview/
    MachOView源码地址:https://github.com/gdbinit/MachOView

    CocoaPods 中用 use_frameworks!

    在使用CocoaPods的时候在Podfile里加入use_frameworks! ,那么你在编译的时候就会默认帮你生成动态库,我们能看到每个源码Pod都会在Pods工程下面生成一个对应的动态库Framework的target,我们能在这个target的 Build Settings -> Mach-O Type 看到默认设置是 Dynamic Library。也就是会生成一个动态Framework,我们能在Products下面看到每一个Pod对应生成的动态库。

    这些生成的动态库将链接到主项目给主工程使用,但是我们上面说过动态库需要在主工程target的 General -> Embedded Binaries 中添加才能使用,而我们并没有在Embedded Binaries中看到这些动态库。那这是怎么回事呢,其实是cocoapods已经执行了脚本把这些动态库嵌入到了.app的Framework目录下,相当于在Embedded Binaries加入了这些动态库。我们能在主工程target的Build Phase -> Embed Pods Frameworks里看到执行的脚本。

    所以Pod默认是生成动态库,然后嵌入到.app下面的Framework文件夹里。我们去Pods工程的target里把 Build Settings -> Mach-O Type 设置为Static Library。那么生成的就是静态库,但是cocoapods也会把它嵌入到.app的Framework目录下,而因为它是静态库,所以会报错:unrecognized selector sent to instanceunrecognized selector sent to instance

    lipo命令的用法

    lipo -info xxxx.framework/xxxx或/xxxx.a
    查看信息,支持的cpu架构列表

    lipo -create xxxx xxxx -output xxxx
    整合成Fat文件

    lipo xxxx -thin cpu(armv7/arm64等) -output xxxx
    提取特定的cpu架构的thin文件

    lipo -remove cpu(armv7/arm64等) xxxx -output xxxx
    移除掉特定的cpu架构的文件

    参考连接

    Embedded Binaries 和 Linked Frameworks and Libraries的区别

    https://www.jianshu.com/p/42891fb90304
    https://www.jianshu.com/p/71c75c287d26
    https://www.jianshu.com/p/c2ee22b68593

    相关文章

      网友评论

          本文标题:iOS区分静态库和动态库

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