未验证 提交 00e4f7cf 编写于 作者: B Bert Belder

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.
上级 243a3ba2
......@@ -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__':
......
......@@ -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)) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册