官方说明

Linking Libraries

链接库的行为是代码依赖管理的一种形式。 当任何应用程序运行时,其可执行代码被加载到内存中。 此外,它所依赖的任何代码库也会加载到内存中。 有两种类型的链接:静态和动态。

Dynamic Linking

动态链接最常用于OS X和iOS。 当动态库链接时,库中的代码都不会直接包含在链接的目标中。 相反,在符号得到解决之前,库会在运行时加载到内存中。 由于代码没有静态链接到可执行二进制文件中,因此在运行时加载有一些好处。 主要的是,这些库可以使用新功能或错误修复进行更新,而无需重新编译和重新链接可执行文件。 此外,在运行时加载意味着各个代码库可以拥有自己的初始化程序,并在从内存中卸载之前清理自己的任务。

For more information on overview and design, see Apple’s Dynamic Library Programming Topics.

Libraries

动态库是一种Mach-O binary1,在应用程序的启动或运行时加载。 由于动态库中的可执行代码并未静态链接到目标可执行文件中,因此在需要重复使用相同代码时,这会减少内存消耗。

由于动态库在运行时被加载,所以库负责告诉链接器需要哪些附加代码。 这消除了管理你使用的所有代码需要操作的负担。

Frameworks

Dynamic frameworksdynamic libraries类似。 两者都是动态链接库,除了dynamic framework是嵌入在一个bundle中的动态库。 这允许对动态库进行版本控制以及对libraries代码使用的其他资源进行排序。

Example

Building

举例:

bar.h

#ifndef __foo__bar__
#define __foo__bar__

#include <stdio.h>

int fizz();

#endif /* defined(__foo__bar__) */

bar.c

#include "bar.h"
#include <CoreFoundation/CoreFoundation.h>

int fizz() {
    CFShow(CFSTR("buzz"));
    
    return 0;
} 

从文件bar.h和bar.c开始。 头文件定义了函数fizz(),它返回一个整数值。 实现文件导入CoreFoundation框架并实现函数fizz在返回0之前打印字符串“buzz”

Compiling:

$  clang -c bar.c -o bar.o

这将创建名为“bar”的对象file2,类型为MH_OBJECT的Mach-O二进制文件。

One of these will be generated for each of the files compiled in the library.

Creating Library:

$ libtool -dynamic bar.o -o libfoo_dynamic.dylib -framework CoreFoundation -lSystem

这会创建dylib(动态库)并链接到libSystem和CoreFoundation.framework。 dylib是一个类型为MH_DYLIB的Mach-O二进制文件。这将在启动时由dyld动态加载,作为另一个二进制文件的依赖关系。

Linking

main.c

#include "bar.h"

int main() {
    return fizz();
}

在这个例子中,为动态库导入“bar.h”头,并直接调用fizz()。

Compiling

$ clang -c main.c -o main.o

This will generate the object file for main.

Linking:

$ ld main.o -lSystem -L. -lfoo_dynamic -o test_dynamic

这将从主目标文件生成一个二进制可执行文件,并且也会传递

  • -lSystem for dyld_stub_binder
  • -lfoo_dynamic for linking against libfoo_dynamic.dylib

Running:

$ ./test_dynamic
buzz

Symbols:

$ nm test_dynamic 
0000000000001000 A __mh_execute_header
                 U _fizz
0000000000001fa0 T _main
                 U dyld_stub_binder

References:

$ otool -L test_dynamic 
test_dynamic:
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
    libfoo_dynamic.dylib (compatibility version 0.0.0, current version 0.0.0)

生成的二进制文件仅链接到libSystem和创建的dylib。 库foo_dynamic负责链接它所需的任何附加库。 这是在发布时动态解决的。 在这种情况下,libfoo_dynamic.dylib的搜索路径将与主要可执行文件的搜索位置相同。 动态库和框架在启动时由动态链接器加载。 它们具有相关的搜索路径,以帮助链接程序找到它们在文件系统上的位置并加载它们。

Static Linking

与动态链接不同,链接静态库包含库中的目标文件代码到目标的二进制文件中。 这会导致更占空间,启动时间更慢。 由于库的代码直接添加到链接目标的二进制文件,这意味着要更新库中的任何代码,链接目标也必须重新构建。

在iOS 8之前,静态链接库是事实上的出货方式,并在应用程序中包含任何第三方代码。

参考出处

https://pewpewthespells.com/blog/static_and_dynamic_libraries.html