0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 17:34:47 -05:00

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.
This commit is contained in:
Bert Belder 2018-10-25 20:04:23 +02:00
parent 243a3ba2d0
commit 00e4f7cf83
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
4 changed files with 49 additions and 31 deletions

View file

@ -25,28 +25,21 @@
# this script then reads the linker arguments from that temporary file, and # this script then reads the linker arguments from that temporary file, and
# then filters it to remove flags that are irrelevant or undesirable. # then filters it to remove flags that are irrelevant or undesirable.
import json
import re
import sys import sys
import os import os
from os import path from os import path
import re
import subprocess import subprocess
import tempfile import tempfile
def capture_args(argsfile_path): def capture_linker_args(argsfile_path):
with open(argsfile_path, "wb") as argsfile: with open(argsfile_path, "wb") as argsfile:
argsfile.write("\n".join(sys.argv[1:])) argsfile.write("\n".join(sys.argv[1:]))
def main(): def get_ldflags(rustc_args):
# 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)
# Prepare the environment for rustc. # Prepare the environment for rustc.
rustc_env = os.environ.copy() rustc_env = os.environ.copy()
@ -80,12 +73,13 @@ def main():
# Build the rustc command line. # Build the rustc command line.
# * `-Clinker=` tells rustc to use our fake linker. # * `-Clinker=` tells rustc to use our fake linker.
# * `-Csave-temps` prevents rustc from deleting object files after # * `-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_cmd = [
"rustc", "rustc",
"-Clinker=" + rustc_linker, "-Clinker=" + rustc_linker,
"-Csave-temps", "-Csave-temps",
] + sys.argv[1:] ] + rustc_args
# Spawn the rust compiler. # Spawn the rust compiler.
rustc_proc = subprocess.Popen( rustc_proc = subprocess.Popen(
@ -143,13 +137,16 @@ def main():
elif arg.endswith(".rlib"): elif arg.endswith(".rlib"):
# Built-in Rust library, e.g. `libstd-8524caae8408aac2.rlib`. # Built-in Rust library, e.g. `libstd-8524caae8408aac2.rlib`.
pass 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 # This file is needed because it contains certain allocator
# related symbols (e.g. `__rust_alloc`, `__rust_oom`). # related symbols (e.g. `__rust_alloc`, `__rust_oom`).
# The Rust compiler normally generates this file just before # The Rust compiler normally generates this file just before
# linking an executable. We pass `-Csave-temps` to rustc so it # linking an executable. We pass `-Csave-temps` to rustc so it
# doesn't delete the file when it's done linking. # doesn't delete the file when it's done linking.
pass 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"): elif arg.endswith(".lib") and not arg.startswith("msvcrt"):
# Include most Windows static/import libraries (e.g. `ws2_32.lib`). # Include most Windows static/import libraries (e.g. `ws2_32.lib`).
# However we ignore Rusts choice of C runtime (`mvcrt*.lib`). # However we ignore Rusts choice of C runtime (`mvcrt*.lib`).
@ -172,8 +169,34 @@ def main():
ldflags += [arg] ldflags += [arg]
# Write the filtered ldflags to stdout, separated by newline characters. return ldflags
sys.stdout.write("\n".join(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__': if __name__ == '__main__':

View file

@ -29,23 +29,15 @@ out_dir = "$root_out_dir/rust_crates"
# * To sidestep rustc weirdness (e.g. on Windows, it always links with the # * To sidestep rustc weirdness (e.g. on Windows, it always links with the
# release C runtime library, even for debug builds). # 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. # successfully link rustc object code into an executable.
# We generate two sets of ldflags: # We generate two sets of ldflags:
# `rust_bin_ldflags`: Used for rust_executable targets. # `ldflags_bin` : Used for rust_executable targets.
# `rust_test_ldflags`: Used for rust_test targets; includes the test harness. # `ldflags_test`: Used for rust_test targets; includes the test harness.
# #
# The tool works by compiling and linking something with rustc, and analyzing # 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. # 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) _rustc_info = exec_script("get_rustc_info.py", [], "json")
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")
template("rust_crate") { template("rust_crate") {
config_name = "${target_name}_config" config_name = "${target_name}_config"
@ -184,7 +176,10 @@ template("rust_crate") {
# This is to disambiguate multiple versions of the same crate. # This is to disambiguate multiple versions of the same crate.
"-Cextra-filename=$crate_suffix", "-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. # This is needed for transitive dependencies.
"-L", "-L",
@ -244,9 +239,9 @@ template("rust_executable") {
forward_variables_from(invoker, "*") forward_variables_from(invoker, "*")
if (defined(is_test) && is_test) { if (defined(is_test) && is_test) {
ldflags = rust_test_ldflags ldflags = _rustc_info.ldflags_test
} else { } else {
ldflags = rust_bin_ldflags ldflags = _rustc_info.ldflags_bin
} }
if (!defined(deps)) { if (!defined(deps)) {