zoukankan      html  css  js  c++  java
  • 静态库、动态库的区别汇总

     

    real framework中不可以使用类别 或 不可以不包含类文件

    real framework 中直接调用NSClassFromString函数会返回null  需要强制加载指定类 或 直接通过类名引用

    linux中静态库和动态库的区别

    一、不同

    库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。 

    1. 静态函数库

        这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个 函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

    2. 动态函数库

        这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。

    二、相同

    都是由*.o目标文件生成

    ios 开发中 动态库 与静态库的区别

    使用静态库的好处

    1,模块化,分工合作

    2,避免少量改动经常导致大量的重复编译连接

    3,也可以重用,注意不是共享使用

    动态库使用有如下好处:

    1使用动态库,可以将最终可执行文件体积缩小

    2使用动态库,多个应用程序共享内存中得同一份库文件,节省资源

    3使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的。

    从1可以得出,将整个应用程序分模块,团队合作,进行分工,影响比较小。

    等其他好处,

    从2可以看出,其实动态库应该叫共享库,那么从这个意义上来说,苹果禁止iOS开发中使用动态库就可以理解了:

    因为在现在的iPhone,iPodTouch,iPad上面程序都是单进程的,也就是某一时刻只有一个进程在运行,那么你写个共享库,

            ----共享给谁?(你使用的时候只有你一个应用程序存在,其他的应该被挂起了,即便是可以同时多个进程运行,别人能使用你的共享库里的东西吗?你这个是给你自己的程序定制的。)

            ----目前苹果的AppStore不支持模块更新,无法更新某个单独文件(除非自己写一个更新机制:有自己的服务端放置最新动态库文件)

    至于苹果为啥禁止ios开发使用动态库我就猜到上面俩原因

    深入理解iPhone静态库

           在实际的编程过程中,通常会把一些公用函数制成函数库,供其它程序使用,一则提搞了代码的复用;二则提搞了核心技术的保密程度。所以在实际的项目开发中,经常会使用到函数库,函数库分为静态库和动态库两种。和多数人所熟悉的动态语言和静态语言一样,这里的所谓静态和动态是相对编译期和运行期的:静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。

      iPhone官方只支持静态库联编。

    深入理解framework(框架,其实相当于静态框架,不是动态库)

    打包framework还是一个比较重要的功能,可以用来做一下事情:

    (1)封装功能模块,比如有比较成熟的功能模块封装成一个包,然后以后自己或其他同事用起来比较方便。

    (2)封装项目,有时候会遇到这个情况,就是一家公司找了两个开发公司做两个项目,然后要求他们的项目中的一个嵌套进另一个项目,此时也可以把呗嵌套的项目打包成framework放进去,这样比较方便。

    我们为什么需要框架(Framework)?

    要想用一种开发者友好的方式共享库是很麻烦的。你不仅仅需要包含库本身,还要加入所有的头文件,资源等等。

    苹果解决这个问题的方式是框架(framework)。基本上,这是含有固定结构并包含了引用该库时所必需的所有东西的文件夹。不幸的是,iOS禁止所有的动态库。同时,苹果也从Xcode中移除了创建静态iOS框架的功能。

    Xcode仍然可以支持创建框架的功能,重启这个功能,我们需要对Xcode做一些小小的改动。

    把代码封装在静态框架是被app store所允许的。尽管形式不同,本质上它仍然是一种静态库。

    框架(Framework)的类别

    大部分框架都是动态链接库的形式。因为只有苹果才能在iOS设备上安装动态库,所以我们无法创建这种类型的框架。

    静态链接库和动态库一样,只不过它是在编译时链接二进制代码,因此使用静态库不会有动态库那样的问题(即除了苹果谁也不能在iOS上使用动态库)。

    “伪”框架是通过破解Xcode的目标Bundle(使用某些脚本)来实现的。它在表面上以及使用时跟静态框架并无区别。“伪”框架项目的功能几乎和真实的框架项目没有区别(不是全部)。

    “嵌入”框架是静态框架的一个包装,以便Xcode能获取框架内的资源(图片、plist、nib等)。

    本次发布包括了创建静态框架和“伪”框架的模板,以及二者的“嵌入”框架。

    用哪一种模板?

    本次发布有两个模板,每个模板都有“强”“弱”两个类别。你可以选择最适合一种(或者两种都安装上)。

    最大的不同是Xcode不能创建“真”框架,除非你安装静态框架文件xcspec在Xcode中。这真是一个遗憾(这个文件是给项目使用的,而不是框架要用的)。

    简单第

    简单说,你可以这样决定用哪一种模板:

    • 如果你不想修改Xcode,那么请使用“伪”框架版本
    • 如果你只是想共享二进制(不是项目),两种都可以
    • 如果你想把框架共享给不想修改Xcode的开发者,使用“伪”框架版本
    • 如果你想把框架共享给修改过Xcode的开发者,使用“真”框架版本
    • 如果你想把框架项目作为另一个项目的依赖(通过workspace或者子项目的方式),请使用“真”框架(或者“伪”框架,使用-framework——见后)
    • 如果你想在你的框架项目中加入其他静态库/框架,并把它们也链接到最终结果以便不需要单独添加到用户项目中,使用“伪”框架

    “伪”框架

    “伪”框架是破解的“reloacatable object file”(可重定位格式的目标文件, 保存着代码和数据,适合于和其他的目标文件连接到一起,用来创建一个可执行目标文件或者是一个可共享目标文件),它可以让Xcode编译出类似框架的东西——其实也是一个bundle。

    “伪框架”模板把整个过程分为几个步骤,用某些脚本去产生一个真正的静态框架(基于静态库而不是reloacatable object file)。而且,框架项目还是把它定义为wrapper.cfbundle类型,一种Xcode中的“二等公民”。

    因此它跟“真”静态框架一样可以正常工作,但当存在依赖关系时就有麻烦了。

    依赖问题

    如果不使用依赖,只是创建普通的项目是没有任何问题的。但是如果使用了项目依赖(比如在workspace中),Xcode就悲剧了。当你点击“Link Binary With Libraries”下方的’+’按钮时,“伪框架”无法显示在列表中。你可以从你的“伪”框架项目的Products下面将它手动拖入,但当你编辑你的主项目时,会出现警告:

    warning: skipping file '/somewhere/MyFramework.framework' (unexpectedfile type 'wrapper.cfbundle' in Frameworks & Libraries build phase)

    并伴随“伪”框架中的链接错误。

    幸运的是,有个办法来解决它。你可以在”Other Linker Flags”中用”-framwork”开关手动告诉linker去使用你的框架进行链接:

    -framework MyFramework

    警告仍然存在,但起码能正确链接了。

    添加其他的库/框架

    如果你加入其他静态(不是动态)库/框架到你的“伪”框架项目中,它们将“链接”进你最终的二进制框架文件中。在“真”框架项目中,它们是纯引用,而不是链接。

    你可以在项目中仅仅包含头文件而不是静态库/框架本身的方式避免这种情况(以便编译通过)。

    “真”框架

    “真”框架各个方面都符合“真”的标准。它是真正的静态框架,正如使用苹果在从Xcode中去除的那个功能所创建的一样。

    为了能创建真正的静态框架项目,你必需在Xcode中安装一个xcspec文件。

    如果你发布一个“真”框架项目(而不是编译),希望去编译这个框架的人必需也安装xcspec文件(使用本次发布的安装脚本),以便Xcode能理解目标类型。

    注意:如果你正在发布完全编译的框架,而不是框架项目,最终用户并不需要安装任何东西。

    我已经提交一个报告给苹果,希望他们在Xcode中更新这个文件,但那需要一点时间.OpenRadarlink here

    加其他静态库/框架

    如果你加入其他静态(不是动态)库/框架到你的“真”框架项目,它们只会被引用,而不会象“伪”框架一样被链接到最终的二进制文件中。

    从早期版本升级

    如果你是从Mk6或者更早的版本升级,同时使用“真”静态框架,并且使用Xcode4.2.1以前的版本,请运行uninstall_legacy.sh以卸载早期用于Xcode的所有修正。然后再运行install.sh,重启Xcode。如果你使用Xcode4.3以后,只需要运行install.sh并重启Xcode。

    安装

    分别运行Real Framework目录或Fake Framework目录下的install.sh脚本进行安装(或者两个你都运行)。

    重启Xcode,你将在新项目向导的Framework&Library下看到StaticiOS Framework(或者Fake Static iOS Framework)。

    卸载请运行unistall.sh脚本并重启Xcode。

    创建一个iOS框架项目

    1. 创建新项目。
    2. 项目类型选择Framework&Library下的Static iOS Framework(或者Fake Static iOS Framework)。
    3. 选择“包含单元测试”(可选的)。
    4. 在target中加入类、资源等。
    5. 凡是其他项目要使用的头文件,必需声明为public。进入target的Build Phases页,展开Copy Headers项,把需要public的头文件从Project或Private部分拖拽到Public部分。

    编译你的 iOS 框架

    1. 选择指定target的scheme
    2. 修改scheme的Run配置(可选)。Run配置默认使用Debug,但在准备部署的时候你可能想使用Release。
    3. 编译框架(无论目标为iOS device和Simulator都会编译出相同的二进制,因此选谁都无所谓了)。
    4. 从Products下选中你的framework,“show in Finder”。

    在build目录下有两个文件夹:(yourframework).framework and (your framework).embeddedframework.

    如果你的框架只有代码,没有资源(比如图片、脚本、xib、coredata的momd文件等),你可以把(yourframework).framework 分发给你的用户就行了。如果还包含有资源,你必需分发(your framework).embeddedframework给你的用户。

    为什么需要embedded framework?因为Xcode不会查找静态框架中的资源,如果你分发(your framework).framework, 则框架中的所有资源都不会显示,也不可用。

    一个embedded framework只是一个framework之外的附加的包,包括了这个框架的所有资源的符号链接。这样做的目的是让Xcode能够找到这些资源。

    使用iOS 框架

    iOS框架和常规的Mac OS动态框架差不多,只是它是静态链接的而已。

    在你的项目中使用一个框架,只需把它拖仅你的项目中。在包含头文件时,记住使用尖括号而不是双引号括住框架名称。例如,对于框架MyFramework:

    #import <MyFramework/MyClass.h>

    使用问题

    Headers Not Found

    如果Xcode找不到框架的头文件,你可能是忘记将它们声明为public了。参考“创建一个iOS框架项目”第5步。

    No Such Product Type

    如果你没有安装iOS Universal Framework在Xcode,并企图编译一个universal框架项目(对于“真”框架,不是“假”框架),这会导致下列错误:

    target specifies product type 'com.apple.product-type.framework.static',but there's no such product type for the 'iphonesimulator' platform

    为了编译“真”iOS静态框架,Xcode需要做一些改动,因此为了编译“真”静态框架项目,请在所有的开发环境中安装它(对于使用框架的用户不需要,只有要编译框架才需要)。

    The selected run destination is not valid for this action

    有时,Xcode出错并加载了错误的active设置。首先,请尝试重启Xcode。如果错误继续存在,Xcode产生了一个坏的项目(因为Xcode4的一个bug,任何类型的项目都会出现这个问题)。如果是这样,你需要创建一个新项目重来一遍。

    链接警告

    第一次编译框架target时,Xcdoe会在链接阶段报告找不到文件夹:

    ld: warning: directory not found for option'-L/Users/myself/Library/Developer/Xcode/DerivedData/MyFramework-ccahfoccjqiognaqraesrxdyqcne/Build/Products/Debug-iphoneos'

    此时,可以clean并重新编译target,警告会消除。

    Core Data momd not found

    对于框架项目和应用程序项目,Xcode会以不同的方式编译momd(托管对象模型文件)。Xcode会简单地在根目录创建.mom文件,而不会创建一个.momd目录(目录中包含VersionInfo.plist和.mom文件)。

    这意味着,当从一个embedded framework的model中实例化NSManagedObjectModel时,你必需使用.mom扩展名作为model的URL,而不是采用.momd扩展名。

    NSURL *modelURL = [[NSBundle mainBundle]URLForResource:@"MyModel" withExtension:@"mom"];

    Unknown class MyClass in Interface Builder file.

    由于静态框架采用静态链接,linker会剔除所有它认为无用的代码。不幸的是,linker不会检查xib文件,因此如果类是在xib中引用,而没有在O-C代码中引用,linker将从最终的可执行文件中删除类。这是linker的问题,不是框架的问题(当你编译一个静态库时也会发生这个问题)。苹果内置框架不会发生这个问题,因为他们是运行时动态加载的,存在于iOS设备固件中的动态库是不可能被删除的。

    有两个解决的办法:

         让框架的最终用户关闭linker的优化选项,通过在他们的项目的Other Linker Flags中添加-ObjC和-all_load。

         在框架的另一个类中加一个该类的代码引用。例如,假设你有个MyTextField类,被linker剔除了。假设你还有一个MyViewController,它在xib中使用了MyTextField,MyViewController并没有被剔除。你应该这样做:

    在MyTextField中:

    + (void)forceLinkerLoad_ {}

    在MyViewController中:

    +(void) initialize {     [MyTextField forceLinkerLoad_]; }

    他们仍然需要添加-ObjC到linker设置,但不需要强制all_load了。

    第2种方法需要你多做一点工作,但却让最终用户避免在使用你的框架时关闭linker优化(关闭linker优化会导致object文件膨胀)。

    unexpected file type 'wrapper.cfbundle' in Frameworks &Libraries build phase

    这个问题发生在把“假”框架项目作为workspace的依赖,或者把它当作子项目时(“真”框架项目没有这个问题)。尽管这种框架项目产生了正确的静态框架,但Xcode只能从项目文件中看出这是一个bundle,因此它在检查依赖性时发出一个警告,并在linker阶段跳过它。

    你可以手动添加一个命令让linker在链接阶段能正确链接。在依赖你的静态框架的项目的OtherLinker Flags中加入:

    -framework MyFramework

    警告仍然存在, 但不会导致链接失败。

    Libraries being linked or not being linked into the finalframework

    很不幸, “真”框架和“假”框架模板在处理引入的静态库/框架的工作方式不同的。

    “真”框架模板采用正常的静态库生成步骤,不会链接其他静态库/框架到最终生产物中。

    “假”框架模板采用“欺骗”Xcode的手段,让它认为是在编译一个可重定位格式的目标文件,在链接阶段就如同编译一个可执行文件,把所有的静态代码文件链接到最终生成物中(尽管不会检查是否确实目标代码)。为了实现象“真”框架一样的效果,你可以只包含库/框架的头文件到你的项目中,而不需要包含库/框架本身。

    Unrecognized selector in (some class with a category method)

    如果你的静态库或静态框架包含了一个模块(只在类别代码中声明,没有类实现),linker会搞不清楚,并把代码从二进制文件中剔除。因为在最终生成的文件中没有这个方法,所以当调用这个类别中定义的方法时,会报一个“unrecognizedselector”异常。

    要解决这个,在包含这个类别的模块代码中加一个“假的”类。linker发现存在完整的O-C类,会将类别代码链接到模块。

    我写了一个头文件 LoadableCategory.h,以减轻这个工作量:

    #import "SomeConcreteClass+MyAdditions.h"

    #import "LoadableCategory.h"  MAKE_CATEGORIES_LOADABLE(SomeConcreteClass_MyAdditions);   @implementation SomeConcreteClass(MyAdditions)

      ... 

    @end

    在使用这个框架时,仍然还需要在Build Setting的Other Linker Flags中加入-ObjC。

    执行任何代码前单元测试崩溃

    如果你在Xcode4.3中创建静态框架(或库)target时,勾选了“withunit tests”,当你试图运行单元测试时,它会崩溃:

    Thread 1: EXC_BAD_ACCESS (code=2, address=0x0) 0 0x00000000 --- 15 dyldbootstrap:start(...)

    这是lldb中的一个bug。你可以用GDB来运行单元测试。编辑scheme,选择Test,在Info标签中将调试器Debugger从LLDB改为GDB。

  • 相关阅读:
    CodeForces 785D Anton and School
    CodeForces 785C Anton and Fairy Tale
    CodeForces 785B Anton and Classes
    CodeForces 785A Anton and Polyhedrons
    爱奇艺全国高校算法大赛初赛C
    爱奇艺全国高校算法大赛初赛B
    爱奇艺全国高校算法大赛初赛A
    EOJ 3265 七巧板
    EOJ 3256 拼音魔法
    EOJ 3262 黑心啤酒厂
  • 原文地址:https://www.cnblogs.com/sytfyf/p/4649176.html
Copyright © 2011-2022 走看看