blob: b0566df9065bf1a522986beb5d1041b2beacc90c [file] [log] [blame] [view]
# LLD for Mac builds
*Disclaimer* We don't use LLD for Mac builds. Using it is not supported, and
if you try to use it, it likely won't work. Only keep reading if you want to
work on the build.
## Background
Chromium uses [LLD](https://lld.llvm.org/) as linker on all platforms,
except when targeting macOS or iOS. LLD is faster than other ELF linkers (ELF
is the executable file format used on most OSs, including Linux, Android,
Chrome OS, Fuchsia), and it's faster than other COFF linkers (the executable
file format on Windows).
ld64, the standard Mach-O linker (the executable file format on iOS and macOS),
is on the other hand already fairly fast and works well, so there are fewer
advantages to using LLD here. (Having said that, LLD is currently 4x faster
at linking Chromium Framework than ld64 in symbol\_level=0 release builds,
despite ld64 being already fast. Maybe that's due to LLD not yet doing
critical things and it will get slower, but at the moment it's faster than
ld64.)
LLD does have a few advantages unrelated to speed, however:
- It's developed in the LLVM repository, and we ship it in our clang package
(except on macOS, where it's not in the default clang package but an opt-in
download instead). We can fix issues upstream and quickly deploy fixed
versions, instead of having to wait for Xcode releases (which is where ld64
ships).
- For the same reason, it has a much simpler LTO setup: Clang and LLD both link
in the same LLVM libraries that are built at the same revision, and compiler
and linker bitcodes are interopable for that reason. With ld64, the LTO code
has to be built as a plugin that's loaded by the linker.
- LLD/Mach-O supports "LLVM-y" features that the ELF and COFF LLDs support as
well, such as thin archives, colored diagnostics, and response files
(ld64 supports this too as of Xcode 12, but we had to wait many years for it,
and it's currently [too crashy](https://crbug.com/1147968) to be usable).
For that reason, it's possible to opt in to LLD for macOS builds (not for
iOS builds, and that's intentionally not in scope).
A background note: There are two versions of LLD upstream: The newer ports,
and an older design that's still available as ld64.lld.darwinold for Mach-O
LLD. We use the new `lld/MachO` port, not the old one. The new one is the
default selection for `-fuse-ld=lld` on macOS as of March 1 2021.
Just like the LLD ELF port tries to be commandline-compatible with other ELF
linkers and the LLD COFF port tries to be commandline-compatible with the
Visual Studio linker link.exe, the LLD Mach-O port tries to be
commandline-compatible with ld64. This means LLD accepts different flags on
different platforms.
## Current status and known issues
A `symbol_level = 0` `is_debug = false` `use_lld = true` x64 build produces
a mostly-working Chromium.app, but there are open issues and missing features:
- LLD's ARM support is very new
- relocations aren't handled correctly ([bug](https://llvm.org/PR49444))
- ad-hoc code signing only signs executables, not yet dylibs
([in-progress patch](https://reviews.llvm.org/D97994)).
- likely other bugs for `target_cpu="arm64"`
- LLD produces bad debug info, and LLD-linked binaries don't yet show C++
source code in a debugger ([bug](https://llvm.org/PR48714)]
- We haven't tried actually running any other binaries, so chances are many
other tests fail
- LLD doesn't yet implement `-dead_strip`, leading to many linker warnings
- LLD doesn't yet implement deduplication (aka "ICF")
- LLD doesn't yet call graph profile sort
- LLD doesn't yet implement `-exported_symbol` or `-exported_symbols_list`,
leading to some linker warnings
## Opting in
1. First, obtain lld. Do either of:
1. run `src/tools/clang/scripts/update.py --package=lld_mac` to download a
prebuilt lld binary.
2. build `lld` and `llvm-ar` locally and copy it to
`third_party/llvm-build/Release+Asserts/bin`. Also run
`ln -s lld third_party/llvm-build/Release+Asserts/bin/ld64.lld`.
You have to do this again every time `runhooks` updates the clang
package.
The prebuilt might work less well than a more up-to-date, locally-built
version -- see the list of open issues above for details. If anything is
marked "fixed upstream", then the fix is upstream but not yet in the
prebuilt lld binary.
2. Add `use_lld = true` to your args.gn
3. Then just build normally.
`use_lld = true` makes the build use thin archives. For that reason, `use_lld`
also switches from `libtool` to `llvm-ar`.
## Creating stand-alone repros for bugs
For simple cases, LLD's `--reproduce=foo.tar` flag / `LLD_REPRODUCE=foo.tar`
env var is sufficient.
See "Note to self:" [here](https://bugs.llvm.org/show_bug.cgi?id=48657#c0) for
making a repro file that involved the full app and framework bundles.
Locally, apply this patch before building chrome to make a repro that can
be used with both lld and ld (useful for making comparisons):
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 5ea2f2130abb..ed871642cee9 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -1780,7 +1780,7 @@ config("export_dynamic") {
config("thin_archive") {
# The macOS and iOS default linker ld64 does not support reading thin
# archives.
- if ((is_posix && !is_nacl && (!is_apple || use_lld)) || is_fuchsia) {
+ if ((is_posix && !is_nacl && (!is_apple)) || is_fuchsia) {
arflags = [ "-T" ]
} else if (is_win && use_lld) {
arflags = [ "/llvmlibthin" ]