Auto Linking on iOS & macOS

Published on

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 importing1.

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

References


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

← Back to Writings