milen.me
milen.me

Auto Linking on iOS & macOS

Permalink | RSS

Auto Linking Explained

When object files get linked at the final build stage, the linker needs to know which libraries to link against. For example, if you add #import <AppKit/AppKit.h> to an implementation file, you need to also add -framework AppKit to the linker flags.

Auto Linking aims to remove the latter step, i.e., it aims to derive the library linker flags from the import statements in your code. Developers do not need to add any framework/library linker flags anymore, they can just start using any framework by importing.

Under the Hood

Auto Linking works by inserting linker flags in object files. When the linker creates the final executable, it’s as if those linker flags were passed as arguments.

The linker flags are stored as LC_LINKER_OPTION load commands in object files. They can be printed using otool -l file.o:

Load command 5
     cmd LC_LINKER_OPTION
 cmdsize 32
   count 2
  string #1 -framework
  string #2 AppKit
Load command 6
     cmd LC_LINKER_OPTION
 cmdsize 40
   count 2
  string #1 -framework
  string #2 QuartzCore

I recently added support for LC_LINKER_OPTION to MachO-Explorer, so you can use it to inspect the linker flags visually as well.

Frameworks vs Dynamic Libraries

It’s important to note that Auto Linking can work with any Clang module, not just frameworks. For example, /usr/include/module.modulemap in the macOS SDK defines the zlib module as follows:

module zlib [system] [extern_c] {
 header "zlib.h"
 export *
 link "z"
}

The above means that if we were to use #import <zlib.h> with modules turned on, -lz will be automatically inserted by the linker. We can verify this using otool -l:

Load command 4
     cmd LC_LINKER_OPTION
 cmdsize 16
   count 1
  string #1 -lz

Controlling Auto Linking

Auto Linking is active only when Clang modules are turned on. If you’re invoking Clang on the command line, this means passing -fmodules. The Xcode setting is CLANG_ENABLE_MODULES (“Enable Modules (C and Objective-C)”).

Auto Linking itself can be disabled even if modules are enabled. The Clang option is -fno-autolink and the corresponding Xcode setting is CLANG_MODULES_AUTOLINK (“Link Frameworks Automatically”).

Swift

Swift extensively uses the Auto Linking mechanism to link against its runtime and overlay frameworks. For example, if you were to compile a simple Swift file using swiftc -c file.swift and inspect it:

Load command 4
     cmd LC_LINKER_OPTION
 cmdsize 32
   count 1
  string #1 -lswiftAppKit
Load command 5
     cmd LC_LINKER_OPTION
 cmdsize 24
   count 1
  string #1 -lswiftCore
Load command 8
     cmd LC_LINKER_OPTION
 cmdsize 32
   count 1
  string #1 -lswiftDarwin
Load command 39
     cmd LC_LINKER_OPTION
 cmdsize 40
   count 1
  string #1 -lswiftSwiftOnoneSupport
Load command 41
     cmd LC_LINKER_OPTION
 cmdsize 40
   count 1
  string #1 -lswiftCompatibility50
Load command 42
     cmd LC_LINKER_OPTION
 cmdsize 56
   count 1
  string #1 -lswiftCompatibilityDynamicReplacements

← Back to Writings

  1. Either using #import or @import in Objective-C or import in Swift.

Any opinions and viewpoints expressed, explicitly or implicitly, are not endorsed by and do not represent any of my previous, current or future employers.