summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBert Belder <bertbelder@gmail.com>2018-10-25 20:04:23 +0200
committerBert Belder <bertbelder@gmail.com>2018-10-25 22:48:08 +0200
commit00e4f7cf835cda09464d67fc1e1b966fc2214823 (patch)
treed0923652f2ffaac4ddffb6f7eee874734890ef7b
parent243a3ba2d0ea3cfa6aa1aa126a7eecf39dd76596 (diff)
build: fix compatibility with rustc 1.30.0
Additionally: * Rebuild rust crates when the rustc version changes. * Fetch all rust ldflags in one exec_script() call instead of two.
-rw-r--r--build_extra/rust/empty_crate.rs (renamed from build_extra/rust/dummy.rs)0
-rw-r--r--build_extra/rust/get_rustc_info.cmd (renamed from build_extra/rust/get_rust_ldflags.cmd)0
-rwxr-xr-xbuild_extra/rust/get_rustc_info.py (renamed from build_extra/rust/get_rust_ldflags.py)55
-rw-r--r--build_extra/rust/rust.gni25
4 files changed, 49 insertions, 31 deletions
diff --git a/build_extra/rust/dummy.rs b/build_extra/rust/empty_crate.rs
index f328e4d9d..f328e4d9d 100644
--- a/build_extra/rust/dummy.rs
+++ b/build_extra/rust/empty_crate.rs
diff --git a/build_extra/rust/get_rust_ldflags.cmd b/build_extra/rust/get_rustc_info.cmd
index 9d5ce12a1..9d5ce12a1 100644
--- a/build_extra/rust/get_rust_ldflags.cmd
+++ b/build_extra/rust/get_rustc_info.cmd
diff --git a/build_extra/rust/get_rust_ldflags.py b/build_extra/rust/get_rustc_info.py
index 79c7bc3fb..1b61bdbc0 100755
--- a/build_extra/rust/get_rust_ldflags.py
+++ b/build_extra/rust/get_rustc_info.py
@@ -25,28 +25,21 @@
# this script then reads the linker arguments from that temporary file, and
# then filters it to remove flags that are irrelevant or undesirable.
+import json
+import re
import sys
import os
from os import path
-import re
import subprocess
import tempfile
-def capture_args(argsfile_path):
+def capture_linker_args(argsfile_path):
with open(argsfile_path, "wb") as argsfile:
argsfile.write("\n".join(sys.argv[1:]))
-def main():
- # If ARGSFILE_PATH is set this script is being invoked by rustc, which
- # thinks we are a linker. All we do now is write our argv to the specified
- # file and exit. Further processing is done by our grandparent process,
- # also this script but invoked by gn.
- argsfile_path = os.getenv("ARGSFILE_PATH")
- if argsfile_path is not None:
- return capture_args(argsfile_path)
-
+def get_ldflags(rustc_args):
# Prepare the environment for rustc.
rustc_env = os.environ.copy()
@@ -80,12 +73,13 @@ def main():
# Build the rustc command line.
# * `-Clinker=` tells rustc to use our fake linker.
# * `-Csave-temps` prevents rustc from deleting object files after
- # linking. We need to preserve the file `xx.crate.allocator.rcgu.o`.
+ # linking. We need to preserve the extra object file with allocator
+ # symbols (`_rust_alloc` etc.) in it that rustc produces.
rustc_cmd = [
"rustc",
"-Clinker=" + rustc_linker,
"-Csave-temps",
- ] + sys.argv[1:]
+ ] + rustc_args
# Spawn the rust compiler.
rustc_proc = subprocess.Popen(
@@ -143,13 +137,16 @@ def main():
elif arg.endswith(".rlib"):
# Built-in Rust library, e.g. `libstd-8524caae8408aac2.rlib`.
pass
- elif arg.endswith(".crate.allocator.rcgu.o"):
+ elif re.match(r"^empty_crate\.[a-z0-9]+\.rcgu.o$", arg):
# This file is needed because it contains certain allocator
# related symbols (e.g. `__rust_alloc`, `__rust_oom`).
# The Rust compiler normally generates this file just before
# linking an executable. We pass `-Csave-temps` to rustc so it
# doesn't delete the file when it's done linking.
pass
+ elif arg.endswith(".crate.allocator.rcgu.o"):
+ # Same as above, but for rustc version 1.29.0 and older.
+ pass
elif arg.endswith(".lib") and not arg.startswith("msvcrt"):
# Include most Windows static/import libraries (e.g. `ws2_32.lib`).
# However we ignore Rusts choice of C runtime (`mvcrt*.lib`).
@@ -172,8 +169,34 @@ def main():
ldflags += [arg]
- # Write the filtered ldflags to stdout, separated by newline characters.
- sys.stdout.write("\n".join(ldflags))
+ return ldflags
+
+
+def get_version():
+ version = subprocess.check_output(["rustc", "--version"])
+ version = version.strip() # Remove trailing newline.
+ return version
+
+
+def main():
+ # If ARGSFILE_PATH is set this script is being invoked by rustc, which
+ # thinks we are a linker. All we do now is write our argv to the specified
+ # file and exit. Further processing is done by our grandparent process,
+ # also this script but invoked by gn.
+ argsfile_path = os.getenv("ARGSFILE_PATH")
+ if argsfile_path is not None:
+ return capture_linker_args(argsfile_path)
+
+ empty_crate_source = path.join(path.dirname(__file__), "empty_crate.rs")
+
+ info = {
+ "version": get_version(),
+ "ldflags_bin": get_ldflags([empty_crate_source]),
+ "ldflags_test": get_ldflags([empty_crate_source, "--test"])
+ }
+
+ # Write the information dict as a json object.
+ json.dump(info, sys.stdout)
if __name__ == '__main__':
diff --git a/build_extra/rust/rust.gni b/build_extra/rust/rust.gni
index 9cb5729da..889e25467 100644
--- a/build_extra/rust/rust.gni
+++ b/build_extra/rust/rust.gni
@@ -29,23 +29,15 @@ out_dir = "$root_out_dir/rust_crates"
# * To sidestep rustc weirdness (e.g. on Windows, it always links with the
# release C runtime library, even for debug builds).
#
-# The `get_rust_ldflags` tool outputs the linker flags that are needed to
+# The `get_rustc_info` tool outputs the linker flags that are needed to
# successfully link rustc object code into an executable.
# We generate two sets of ldflags:
-# `rust_bin_ldflags`: Used for rust_executable targets.
-# `rust_test_ldflags`: Used for rust_test targets; includes the test harness.
+# `ldflags_bin` : Used for rust_executable targets.
+# `ldflags_test`: Used for rust_test targets; includes the test harness.
#
# The tool works by compiling and linking something with rustc, and analyzing
# the arguments it passes to the system linker. That's what dummy.rs is for.
-dummy_rs_path = rebase_path("dummy.rs", root_build_dir)
-rust_bin_ldflags =
- exec_script("get_rust_ldflags.py", [ dummy_rs_path ], "list lines")
-rust_test_ldflags = exec_script("get_rust_ldflags.py",
- [
- dummy_rs_path,
- "--test",
- ],
- "list lines")
+_rustc_info = exec_script("get_rustc_info.py", [], "json")
template("rust_crate") {
config_name = "${target_name}_config"
@@ -184,7 +176,10 @@ template("rust_crate") {
# This is to disambiguate multiple versions of the same crate.
"-Cextra-filename=$crate_suffix",
- "-Cmetadata=$crate_suffix",
+
+ # Appending the rustc version to the crate metadata ensures that they are
+ # rebuilt when rustc is upgraded, by changing the command line.
+ "-Cmetadata=\"${crate_suffix}_${_rustc_info.version}\"",
# This is needed for transitive dependencies.
"-L",
@@ -244,9 +239,9 @@ template("rust_executable") {
forward_variables_from(invoker, "*")
if (defined(is_test) && is_test) {
- ldflags = rust_test_ldflags
+ ldflags = _rustc_info.ldflags_test
} else {
- ldflags = rust_bin_ldflags
+ ldflags = _rustc_info.ldflags_bin
}
if (!defined(deps)) {