cargo-linker (2707B)
1 #!/usr/bin/env python3 2 3 # If you want to use a custom linker with Cargo, Cargo requires that you 4 # specify it in Cargo.toml or via the matching environment variable. 5 # Passing extra options to the linker is possible with Cargo via 6 # RUSTFLAGS='-C link-args', but testing showed that doing this reliably 7 # was difficult. 8 # 9 # Our solution to these problems is to use this wrapper script. We pass 10 # in the LD and the LDFLAGS to use via environment variables. 11 # 12 # * MOZ_CARGO_WRAP_LD is equivalent to CC on Unix-y platforms, and CC 13 # frequently has additional arguments in addition to the compiler 14 # itself. 15 # 16 # * MOZ_CARGO_WRAP_LDFLAGS contains space-separated arguments to pass, 17 # and not quoting it ensures that each of those arguments is passed 18 # as a separate argument to the actual LD. 19 # 20 # * In rare cases, we also need MOZ_CARGO_WRAP_LD_CXX, which is the 21 # equivalent of CXX, when linking C++ code. Usually, this should 22 # simply work by the use of CC and -lstdc++ (added by cc-rs). 23 # However, in the case of sanitizer runtimes, there is a separate 24 # runtime for C and C++ and linking C++ code with the C runtime can 25 # fail if the requested feature is in the C++ runtime only (bug 1747298). 26 27 import os 28 import sys 29 30 # This is not necessarily run with a virtualenv python, so add 31 # the necessary directory for the mozshellutil module. 32 base_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) 33 sys.path.insert(0, os.path.join(base_dir, "testing", "mozbase", "mozshellutil")) 34 from mozshellutil import split 35 36 37 SANITIZERS = { 38 "asan": "address", 39 "hwasan": "hwaddress", 40 "lsan": "leak", 41 "msan": "memory", 42 "tsan": "thread", 43 } 44 45 use_clang_sanitizer = os.environ.get("MOZ_CLANG_NEWER_THAN_RUSTC_LLVM") 46 wrap_ld = os.environ["MOZ_CARGO_WRAP_LD"] 47 args = [] 48 for arg in sys.argv[1:]: 49 if arg in ["-lc++", "-lstdc++"]: 50 wrap_ld = os.environ["MOZ_CARGO_WRAP_LD_CXX"] 51 elif use_clang_sanitizer and arg.endswith("san.a"): 52 # When clang is newer than rustc's LLVM, we replace rust's sanitizer 53 # runtimes with clang's. 54 filename = os.path.basename(arg) 55 prefix, dot, suffix = filename[:-2].rpartition(".") 56 if ( 57 prefix.startswith("librustc-") 58 and prefix.endswith("_rt") and dot == "." 59 ): 60 args.append(f"-fsanitize={SANITIZERS[suffix]}") 61 continue 62 args.append(arg) 63 args.extend(split(os.environ["MOZ_CARGO_WRAP_LDFLAGS"])) 64 65 wrap_ld = split(wrap_ld) 66 if sys.platform == "win32": 67 # For some reason, os.execvp doesn't handle arguments properly on Windows. 68 import subprocess 69 sys.exit(subprocess.run(wrap_ld + args).returncode) 70 71 os.execvp(wrap_ld[0], wrap_ld + args)