为什么iOS框架依赖项在为应用程序项目执行时不需要显式链接到静态库项目或框架项目?

Hal*_*lle 6 xcode gcc objective-c llvm static-libraries

为什么恰好是它,当我在Xcode中创建一个iOS的静态库项目或框架项目,我不需要为了使用它们的标题和对象的任何iOS版SDK框架链接到项目-例如,我可以#import <AudioToolbox/AudioToolbox.h>并将AudioToolbox代码放在静态库或框架中,而无需在构建设置中的"Link Binary with Libraries"下添加AudioToolbox或将其存在于文件导航器中,并且项目将无问题地构建,这在某些情况下无效应用程序项目 - 但是当开发人员在应用程序中使用静态库或框架产品时,他们必须链接到框架才能使用相同的标头和对象?

我有一个模糊的想法,为什么会这样,但我真的很想听到一个肯定知道的人.

Rob*_*ier 10

静态库只是一个.o文件包.他们没有任何有意义的"联系"; 只是连在一起.直到您执行实际链接步骤才能解析符号.

将a .a与可执行文件链接并将等效源代码复制到可执行文件项目之间基本没有区别.因此,在此之前不需要与任何其他框架或库链接.


以下练习可能具有教育意义:

创建以下内容comptest.c:

#include <stdio.h>

int main() {
   printf("Hello world.\n");
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

看看预处理器的作用:

gcc -E comptest.c > comptest-cpp.c
Run Code Online (Sandbox Code Playgroud)

这将删除#include并将其替换为引用文件的内容.这个文件是编译器实际看到的.

现在看看编译器做了什么(我在>这里和下面使用语法,以便与事物平行-E):

gcc -S comptest.c > comptest.s
Run Code Online (Sandbox Code Playgroud)

这是预处理和编译后生成的汇编语言.现在我们将其转换为.o:

gcc -c comptest.c > comptest.o
Run Code Online (Sandbox Code Playgroud)

现在让我们看看那里有什么.o:

$ nm comptest.o
0000000000000040 s EH_frame0
000000000000002d s L_.str
0000000000000000 T _main
0000000000000058 S _main.eh
                 U _puts
Run Code Online (Sandbox Code Playgroud)

这里重要的事情是_main_puts._main在此文件中定义的地址为0. _puts未定义.所以我们联系的东西最好提供它.让我们试着没有任何东西:

$ gcc -nodefaultlibs comptest.o
Undefined symbols for architecture x86_64:
  "_exit", referenced from:
      start in crt1.10.6.o
  "_puts", referenced from:
      _main in comptest.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

(_exit从C运行时隐式;它不直接在.o中引用)

好的,现在我们已经准备好把它们放在一起了.我们会明确的:

gcc -nodefaultlibs comptest.o /usr/lib/libc.dylib -o comptest
Run Code Online (Sandbox Code Playgroud)

这表示链接在一起comptest.o和动态库libc.它承诺所引用的每个符号都将由其中一个文件提供.它在生成的二进制文件中注释它应该动态加载符号/usr/lib/libc.dylib(这是一个符号链接到libSystem.B.dylib,它本身就是一个"伞形框架"而不是一个合适的库,但是这稍微超出了你的需要在大多数情况下要知道;你可以假装puts()在libSystem中):

$ otool -L comptest
comptest:
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
Run Code Online (Sandbox Code Playgroud)

如果链接到静态库,则与在命令行中列出其中包含的所有.o文件相同.

请注意,在链接步骤中,我们只有.o和.dylib文件(.a只是.o的包).没有.c文件,没有.h文件,没有.s文件,没有源代码.只需要解析符号的目标文件.这就是头文件在这里无关紧要的原因,但在编译时很重要.