diff options
Diffstat (limited to 'build/cargo-linker')
-rwxr-xr-x | build/cargo-linker | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/build/cargo-linker b/build/cargo-linker new file mode 100755 index 0000000000..898e21d482 --- /dev/null +++ b/build/cargo-linker @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 + +# If you want to use a custom linker with Cargo, Cargo requires that you +# specify it in Cargo.toml or via the matching environment variable. +# Passing extra options to the linker is possible with Cargo via +# RUSTFLAGS='-C link-args', but testing showed that doing this reliably +# was difficult. +# +# Our solution to these problems is to use this wrapper script. We pass +# in the LD and the LDFLAGS to use via environment variables. +# +# * MOZ_CARGO_WRAP_LD is equivalent to CC on Unix-y platforms, and CC +# frequently has additional arguments in addition to the compiler +# itself. +# +# * MOZ_CARGO_WRAP_LDFLAGS contains space-separated arguments to pass, +# and not quoting it ensures that each of those arguments is passed +# as a separate argument to the actual LD. +# +# * In rare cases, we also need MOZ_CARGO_WRAP_LD_CXX, which is the +# equivalent of CXX, when linking C++ code. Usually, this should +# simply work by the use of CC and -lstdc++ (added by cc-rs). +# However, in the case of sanitizer runtimes, there is a separate +# runtime for C and C++ and linking C++ code with the C runtime can +# fail if the requested feature is in the C++ runtime only (bug 1747298). + +import os +import sys + +# This is not necessarily run with a virtualenv python, so add +# the necessary directory for the shellutil module. +base_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) +sys.path.insert(0, os.path.join(base_dir, "python", "mozbuild")) +from mozbuild.shellutil import split + + +SANITIZERS = { + "asan": "address", + "hwasan": "hwaddress", + "lsan": "leak", + "msan": "memory", + "tsan": "thread", +} + +use_clang_sanitizer = os.environ.get("MOZ_CLANG_NEWER_THAN_RUSTC_LLVM") +wrap_ld = os.environ["MOZ_CARGO_WRAP_LD"] +args = split(os.environ["MOZ_CARGO_WRAP_LDFLAGS"]) +for arg in sys.argv[1:]: + if arg in ["-lc++", "-lstdc++"]: + wrap_ld = os.environ["MOZ_CARGO_WRAP_LD_CXX"] + elif use_clang_sanitizer and arg.endswith("san.a"): + # When clang is newer than rustc's LLVM, we replace rust's sanitizer + # runtimes with clang's. + filename = os.path.basename(arg) + prefix, dot, suffix = filename[:-2].rpartition(".") + if ( + prefix.startswith("librustc-") + and prefix.endswith("_rt") and dot == "." + ): + args.append(f"-fsanitize={SANITIZERS[suffix]}") + continue + args.append(arg) + +wrap_ld = split(wrap_ld) +os.execvp(wrap_ld[0], wrap_ld + args) |