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?

后端 未结 1 1415
名媛妹妹
名媛妹妹 2020-12-30 13:48

Why exactly is it that when I create an iOS static library project or framework project in Xcode, I don\'t need to link any iOS SDK frameworks to the projec

相关标签:
1条回答
  • 2020-12-30 14:24

    Static libraries are just a bundle of .o files. They're not "linked" in any meaningful way; just concatenated together. It's not until you perform a real link step that symbols are resolved.

    There is basically no difference between linking a .a with your executable and copying the equivalent source code into your executable's project. So there's no need to link with any additional frameworks or libraries until that time.


    The following exercise may be educational:

    Create the following comptest.c:

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

    See what the pre-processor does:

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

    This removes the #include and replaces it with the contents of the referenced file. This file is what the compiler actually sees.

    Now see what the compiler does (I'm using the > syntax here and below so that things are parallel with -E):

    gcc -S comptest.c > comptest.s
    

    This is the generated assembly language after pre-processing and compilation. Now we turn that into a .o:

    gcc -c comptest.c > comptest.o
    

    Now let's see what's in that .o:

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

    The important things here are _main and _puts. _main is defined in this file at address 0. _puts is undefined. So something we link with had better provide it. Let's try linking without anything:

    $ 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 is implicit from the C runtime; it's not directly referenced in the .o)

    OK, so now we're ready to put it all together. We'll be explicit:

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

    This says to link together comptest.o and the dynamic library libc. It promises that every symbol referenced will be provided by one of these files. It makes a note in the resulting binary that it should dynamically load symbols from /usr/lib/libc.dylib (this is a symlink to libSystem.B.dylib, which is itself an "umbrella framework" rather than a proper library, but that goes a little past what you need to know in most cases; you can pretend that puts() is in libSystem):

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

    If you link with a static library, it's identical to listing all the .o files included in it on the command-line.

    Notice that at the link step, we just have .o and .dylib files (.a is just a package of .o). There are no .c files, no .h files, no .s files, no source code. Just object files that need symbols resolved. This is why header files don't matter here, but do matter when you're compiling.

    0 讨论(0)
提交回复
热议问题