Bug 1329737 - part 3 - use an alternate linker for Cargo invocations; r=rillian
authorNathan Froyd <froydnj@mozilla.com>
Fri, 28 Apr 2017 14:06:41 -0400
changeset 355703 fc34b2a31c4beb821ab40c8eca744c78212c14f5
parent 355702 fbbceb56e0d9da91ea3b622f6e7b7fda4b83b4ae
child 355704 85d31cb549035041027c5a09b1e9a36b856626bc
push id31736
push userarchaeopteryx@coole-files.de
push dateSat, 29 Apr 2017 09:10:55 +0000
treeherdermozilla-central@308cdb913d71 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrillian
bugs1329737
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1329737 - part 3 - use an alternate linker for Cargo invocations; r=rillian For linking static libraries, rustc will use whatever `cc` it finds (or the equivalent on Windows). For our purposes, however, `cc` is not what we use to link and we may have additional options we would like to pass to the linker. To do this, we need to tell Cargo about our alternate linker (currently only used for target compilations, on the theory that the host compiler rustc finds is probably good enough) and we also need to pass our linker options into the process. We do this with environment variables, which is not a great solution, but works surprisingly well. This alternate linker is disabled for ASan builds due to peculiar crashes when running Rust build scripts and for Windows, because we don't do any interesting cross-compiling there.
build/cargo-linker
config/rules.mk
new file mode 100755
--- /dev/null
+++ b/build/cargo-linker
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# 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.  Note that
+# we do *not* quote either MOZ_CARGO_WRAP variable:
+#
+# * 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 either of those arguments is passed
+#   as a separate argument to the actual LD.
+
+${MOZ_CARGO_WRAP_LD} ${MOZ_CARGO_WRAP_LDFLAGS} "$@"
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -979,30 +979,50 @@ env $(environment_cleaner) $(rustflags_o
 	CLANG_PATH=$(MOZ_CLANG_PATH) \
 	PKG_CONFIG_ALLOW_CROSS=1 \
 	RUST_BACKTRACE=1 \
 	MOZ_TOPOBJDIR=$(topobjdir) \
 	$(1) \
 	$(CARGO) build $(cargo_build_flags)
 endef
 
+cargo_linker_env_var := CARGO_TARGET_$(RUST_TARGET_ENV_NAME)_LINKER
+
+# Don't define a custom linker on Windows, as it's difficult to have a
+# non-binary file that will get executed correctly by Cargo.  We don't
+# have to worry about a cross-compiling (besides x86-64 -> x86, which
+# already works with the current setup) setup on Windows, and we don't
+# have to pass in any special linker options on Windows.
+ifneq (WINNT,$(OS_ARCH))
+
+# Defining all of this for ASan builds results in crashes while running
+# some crates's build scripts (!), so disable it for now.
+ifndef MOZ_ASAN
+target_cargo_env_vars := \
+	MOZ_CARGO_WRAP_LDFLAGS="$(LDFLAGS)" \
+	MOZ_CARGO_WRAP_LD="$(CC)" \
+	$(cargo_linker_env_var)=$(topsrcdir)/build/cargo-linker
+endif # MOZ_ASAN
+
+endif # ifneq WINNT
+
 ifdef RUST_LIBRARY_FILE
 
 ifdef RUST_LIBRARY_FEATURES
 rust_features_flag := --features "$(RUST_LIBRARY_FEATURES)"
 endif
 
 # Assume any system libraries rustc links against are already in the target's LIBS.
 #
 # We need to run cargo unconditionally, because cargo is the only thing that
 # has full visibility into how changes in Rust sources might affect the final
 # build.
 force-cargo-library-build:
 	$(REPORT_BUILD)
-	$(call CARGO_BUILD) --lib $(cargo_target_flag) $(rust_features_flag)
+	$(call CARGO_BUILD,$(target_cargo_env_vars)) --lib $(cargo_target_flag) $(rust_features_flag)
 
 $(RUST_LIBRARY_FILE): force-cargo-library-build
 endif # RUST_LIBRARY_FILE
 
 ifdef HOST_RUST_LIBRARY_FILE
 
 ifdef HOST_RUST_LIBRARY_FEATURES
 host_rust_features_flag := --features "$(HOST_RUST_LIBRARY_FEATURES)"
@@ -1013,17 +1033,17 @@ force-cargo-host-library-build:
 	$(call CARGO_BUILD) --lib $(cargo_host_flag) $(host_rust_features_flag)
 
 $(HOST_RUST_LIBRARY_FILE): force-cargo-host-library-build
 endif # HOST_RUST_LIBRARY_FILE
 
 ifdef RUST_PROGRAMS
 force-cargo-program-build:
 	$(REPORT_BUILD)
-	$(call CARGO_BUILD) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag)
+	$(call CARGO_BUILD,$(target_cargo_env_vars)) $(addprefix --bin ,$(RUST_CARGO_PROGRAMS)) $(cargo_target_flag)
 
 $(RUST_PROGRAMS): force-cargo-program-build
 endif # RUST_PROGRAMS
 ifdef HOST_RUST_PROGRAMS
 force-cargo-host-program-build:
 	$(REPORT_BUILD)
 	$(call CARGO_BUILD) $(addprefix --bin ,$(HOST_RUST_CARGO_PROGRAMS)) $(cargo_host_flag)