Upgrade to Pro — share decks privately, control downloads, hide ads and more …

The new linker in Xcode 15

The new linker in Xcode 15

Yuta Saito

July 14, 2023
Tweet

More Decks by Yuta Saito

Other Decks in Programming

Transcript

  1. Agenda 1. man page diff 2. What is ld-prime? 3.

    Faster Linking 4. Mergeable Library 5. Mergeable Library Internals 2
  2. 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
  3. 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
  4. Trade off between static linking and dynamic linking Static Linking

    Dynamic Linking Launch Time Fast Slow Linking Time Slow Fast 8
  5. 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
  6. 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
  7. .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
  8. 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
  9. 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
  10. 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
  11. /** * 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
  12. 18

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