【问题标题】:Why don't iOS framework dependencies need to be explicitly linked to a static library project or framework project when they do for an app project?为什么 iOS 框架依赖项在应用程序项目中不需要显式链接到静态库项目或框架项目?
【发布时间】:2012-04-30 14:24:40
【问题描述】:

究竟是什么原因是因为当我在 Xcode 中创建 iOS 静态库项目或框架项目时,我不需要将任何 iOS SDK 框架链接到该项目即可使用它们标头和对象——例如,我可以#import <AudioToolbox/AudioToolbox.h> 并将 AudioToolbox 代码放入静态库或框架中,而无需在构建设置中的“Link Binary with Libraries”下添加 AudioToolbox 或将其显示在文件导航器和项目中将毫无问题地构建,这在应用程序项目中不起作用 - 但是当开发人员随后在应用程序中使用静态库或框架产品时,他们必须链接到框架才能使用相同的标头和对象?

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

【问题讨论】:

    标签: objective-c xcode gcc static-libraries llvm


    【解决方案1】:

    静态库只是一组.o 文件。它们没有以任何有意义的方式“链接”;只是串联在一起。直到您执行真正的链接步骤才能解析符号。

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


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

    创建以下comptest.c:

    #include <stdio.h>
    
    int main() {
       printf("Hello world.\n");
       return 0;
    }
    

    看看预处理器做了什么:

    gcc -E comptest.c > comptest-cpp.c
    

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

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

    gcc -S comptest.c > comptest.s
    

    这是经过预处理和编译后生成的汇编语言。现在我们把它变成一个 .o:

    gcc -c comptest.c > comptest.o
    

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

    $ nm comptest.o
    0000000000000040 s EH_frame0
    000000000000002d s L_.str
    0000000000000000 T _main
    0000000000000058 S _main.eh
                     U _puts
    

    这里重要的是_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
    

    (_exit 隐含在 C 运行时中;它没有在 .o 中直接引用)

    好的,现在我们准备好将它们放在一起。我们将明确:

    gcc -nodefaultlibs comptest.o /usr/lib/libc.dylib -o comptest
    

    这表示将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)
    

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

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

    【讨论】:

    • 好的,但是让我没有 100% 清楚这一点的原因是,例如,如果项目源代码中缺少标头并且项目中的实现文件引用它,则构建将导致由于缺少标头而导致的构建错误。另一个问题是,如果我从我自己的框架而不是 iOS 框架中导入标头,我将收到标头未找到错误并且构建将失败。
    • 是不是因为iOS框架的项目构建设置中某处有标头搜索路径?
    • 标头必须在预处理时(编译前)可用。它们与链接器无关。静态库是 .o 文件的集合。这些已经过预处理和编译。然而,它们并没有联系在一起。链接不需要或使用头文件。链接解析符号。
    • 大家好。你能看看这个问题stackoverflow.com/questions/25504973/…吗?
    猜你喜欢
    • 2014-05-28
    • 2012-02-04
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    • 2015-11-23
    • 2015-05-07
    • 2023-03-29
    • 2020-05-21
    相关资源
    最近更新 更多