Xcode 使用两种不同的编译器前端,一种是针对 Objective-C/Objective-C++ 或者 C/C++ 代码使用的,另一种就是在 Swift 出现之后针对 Swift 语言使用的。前者就是 clang,后者是 swiftc / swift。
因为 swift 语言本身是没有预处理器的,因此忽略前一步。在预编译阶段,我使用了 Clang 作为演示,而 Swift 文件是无需进行预编译处理的。最终编译器生成的文件,称之为目标文件,在 Apple 平台中以特殊的格式存在,这种格式就是 Mach-O 格式,下文会讲。
而每个目标文件中都有暴露给其他目标文件所使用的符号,这些也就是外部符号,这些符号被管理起来,以一个符号表的形式存在,对于变量和函数来说,其符号表中的 Key 就是这些变量和函数的名字,而 Value 就是其在目标文件中的地址。
生成产物为两个对应的目标文件,main.o 以及 Foo.o ,使用链接器进行链接,传统的链接器,无论是 Mac 还是 Linux 上都会有 ld 这个工具,在 /usr/bin/ 下,我们先使用 ld 将对应两个目标文件链接起来,如下:
1
ld Foo.o main.o
但是报错,如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
ld: warning: No version-min specified on command line
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_NSObject", referenced from:
_OBJC_CLASS_$_Foo in Foo.o
"_OBJC_METACLASS_$_NSObject", referenced from:
_OBJC_METACLASS_$_Foo in Foo.o
"__objc_empty_cache", referenced from:
_OBJC_METACLASS_$_Foo in Foo.o
_OBJC_CLASS_$_Foo in Foo.o
"_objc_msgSend", referenced from:
_main in main.o
"_printf", referenced from:
-[Foo hello] in Foo.o
ld: symbol(s) not found for inferred architecture x86_64
其中,报了一堆 OBJC 库找不到的问题,因为是静态链接,我们内部使用了 Foundation 的一些内容,这里也在侧面证明了,想要完成静态链接,所有未定义的符号都需要在静态链接阶段进行修正,因此我们还需要将这些库也链进来,当然,还有 _printf 也找不到,我们还需要把 C++ 相关的库也同时一并链接,最后的链接命令如下:
llvm-otool - the otool-compatible command line parser for llvm-objdump.
The command line shim llvm-otool takes all the same options as the original otool(1) command and executes an equivalent objdump(1) command.
// -L print shared libraries used
xcrun otool -L a.out
a.out:
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1560.12.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5) /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
当然,我们也可以查看一下其中的 libSystem.B.dylib 的情况,其实 macOS 上的 C 基础库。
xcrun otool -L /usr/lib/libSystem.B.dylib
/usr/lib/libSystem.B.dylib:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1) /usr/lib/system/libcache.dylib (compatibility version 1.0.0, current version 81.0.0) /usr/lib/system/libcommonCrypto.dylib (compatibility version 1.0.0, current version 60118.250.2) /usr/lib/system/libcompiler_rt.dylib (compatibility version 1.0.0, current version 63.4.0) /usr/lib/system/libcopyfile.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/system/libcorecrypto.dylib (compatibility version 1.0.0, current version 602.250.23) /usr/lib/system/libdispatch.dylib (compatibility version 1.0.0, current version 1008.250.7) /usr/lib/system/libdyld.dylib (compatibility version 1.0.0, current version 655.1.1) /usr/lib/system/libkeymgr.dylib (compatibility version 1.0.0, current version 30.0.0) /usr/lib/system/liblaunch.dylib (compatibility version 1.0.0, current version 1336.251.2) /usr/lib/system/libmacho.dylib (compatibility version 1.0.0, current version 927.0.2) /usr/lib/system/libquarantine.dylib (compatibility version 1.0.0, current version 86.220.1) /usr/lib/system/libremovefile.dylib (compatibility version 1.0.0, current version 45.200.2) /usr/lib/system/libsystem_asl.dylib (compatibility version 1.0.0, current version 356.200.4) /usr/lib/system/libsystem_blocks.dylib (compatibility version 1.0.0, current version 73.0.0) /usr/lib/system/libsystem_c.dylib (compatibility version 1.0.0, current version 1272.250.1) /usr/lib/system/libsystem_configuration.dylib (compatibility version 1.0.0, current version 963.250.1) /usr/lib/system/libsystem_coreservices.dylib (compatibility version 1.0.0, current version 66.0.0) /usr/lib/system/libsystem_darwin.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/system/libsystem_dnssd.dylib (compatibility version 1.0.0, current version 878.250.4) /usr/lib/system/libsystem_info.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/system/libsystem_m.dylib (compatibility version 1.0.0, current version 3158.200.7) /usr/lib/system/libsystem_malloc.dylib (compatibility version 1.0.0, current version 166.251.2) /usr/lib/system/libsystem_networkextension.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/system/libsystem_notify.dylib (compatibility version 1.0.0, current version 172.200.21) /usr/lib/system/libsystem_sandbox.dylib (compatibility version 1.0.0, current version 851.250.12) /usr/lib/system/libsystem_secinit.dylib (compatibility version 1.0.0, current version 30.220.1) /usr/lib/system/libsystem_kernel.dylib (compatibility version 1.0.0, current version 4903.251.3) /usr/lib/system/libsystem_platform.dylib (compatibility version 1.0.0, current version 177.250.1) /usr/lib/system/libsystem_pthread.dylib (compatibility version 1.0.0, current version 330.250.2) /usr/lib/system/libsystem_symptoms.dylib (compatibility version 1.0.0, current version 1.0.0) /usr/lib/system/libsystem_trace.dylib (compatibility version 1.0.0, current version 906.250.5) /usr/lib/system/libunwind.dylib (compatibility version 1.0.0, current version 35.4.0) /usr/lib/system/libxpc.dylib (compatibility version 1.0.0, current version 1336.251.2)