Slide 1

Slide 1 text

The new linker in Xcode 15 WWDC Recap Yuta Saito (@kateinoigakukun) 1

Slide 2

Slide 2 text

Agenda 1. man page diff 2. What is ld-prime? 3. Faster Linking 4. Mergeable Library 5. Mergeable Library Internals 2

Slide 3

Slide 3 text

1. man page diff Changes 1. Two linker binaries: ld and ld-prime 2. New options for ld-prime 3. ld-prime drops support for armv7k and i386 Rarely used Options + -ld64 Override the choice of linker, and force the use of ld64 to link + the binary. This is incompatible with options such as -merge*, + used to build/merge libraries. + + -ld_prime + Override the choice of linker, and force the use of ld-prime to + link the binary. This is incompatible with older architectures + such as armv7k and i386. + + Mergeable Library Options + -make_mergeable + Adds additional metadata to a dylib which makes it a mergeable + library. It can still be used as a dylib, or can be merged into + other binaries when they link it with a -merge* option. + + -merge-lx + This is the same as the -lx option but means to merge the + contents of the library x into this binary. + + -merge_library path_to_library + This is the same as listing a file name path to a library on the + link line but also merges the contents of the library into this + binary. + + -merge_framework name[,suffix] + This is the same as the -framework name[,suffix] but means that + the contents of the framework should be merged into this binary. + 3

Slide 4

Slide 4 text

2. What is ld-prime? From Platforms State of the Union • The linker has been redesigned from the ground up • Linking is up to 5 times faster! • Size of debug binaries are up to 30% smaller! 4

Slide 5

Slide 5 text

3. Faster Linking 5

Slide 6

Slide 6 text

3. Faster Linking ld-prime utilizes parallelism to speed up linking. 6

Slide 7

Slide 7 text

4. Mergeable Library 7

Slide 8

Slide 8 text

Trade off between static linking and dynamic linking Static Linking Dynamic Linking Launch Time Fast Slow Linking Time Slow Fast 8

Slide 9

Slide 9 text

Before Xcode 15 • Two targets are needed to achieve the best build- time and launch-time. • Pre-compiled framework authors need to ship both static and dynamic frameworks to support both use cases. 9

Slide 10

Slide 10 text

Mergeable Library • Mergeable Library is a new concept introduced in Xcode 15 • A dynamic library with additional metadata • Designed to be able to defer the decision of link-strategy until the final link step. 10

Slide 11

Slide 11 text

.xcodeproj settings • MERGED_BINARY_TYPE • Automatic: Static link for Debug, Dynamic link for Release • Manual: Static link targets whose MERGEABLE_LIBRARY is set to YES for Debug. • MERGEABLE_LIBRARY • YES: The target is built as a mergeable library 11

Slide 12

Slide 12 text

See https://developer.apple.com/videos/play/ wwdc2023/10268/ 12

Slide 13

Slide 13 text

5. Mergeable Library Internals 13

Slide 14

Slide 14 text

Debug $ otool -L Debug-iphonesimulator/MyApp.app/MyApp | grep @rpath @rpath/MyUI.framework/MyUI Release $ otool -L Release-iphonesimulator/MyApp.app/MyApp | grep @rpath # empty 14

Slide 15

Slide 15 text

Debug $ tree -h -L 3 Debug-iphonesimulator/MyApp.app ├── [ 96] Frameworks │ └── [ 192] MyUI.framework │ ├── [ 22K] Assets.car │ ├── [ 716] Info.plist │ ├── [ 34K] MyUI │ └── [ 96] _CodeSignature ├── [1.2K] Info.plist ├── [106K] MyApp ├── [ 8] PkgInfo ├── [ 96] ReexportedBinaries │ └── [ 160] MyUI.framework │ ├── [ 716] Info.plist │ ├── [106K] MyUI │ └── [ 96] _CodeSignature └── [ 96] _CodeSignature └── [3.7K] CodeResources Release $ tree -h -L 3 Release-iphonesimulator/MyApp.app ├── [ 96] Frameworks │ └── [ 192] MyUI.framework │ ├── [ 22K] Assets.car │ ├── [ 716] Info.plist │ ├── [ 34K] MyUI │ └── [ 96] _CodeSignature ├── [1.2K] Info.plist ├── [231K] MyApp ├── [ 8] PkgInfo └── [ 96] _CodeSignature └── [2.9K] CodeResources 15

Slide 16

Slide 16 text

Bundle(for: AnyClass) hook for statically linked Mergeable Library • Bundle(for: AnyClass) finds a bundle path which contains the given class code • If a library is statically linked, its code is in the merged binary but bundle resources are not. • ld-prime inserts a hook to find the correct bundle path when merging a framework. 16

Slide 17

Slide 17 text

/** * Returns the dynamic library name a class originated from. * * @param cls The class you are inquiring about. * * @return The name of the library containing this class. */ OBJC_EXPORT const char * _Nullable class_getImageName(Class _Nullable cls) /** * Install a hook for class_getImageName(). * * @param newValue The hook function to install. * @param outOldValue The address of a function pointer variable. On return, * the old hook function is stored in the variable. * * @note The store to *outOldValue is thread-safe: the variable will be * updated before class_getImageName() calls your new hook to read it, * even if your new hook is called from another thread before this * setter completes. * @note The first hook in the chain is the native implementation of * class_getImageName(). Your hook should call the previous hook for * classes that you do not recognize. * * @see class_getImageName * @see objc_hook_getImageName */ OBJC_EXPORT void objc_setHook_getImageName(objc_hook_getImageName _Nonnull newValue, objc_hook_getImageName _Nullable * _Nonnull outOldValue) https://github.com/apple-oss-distributions/objc4/blob/689525d556eb3dee1ffb700423bccf5ecc501dbf/runtime/runtime.h#L1454-L1462 17

Slide 18

Slide 18 text

18

Slide 19

Slide 19 text

Wrap up 1. Xcode 15 ships a blazingly fast new linker ld-prime 2. ld-prime introduces a new concept called Mergeable Library 3. Mergeable Library achieves best developer/user experience 4. See my research notes for more details: https://github.com/kateinoigakukun/ MergeableLibraryInternals 19