blob: 87c8fb0a1c6e888837767c598bb663787f8b2dc2 [file] [log] [blame]
Adrian Taylor792467f22021-10-29 20:18:301#!/usr/bin/env vpython3
2
3# Copyright 2021 The Chromium Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7# This is a wrapper script which runs a Cargo build.rs build script
8# executable in a Cargo-like environment. Build scripts can do arbitrary
9# things and we can't support everything. Moreover, we do not WANT
10# to support everything because that means the build is not deterministic.
11# Code review processes must be applied to ensure that the build script
12# depends upon only these inputs:
13#
14# * The environment variables set by Cargo here:
15# https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
16# * Output from rustc commands, e.g. to figure out the Rust version.
17#
18# Similarly, the only allowable output from such a build script
19# is currently:
20#
21# * Generated .rs files
22# * cargo:rustc-cfg output.
23#
24# That's it. We don't even support the other standard cargo:rustc-
25# output messages.
26
27import os
28import sys
29
Adrian Taylor1f172cd2021-11-04 18:35:4430# Set up path to be able to import build_utils
Adrian Taylor792467f22021-10-29 20:18:3031sys.path.append(
32 os.path.join(os.path.dirname(os.path.abspath(__file__)), os.pardir,
Adrian Taylor1f172cd2021-11-04 18:35:4433 os.pardir, 'build', 'android', 'gyp'))
Adrian Taylor792467f22021-10-29 20:18:3034from util import build_utils
35
36import argparse
37import io
38import subprocess
39import re
40import platform
41
42RUSTC_VERSION_LINE = re.compile(r"(\w+): (.*)")
43
44
45def rustc_name():
46 if platform.system() == 'Windows':
47 return "rustc.exe"
48 else:
49 return "rustc"
50
51
52def host_triple(rustc_path):
53 """ Works out the host rustc target. """
54 args = [rustc_path, "-vV"]
55 known_vars = dict()
56 proc = subprocess.Popen(args, stdout=subprocess.PIPE)
57 for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):
58 m = RUSTC_VERSION_LINE.match(line.rstrip())
59 if m:
60 known_vars[m.group(1)] = m.group(2)
61 return known_vars["host"]
62
63
64RUSTC_CFG_LINE = re.compile("cargo:rustc-cfg=(.*)")
65
66parser = argparse.ArgumentParser(description='Run Rust build script.')
67parser.add_argument('--build-script', required=True, help='build script to run')
68parser.add_argument('--output',
69 required=True,
70 help='where to write output rustc flags')
71parser.add_argument('--target', help='rust target triple')
Adrian Taylore9e15d12021-11-18 19:36:2172parser.add_argument('--features', help='features', nargs='+')
Adrian Taylor792467f22021-10-29 20:18:3073parser.add_argument('--rust-prefix', required=True, help='rust path prefix')
74parser.add_argument('--out-dir', required=True, help='target out dir')
Adrian Taylorb238a972021-12-01 15:02:2375parser.add_argument('--src-dir', required=True, help='target source dir')
Adrian Taylor792467f22021-10-29 20:18:3076
77args = parser.parse_args()
78
79rustc_path = os.path.join(args.rust_prefix, rustc_name())
80env = os.environ.copy()
81env.clear() # try to avoid build scripts depending on other things
Adrian Taylorb238a972021-12-01 15:02:2382env["RUSTC"] = os.path.abspath(rustc_path)
83env["OUT_DIR"] = os.path.abspath(args.out_dir)
84env["CARGO_MANIFEST_DIR"] = os.path.abspath(args.src_dir)
Adrian Taylor792467f22021-10-29 20:18:3085env["HOST"] = host_triple(rustc_path)
86if args.target is None:
87 env["TARGET"] = env["HOST"]
88else:
89 env["TARGET"] = args.target
Adrian Taylore9e15d12021-11-18 19:36:2190if args.features:
91 for f in args.features:
92 feature_name = f.upper().replace("-", "_")
93 env["CARGO_FEATURE_%s" % feature_name] = "1"
94
95# In the future we should, set all the variables listed here:
Adrian Taylor792467f22021-10-29 20:18:3096# https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-sets-for-build-scripts
97
Adrian Taylor792467f22021-10-29 20:18:3098# In the future, we could consider isolating this build script
99# into a chroot jail or similar on some platforms, but ultimately
100# we are always going to be reliant on code review to ensure the
101# build script is deterministic and trustworthy, so this would
102# really just be a backup to humans.
Adrian Taylora63952d52021-11-30 18:49:22103proc = subprocess.run([os.path.abspath(args.build_script)],
Adrian Taylor792467f22021-10-29 20:18:30104 env=env,
Adrian Taylorb238a972021-12-01 15:02:23105 cwd=args.src_dir,
Adrian Taylor792467f22021-10-29 20:18:30106 text=True,
107 capture_output=True)
108
Adrian Taylorb238a972021-12-01 15:02:23109if proc.stderr.rstrip():
110 print(proc.stderr.rstrip(), file=sys.stderr)
111proc.check_returncode()
112
Adrian Taylor5711e2132021-11-09 15:09:09113flags = ""
Adrian Taylor792467f22021-10-29 20:18:30114for line in proc.stdout.split("\n"):
115 m = RUSTC_CFG_LINE.match(line.rstrip())
116 if m:
Adrian Taylor5711e2132021-11-09 15:09:09117 flags = "%s--cfg\n%s\n" % (flags, m.group(1))
Adrian Taylor792467f22021-10-29 20:18:30118
Adrian Taylor5711e2132021-11-09 15:09:09119# AtomicOutput will ensure we only write to the file on disk if what we give to
120# write() is different than what's currently on disk.
121with build_utils.AtomicOutput(args.output) as output:
122 output.write(flags.encode("utf-8"))