Commit 22d0d663 authored by Nico Weber's avatar Nico Weber Committed by Chromium LUCI CQ

mac: Make it possible to build with lld instead of ld64.

This mostly doesn't work, so also add some documentation that tells
people not to use it. (The documentation also has some other
information.)

No behavior change for regular builds.

Bug: 1149587
Change-Id: I03f4f5b65a0d010636a499b043bfcf31b0cd34b5
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2574601Reviewed-by: default avatarHans Wennborg <hans@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarMark Mentovai <mark@chromium.org>
Commit-Queue: Nico Weber <thakis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834446}
parent cd128dcf
......@@ -274,7 +274,7 @@ config("compiler") {
}
# In general, Windows is totally different, but all the other builds share
# some common GCC configuration.
# some common compiler and linker configuration.
if (!is_win) {
# Common POSIX compiler flags setup.
# --------------------------------
......@@ -303,6 +303,14 @@ config("compiler") {
}
}
if (use_lld) {
if (is_apple) {
ldflags += [ "-fuse-ld=lld.darwinnew" ]
} else {
ldflags += [ "-fuse-ld=lld" ]
}
}
# Linker warnings.
if (fatal_linker_warnings && !is_apple && current_os != "aix") {
ldflags += [ "-Wl,--fatal-warnings" ]
......@@ -310,7 +318,6 @@ config("compiler") {
if (fatal_linker_warnings && is_apple) {
ldflags += [ "-Wl,-fatal_warnings" ]
}
} else {
}
if (is_clang && is_debug) {
......@@ -411,7 +418,6 @@ config("compiler") {
# Linux-specific compiler flags setup.
# ------------------------------------
if ((is_posix || is_fuchsia) && use_lld) {
ldflags += [ "-fuse-ld=lld" ]
if (current_cpu == "arm64") {
# Reduce the page size from 65536 in order to reduce binary size slightly
# by shrinking the alignment gap between segments. This also causes all
......@@ -447,7 +453,7 @@ config("compiler") {
#}
}
if (use_icf) {
if (use_icf && !is_apple) {
ldflags += [ "-Wl,--icf=all" ]
}
......@@ -1765,10 +1771,9 @@ config("export_dynamic") {
# 2. Remove the thin_archive config, so that the .a file actually contains all
# .o files, instead of just references to .o files in the build directoy
config("thin_archive") {
# Mac and iOS use the mac-specific "libtool" command, not ar, which doesn't
# have a "thin archive" mode (it does accept -T, but it means truncating
# archive names to 16 characters, which is not what we want).
if ((is_posix && !is_nacl && !is_apple) || is_fuchsia) {
# The macOS and iOS default linker ld64 does not support reading thin
# archives.
if ((is_posix && !is_nacl && (!is_apple || use_lld)) || is_fuchsia) {
arflags = [ "-T" ]
} else if (is_win && use_lld) {
arflags = [ "/llvmlibthin" ]
......
......@@ -190,6 +190,8 @@ enable_arm_cfi_table = is_android && !is_component_build && current_cpu == "arm"
declare_args() {
# Set to true to use lld, the LLVM linker.
# Not supported for macOS (see docs/mac_lld.md), and not functional at all for
# iOS. The default linker everywhere else.
use_lld = is_clang && !is_apple
}
......
......@@ -263,16 +263,26 @@ template("mac_toolchain") {
}
tool("alink") {
script =
rebase_path("//build/toolchain/mac/filter_libtool.py", root_build_dir)
rspfile = "{{output}}.rsp"
rspfile_content = "{{inputs}}"
# Specify explicit path for libtool.
libtool = mac_bin_path + "libtool"
command = "rm -f {{output}} && TOOL_VERSION=${tool_versions.filter_libtool} python $script $libtool -static -D {{arflags}} -o {{output}} \"@$rspfile\""
description = "LIBTOOL-STATIC {{output}}"
if (!use_lld) {
script = rebase_path("//build/toolchain/mac/filter_libtool.py",
root_build_dir)
# Specify explicit path for libtool.
libtool = mac_bin_path + "libtool"
command = "rm -f {{output}} && TOOL_VERSION=${tool_versions.filter_libtool} python $script $libtool -static -D {{arflags}} -o {{output}} \"@$rspfile\""
description = "LIBTOOL-STATIC {{output}}"
} else {
ar = "${prefix}llvm-ar"
command = "\"$ar\" {{arflags}} -r -c -s -D {{output}} \"@$rspfile\""
# Remove the output file first so that ar doesn't try to modify the
# existing file.
command = "rm -f {{output}} && $command"
description = "AR {{output}}"
}
outputs = [ "{{output_dir}}/{{target_output_name}}{{output_extension}}" ]
default_output_dir = "{{target_out_dir}}"
default_output_extension = ".a"
......
# 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 fast and works well, so there are fewer advantages
to using LLD here.
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 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
that are nowadays used for ELF and COFF, and an older design that's still the
default Mach-O LLD. There's however an effort underway to write a new Mach-O
LLD that's built on the same design as the ELF and COFF ports. Chromium Mac
builds uses the new Mach-O port of LLD ("`ld64.lld.darwinnew`").
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.
## Known issues
- LLD/Mach-O is moving quickly, so things usually work best with a trunk build
of LLD instead of the prebuilt one
- LLD does not yet have any ARM support
([in-progress patch](https://reviews.llvm.org/D88629))
- LLD-linked binaries don't work on macOS 10.13 or older
([bug](https://llvm.org/PR48395))
- LLD cannot yet link swiftshader binaries ([bug](https://llvm.org/PR48332)) --
but other than that, all targets build
- LLD likely produces bad debug info, and LLD-linked binaries likely don't
yet work in a debugger
- LLD-linked base\_unittests fails some unwind-related tests
([bug](https://llvm.org/PR48389))
- 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 implement `-exported_symbol` or `-exported_symbols_list`,
leading to some linker warnings
## Opting in
1. First, obtain lld. Do either of:
1. build `lld` locally and copy it to
`third_party/llvm-build/Relase+Asserts/bin`
2. run `src/tools/clang/scripts/update.py --package=lld_mac` to download a
prebuilt lld binary.
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.
2. Add `use_lld = true` to your args.gn
3. Add `fatal_linker_warnings = false` to your args.gn -- builds that use LLD
currently emit all kinds of warnings (see "Known issues" above).
4. 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`.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment