summaryrefslogtreecommitdiffstats
path: root/src/bootstrap
diff options
context:
space:
mode:
Diffstat (limited to 'src/bootstrap')
-rw-r--r--src/bootstrap/Cargo.lock46
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/README.md5
-rw-r--r--src/bootstrap/bin/_helper.rs24
-rw-r--r--src/bootstrap/bin/rustc.rs17
-rw-r--r--src/bootstrap/bin/rustdoc.rs19
-rw-r--r--src/bootstrap/bootstrap.py141
-rw-r--r--src/bootstrap/builder.rs18
-rw-r--r--src/bootstrap/builder/tests.rs4
-rw-r--r--src/bootstrap/check.rs11
-rw-r--r--src/bootstrap/compile.rs14
-rw-r--r--src/bootstrap/config.rs42
-rw-r--r--src/bootstrap/config/tests.rs16
-rwxr-xr-xsrc/bootstrap/configure.py1
-rw-r--r--src/bootstrap/download.rs21
-rw-r--r--src/bootstrap/format.rs4
-rw-r--r--src/bootstrap/install.rs59
-rw-r--r--src/bootstrap/job.rs2
-rw-r--r--src/bootstrap/lib.rs17
-rw-r--r--src/bootstrap/llvm.rs56
-rw-r--r--src/bootstrap/mk/Makefile.in7
-rw-r--r--src/bootstrap/sanity.rs44
-rw-r--r--src/bootstrap/setup.rs1
-rw-r--r--src/bootstrap/test.rs174
-rw-r--r--src/bootstrap/tool.rs3
25 files changed, 474 insertions, 274 deletions
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index ecb58a0e9..f5220e361 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -142,7 +142,7 @@ dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.8",
+ "syn",
]
[[package]]
@@ -229,16 +229,6 @@ dependencies = [
]
[[package]]
-name = "ctor"
-version = "0.1.22"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
-dependencies = [
- "quote",
- "syn 1.0.102",
-]
-
-[[package]]
name = "diff"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -350,9 +340,9 @@ dependencies = [
[[package]]
name = "hermit-abi"
-version = "0.3.1"
+version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
[[package]]
name = "hex"
@@ -384,7 +374,7 @@ version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
dependencies = [
- "hermit-abi 0.3.1",
+ "hermit-abi 0.3.2",
"libc",
"windows-sys",
]
@@ -503,15 +493,6 @@ dependencies = [
]
[[package]]
-name = "output_vt100"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
-dependencies = [
- "winapi",
-]
-
-[[package]]
name = "pkg-config"
version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -519,13 +500,11 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "pretty_assertions"
-version = "1.3.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
+checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
dependencies = [
- "ctor",
"diff",
- "output_vt100",
"yansi",
]
@@ -657,7 +636,7 @@ checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.8",
+ "syn",
]
[[package]]
@@ -684,17 +663,6 @@ dependencies = [
[[package]]
name = "syn"
-version = "1.0.102"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fcd952facd492f9be3ef0d0b7032a6e442ee9b361d4acc2b1d0c4aaa5f613a1"
-dependencies = [
- "proc-macro2",
- "quote",
- "unicode-ident",
-]
-
-[[package]]
-name = "syn"
version = "2.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 74b9a23fa..9bf26948a 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -78,7 +78,7 @@ features = [
]
[dev-dependencies]
-pretty_assertions = "1.2"
+pretty_assertions = "1.4"
[features]
build-metrics = ["sysinfo"]
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 253d504d7..548281ca5 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -1,8 +1,7 @@
# rustbuild - Bootstrapping Rust
-This is an in-progress README which is targeted at helping to explain how Rust
-is bootstrapped and in general, some of the technical details of the build
-system.
+This README is aimed at helping to explain how Rust is bootstrapped and in general,
+some of the technical details of the build system.
Note that this README only covers internal information, not how to use the tool.
Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information.
diff --git a/src/bootstrap/bin/_helper.rs b/src/bootstrap/bin/_helper.rs
new file mode 100644
index 000000000..09aa471db
--- /dev/null
+++ b/src/bootstrap/bin/_helper.rs
@@ -0,0 +1,24 @@
+/// Parses the value of the "RUSTC_VERBOSE" environment variable and returns it as a `usize`.
+/// If it was not defined, returns 0 by default.
+///
+/// Panics if "RUSTC_VERBOSE" is defined with the value that is not an unsigned integer.
+fn parse_rustc_verbose() -> usize {
+ use std::str::FromStr;
+
+ match std::env::var("RUSTC_VERBOSE") {
+ Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
+ Err(_) => 0,
+ }
+}
+
+/// Parses the value of the "RUSTC_STAGE" environment variable and returns it as a `String`.
+///
+/// If "RUSTC_STAGE" was not set, the program will be terminated with 101.
+fn parse_rustc_stage() -> String {
+ std::env::var("RUSTC_STAGE").unwrap_or_else(|_| {
+ // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead.
+ eprintln!("rustc shim: fatal: RUSTC_STAGE was not set");
+ eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap");
+ exit(101);
+ })
+}
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 10718aeb8..20cd63b96 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -16,27 +16,25 @@
//! never get replaced.
include!("../dylib_util.rs");
+include!("./_helper.rs");
use std::env;
use std::path::PathBuf;
use std::process::{exit, Child, Command};
-use std::str::FromStr;
use std::time::Instant;
fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
let arg = |name| args.windows(2).find(|args| args[0] == name).and_then(|args| args[1].to_str());
+ let stage = parse_rustc_stage();
+ let verbose = parse_rustc_verbose();
+
// Detect whether or not we're a build script depending on whether --target
// is passed (a bit janky...)
let target = arg("--target");
let version = args.iter().find(|w| &**w == "-vV");
- let verbose = match env::var("RUSTC_VERBOSE") {
- Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
- Err(_) => 0,
- };
-
// Use a different compiler for build scripts, since there may not yet be a
// libstd for the real compiler to use. However, if Cargo is attempting to
// determine the version of the compiler, the real compiler needs to be
@@ -47,12 +45,7 @@ fn main() {
} else {
("RUSTC_REAL", "RUSTC_LIBDIR")
};
- let stage = env::var("RUSTC_STAGE").unwrap_or_else(|_| {
- // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead.
- eprintln!("rustc shim: fatal: RUSTC_STAGE was not set");
- eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap");
- exit(101);
- });
+
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
let on_fail = env::var_os("RUSTC_ON_FAIL").map(Command::new);
diff --git a/src/bootstrap/bin/rustdoc.rs b/src/bootstrap/bin/rustdoc.rs
index 4ecb33498..6561c1c19 100644
--- a/src/bootstrap/bin/rustdoc.rs
+++ b/src/bootstrap/bin/rustdoc.rs
@@ -9,14 +9,14 @@ use std::process::{exit, Command};
include!("../dylib_util.rs");
+include!("./_helper.rs");
+
fn main() {
let args = env::args_os().skip(1).collect::<Vec<_>>();
- let stage = env::var("RUSTC_STAGE").unwrap_or_else(|_| {
- // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead.
- eprintln!("rustc shim: fatal: RUSTC_STAGE was not set");
- eprintln!("rustc shim: note: use `x.py build -vvv` to see all environment variables set by bootstrap");
- exit(101);
- });
+
+ let stage = parse_rustc_stage();
+ let verbose = parse_rustc_verbose();
+
let rustdoc = env::var_os("RUSTDOC_REAL").expect("RUSTDOC_REAL was not set");
let libdir = env::var_os("RUSTDOC_LIBDIR").expect("RUSTDOC_LIBDIR was not set");
let sysroot = env::var_os("RUSTC_SYSROOT").expect("RUSTC_SYSROOT was not set");
@@ -25,13 +25,6 @@ fn main() {
// is passed (a bit janky...)
let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str());
- use std::str::FromStr;
-
- let verbose = match env::var("RUSTC_VERBOSE") {
- Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
- Err(_) => 0,
- };
-
let mut dylib_path = dylib_path();
dylib_path.insert(0, PathBuf::from(libdir.clone()));
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index f44a05a6b..fac0cdf20 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -41,6 +41,10 @@ def get_cpus():
return 1
+def eprint(*args, **kwargs):
+ kwargs["file"] = sys.stderr
+ print(*args, **kwargs)
+
def get(base, url, path, checksums, verbose=False):
with tempfile.NamedTemporaryFile(delete=False) as temp_file:
@@ -57,23 +61,23 @@ def get(base, url, path, checksums, verbose=False):
if os.path.exists(path):
if verify(path, sha256, False):
if verbose:
- print("using already-download file", path, file=sys.stderr)
+ eprint("using already-download file", path)
return
else:
if verbose:
- print("ignoring already-download file",
- path, "due to failed verification", file=sys.stderr)
+ eprint("ignoring already-download file",
+ path, "due to failed verification")
os.unlink(path)
download(temp_path, "{}/{}".format(base, url), True, verbose)
if not verify(temp_path, sha256, verbose):
raise RuntimeError("failed verification")
if verbose:
- print("moving {} to {}".format(temp_path, path), file=sys.stderr)
+ eprint("moving {} to {}".format(temp_path, path))
shutil.move(temp_path, path)
finally:
if os.path.isfile(temp_path):
if verbose:
- print("removing", temp_path, file=sys.stderr)
+ eprint("removing", temp_path)
os.unlink(temp_path)
@@ -83,7 +87,7 @@ def download(path, url, probably_big, verbose):
_download(path, url, probably_big, verbose, True)
return
except RuntimeError:
- print("\nspurious failure, trying again", file=sys.stderr)
+ eprint("\nspurious failure, trying again")
_download(path, url, probably_big, verbose, False)
@@ -94,7 +98,7 @@ def _download(path, url, probably_big, verbose, exception):
# - If we are on win32 fallback to powershell
# - Otherwise raise the error if appropriate
if probably_big or verbose:
- print("downloading {}".format(url), file=sys.stderr)
+ eprint("downloading {}".format(url))
try:
if (probably_big or verbose) and "GITHUB_ACTIONS" not in os.environ:
@@ -104,16 +108,15 @@ def _download(path, url, probably_big, verbose, exception):
# If curl is not present on Win32, we should not sys.exit
# but raise `CalledProcessError` or `OSError` instead
require(["curl", "--version"], exception=platform_is_win32())
- with open(path, "wb") as outfile:
- run(["curl", option,
- "-L", # Follow redirect.
- "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds
- "--connect-timeout", "30", # timeout if cannot connect within 30 seconds
- "--retry", "3", "-SRf", url],
- stdout=outfile, #Implements cli redirect operator '>'
- verbose=verbose,
- exception=True, # Will raise RuntimeError on failure
- )
+ run(["curl", option,
+ "-L", # Follow redirect.
+ "-y", "30", "-Y", "10", # timeout if speed is < 10 bytes/sec for > 30 seconds
+ "--connect-timeout", "30", # timeout if cannot connect within 30 seconds
+ "-o", path,
+ "--retry", "3", "-SRf", url],
+ verbose=verbose,
+ exception=True, # Will raise RuntimeError on failure
+ )
except (subprocess.CalledProcessError, OSError, RuntimeError):
# see http://serverfault.com/questions/301128/how-to-download
if platform_is_win32():
@@ -130,20 +133,20 @@ def _download(path, url, probably_big, verbose, exception):
def verify(path, expected, verbose):
"""Check if the sha256 sum of the given path is valid"""
if verbose:
- print("verifying", path, file=sys.stderr)
+ eprint("verifying", path)
with open(path, "rb") as source:
found = hashlib.sha256(source.read()).hexdigest()
verified = found == expected
if not verified:
- print("invalid checksum:\n"
+ eprint("invalid checksum:\n"
" found: {}\n"
- " expected: {}".format(found, expected), file=sys.stderr)
+ " expected: {}".format(found, expected))
return verified
def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
"""Unpack the given tarball file"""
- print("extracting", tarball, file=sys.stderr)
+ eprint("extracting", tarball)
fname = os.path.basename(tarball).replace(tarball_suffix, "")
with contextlib.closing(tarfile.open(tarball)) as tar:
for member in tar.getnames():
@@ -156,7 +159,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
dst_path = os.path.join(dst, name)
if verbose:
- print(" extracting", member, file=sys.stderr)
+ eprint(" extracting", member)
tar.extract(member, dst)
src_path = os.path.join(dst, member)
if os.path.isdir(src_path) and os.path.exists(dst_path):
@@ -168,7 +171,7 @@ def unpack(tarball, tarball_suffix, dst, verbose=False, match=None):
def run(args, verbose=False, exception=False, is_bootstrap=False, **kwargs):
"""Run a child program in a new process"""
if verbose:
- print("running: " + ' '.join(args), file=sys.stderr)
+ eprint("running: " + ' '.join(args))
sys.stdout.flush()
# Ensure that the .exe is used on Windows just in case a Linux ELF has been
# compiled in the same directory.
@@ -208,8 +211,8 @@ def require(cmd, exit=True, exception=False):
if exception:
raise
elif exit:
- print("error: unable to run `{}`: {}".format(' '.join(cmd), exc), file=sys.stderr)
- print("Please make sure it's installed and in the path.", file=sys.stderr)
+ eprint("error: unable to run `{}`: {}".format(' '.join(cmd), exc))
+ eprint("Please make sure it's installed and in the path.")
sys.exit(1)
return None
@@ -240,14 +243,12 @@ def default_build_triple(verbose):
host = next(x for x in version.split('\n') if x.startswith("host: "))
triple = host.split("host: ")[1]
if verbose:
- print("detected default triple {} from pre-installed rustc".format(triple),
- file=sys.stderr)
+ eprint("detected default triple {} from pre-installed rustc".format(triple))
return triple
except Exception as e:
if verbose:
- print("pre-installed rustc not detected: {}".format(e),
- file=sys.stderr)
- print("falling back to auto-detect", file=sys.stderr)
+ eprint("pre-installed rustc not detected: {}".format(e))
+ eprint("falling back to auto-detect")
required = not platform_is_win32()
uname = require(["uname", "-smp"], exit=required)
@@ -266,7 +267,8 @@ def default_build_triple(verbose):
'FreeBSD': 'unknown-freebsd',
'Haiku': 'unknown-haiku',
'NetBSD': 'unknown-netbsd',
- 'OpenBSD': 'unknown-openbsd'
+ 'OpenBSD': 'unknown-openbsd',
+ 'GNU': 'unknown-hurd',
}
# Consider the direct transformation first and then the special cases
@@ -313,6 +315,14 @@ def default_build_triple(verbose):
# non-standard string (e.g. gnuwin32 tools returns `windows32`). In
# these cases, fall back to using sys.platform.
return 'x86_64-pc-windows-msvc'
+ elif kernel == 'AIX':
+ # `uname -m` returns the machine ID rather than machine hardware on AIX,
+ # so we are unable to use cputype to form triple. AIX 7.2 and
+ # above supports 32-bit and 64-bit mode simultaneously and `uname -p`
+ # returns `powerpc`, however we only supports `powerpc64-ibm-aix` in
+ # rust on AIX. For above reasons, kerneltype_mapper and cputype_mapper
+ # are not used to infer AIX's triple.
+ return 'powerpc64-ibm-aix'
else:
err = "unknown OS type: {}".format(kernel)
sys.exit(err)
@@ -329,6 +339,7 @@ def default_build_triple(verbose):
'i386': 'i686',
'i486': 'i686',
'i686': 'i686',
+ 'i686-AT386': 'i686',
'i786': 'i686',
'loongarch64': 'loongarch64',
'm68k': 'm68k',
@@ -623,7 +634,7 @@ class RustBuild(object):
def should_fix_bins_and_dylibs(self):
"""Whether or not `fix_bin_or_dylib` needs to be run; can only be True
- on NixOS.
+ on NixOS or if config.toml has `build.patch-binaries-for-nix` set.
"""
if self._should_fix_bins_and_dylibs is not None:
return self._should_fix_bins_and_dylibs
@@ -643,27 +654,34 @@ class RustBuild(object):
if ostype != "Linux":
return False
- # If the user has asked binaries to be patched for Nix, then
- # don't check for NixOS or `/lib`.
+ # If the user has explicitly indicated whether binaries should be
+ # patched for Nix, then don't check for NixOS.
if self.get_toml("patch-binaries-for-nix", "build") == "true":
return True
+ if self.get_toml("patch-binaries-for-nix", "build") == "false":
+ return False
# Use `/etc/os-release` instead of `/etc/NIXOS`.
# The latter one does not exist on NixOS when using tmpfs as root.
try:
with open("/etc/os-release", "r") as f:
- if not any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f):
- return False
+ is_nixos = any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"')
+ for ln in f)
except FileNotFoundError:
- return False
- if os.path.exists("/lib"):
- return False
+ is_nixos = False
- return True
+ # If not on NixOS, then warn if user seems to be atop Nix shell
+ if not is_nixos:
+ in_nix_shell = os.getenv('IN_NIX_SHELL')
+ if in_nix_shell:
+ eprint("The IN_NIX_SHELL environment variable is `{}`;".format(in_nix_shell),
+ "you may need to set `patch-binaries-for-nix=true` in config.toml")
+
+ return is_nixos
answer = self._should_fix_bins_and_dylibs = get_answer()
if answer:
- print("info: You seem to be using Nix.", file=sys.stderr)
+ eprint("info: You seem to be using Nix.")
return answer
def fix_bin_or_dylib(self, fname):
@@ -676,7 +694,7 @@ class RustBuild(object):
Please see https://nixos.org/patchelf.html for more information
"""
assert self._should_fix_bins_and_dylibs is True
- print("attempting to patch", fname, file=sys.stderr)
+ eprint("attempting to patch", fname)
# Only build `.nix-deps` once.
nix_deps_dir = self.nix_deps_dir
@@ -709,7 +727,7 @@ class RustBuild(object):
"nix-build", "-E", nix_expr, "-o", nix_deps_dir,
])
except subprocess.CalledProcessError as reason:
- print("warning: failed to call nix-build:", reason, file=sys.stderr)
+ eprint("warning: failed to call nix-build:", reason)
return
self.nix_deps_dir = nix_deps_dir
@@ -729,7 +747,7 @@ class RustBuild(object):
try:
subprocess.check_output([patchelf] + patchelf_args + [fname])
except subprocess.CalledProcessError as reason:
- print("warning: failed to call patchelf:", reason, file=sys.stderr)
+ eprint("warning: failed to call patchelf:", reason)
return
def rustc_stamp(self):
@@ -871,7 +889,7 @@ class RustBuild(object):
if "GITHUB_ACTIONS" in env:
print("::group::Building bootstrap")
else:
- print("Building bootstrap", file=sys.stderr)
+ eprint("Building bootstrap")
args = self.build_bootstrap_cmd(env)
# Run this from the source directory so cargo finds .cargo/config
@@ -980,12 +998,9 @@ class RustBuild(object):
if 'SUDO_USER' in os.environ and not self.use_vendored_sources:
if os.getuid() == 0:
self.use_vendored_sources = True
- print('info: looks like you\'re trying to run this command as root',
- file=sys.stderr)
- print(' and so in order to preserve your $HOME this will now',
- file=sys.stderr)
- print(' use vendored sources by default.',
- file=sys.stderr)
+ eprint('info: looks like you\'re trying to run this command as root')
+ eprint(' and so in order to preserve your $HOME this will now')
+ eprint(' use vendored sources by default.')
cargo_dir = os.path.join(self.rust_root, '.cargo')
if self.use_vendored_sources:
@@ -995,18 +1010,14 @@ class RustBuild(object):
"--sync ./src/tools/rust-analyzer/Cargo.toml " \
"--sync ./compiler/rustc_codegen_cranelift/Cargo.toml " \
"--sync ./src/bootstrap/Cargo.toml "
- print('error: vendoring required, but vendor directory does not exist.',
- file=sys.stderr)
- print(' Run `cargo vendor {}` to initialize the '
- 'vendor directory.'.format(sync_dirs),
- file=sys.stderr)
- print('Alternatively, use the pre-vendored `rustc-src` dist component.',
- file=sys.stderr)
+ eprint('error: vendoring required, but vendor directory does not exist.')
+ eprint(' Run `cargo vendor {}` to initialize the '
+ 'vendor directory.'.format(sync_dirs))
+ eprint('Alternatively, use the pre-vendored `rustc-src` dist component.')
raise Exception("{} not found".format(vendor_dir))
if not os.path.exists(cargo_dir):
- print('error: vendoring required, but .cargo/config does not exist.',
- file=sys.stderr)
+ eprint('error: vendoring required, but .cargo/config does not exist.')
raise Exception("{} not found".format(cargo_dir))
else:
if os.path.exists(cargo_dir):
@@ -1100,10 +1111,9 @@ def main():
# If the user is asking for help, let them know that the whole download-and-build
# process has to happen before anything is printed out.
if help_triggered:
- print(
+ eprint(
"info: Downloading and building bootstrap before processing --help command.\n"
- " See src/bootstrap/README.md for help with common commands."
- , file=sys.stderr)
+ " See src/bootstrap/README.md for help with common commands.")
exit_code = 0
success_word = "successfully"
@@ -1114,12 +1124,11 @@ def main():
exit_code = error.code
else:
exit_code = 1
- print(error, file=sys.stderr)
+ eprint(error)
success_word = "unsuccessfully"
if not help_triggered:
- print("Build completed", success_word, "in", format_build_time(time() - start_time),
- file=sys.stderr)
+ eprint("Build completed", success_word, "in", format_build_time(time() - start_time))
sys.exit(exit_code)
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index b36661928..46a62eed9 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -302,8 +302,10 @@ impl StepDescription {
}
}
- fn maybe_run(&self, builder: &Builder<'_>, pathsets: Vec<PathSet>) {
- if pathsets.iter().any(|set| self.is_excluded(builder, set)) {
+ fn maybe_run(&self, builder: &Builder<'_>, mut pathsets: Vec<PathSet>) {
+ pathsets.retain(|set| !self.is_excluded(builder, set));
+
+ if pathsets.is_empty() {
return;
}
@@ -523,7 +525,7 @@ impl<'a> ShouldRun<'a> {
.iter()
.map(|p| {
// assert only if `p` isn't submodule
- if !submodules_paths.iter().find(|sm_p| p.contains(*sm_p)).is_some() {
+ if submodules_paths.iter().find(|sm_p| p.contains(*sm_p)).is_none() {
assert!(
self.builder.src.join(p).exists(),
"`should_run.paths` should correspond to real on-disk paths - use `alias` if there is no relevant path: {}",
@@ -703,7 +705,8 @@ impl<'a> Builder<'a> {
llvm::Lld,
llvm::CrtBeginEnd,
tool::RustdocGUITest,
- tool::OptimizedDist
+ tool::OptimizedDist,
+ tool::CoverageDump,
),
Kind::Check | Kind::Clippy | Kind::Fix => describe!(
check::Std,
@@ -725,6 +728,7 @@ impl<'a> Builder<'a> {
test::Tidy,
test::Ui,
test::RunPassValgrind,
+ test::CoverageMap,
test::RunCoverage,
test::MirOpt,
test::Codegen,
@@ -733,6 +737,7 @@ impl<'a> Builder<'a> {
test::Incremental,
test::Debuginfo,
test::UiFullDeps,
+ test::CodegenCranelift,
test::Rustdoc,
test::RunCoverageRustdoc,
test::Pretty,
@@ -1635,7 +1640,10 @@ impl<'a> Builder<'a> {
// flesh out rpath support more fully in the future.
rustflags.arg("-Zosx-rpath-install-name");
Some(format!("-Wl,-rpath,@loader_path/../{libdir}"))
- } else if !target.contains("windows") && !target.contains("aix") {
+ } else if !target.contains("windows")
+ && !target.contains("aix")
+ && !target.contains("xous")
+ {
rustflags.arg("-Clink-args=-Wl,-z,origin");
Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}"))
} else {
diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs
index 43b4a34fe..80e66622e 100644
--- a/src/bootstrap/builder/tests.rs
+++ b/src/bootstrap/builder/tests.rs
@@ -136,9 +136,9 @@ fn test_exclude_kind() {
let mut config = configure("test", &["A"], &["A"]);
// Ensure our test is valid, and `test::Rustc` would be run without the exclude.
assert!(run_build(&[], config.clone()).contains::<test::CrateLibrustc>());
- // Ensure tests for rustc are skipped.
+ // Ensure tests for rustc are not skipped.
config.skip = vec![path.clone()];
- assert!(!run_build(&[], config.clone()).contains::<test::CrateLibrustc>());
+ assert!(run_build(&[], config.clone()).contains::<test::CrateLibrustc>());
// Ensure builds for rustc are not skipped.
assert!(run_build(&[], config).contains::<compile::Rustc>());
}
diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs
index bdefc41c9..b417abc00 100644
--- a/src/bootstrap/check.rs
+++ b/src/bootstrap/check.rs
@@ -353,10 +353,17 @@ pub struct RustAnalyzer {
impl Step for RustAnalyzer {
type Output = ();
const ONLY_HOSTS: bool = true;
- const DEFAULT: bool = false;
+ const DEFAULT: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/tools/rust-analyzer")
+ let builder = run.builder;
+ run.path("src/tools/rust-analyzer").default_condition(
+ builder
+ .config
+ .tools
+ .as_ref()
+ .map_or(true, |tools| tools.iter().any(|tool| tool == "rust-analyzer")),
+ )
}
fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index 9c68e5a78..292ccc578 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -570,6 +570,9 @@ fn copy_sanitizers(
let dst = libdir.join(&runtime.name);
builder.copy(&runtime.path, &dst);
+ // The `aarch64-apple-ios-macabi` and `x86_64-apple-ios-macabi` are also supported for
+ // sanitizers, but they share a sanitizer runtime with `${arch}-apple-darwin`, so we do
+ // not list them here to rename and sign the runtime library.
if target == "x86_64-apple-darwin"
|| target == "aarch64-apple-darwin"
|| target == "aarch64-apple-ios"
@@ -876,10 +879,8 @@ impl Step for Rustc {
cargo.rustflag("-Clto=off");
}
}
- } else {
- if builder.config.rust_lto == RustcLto::Off {
- cargo.rustflag("-Clto=off");
- }
+ } else if builder.config.rust_lto == RustcLto::Off {
+ cargo.rustflag("-Clto=off");
}
for krate in &*self.crates {
@@ -1788,7 +1789,10 @@ pub fn run_cargo(
// During check builds we need to keep crate metadata
keep = true;
} else if rlib_only_metadata {
- if filename.contains("jemalloc_sys") || filename.contains("rustc_smir") {
+ if filename.contains("jemalloc_sys")
+ || filename.contains("rustc_smir")
+ || filename.contains("stable_mir")
+ {
// jemalloc_sys and rustc_smir are not linked into librustc_driver.so,
// so we need to distribute them as rlib to be able to use them.
keep |= filename.ends_with(".rlib");
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 4821d20a8..836328f94 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -137,7 +137,7 @@ pub struct Config {
pub json_output: bool,
pub test_compare_mode: bool,
pub color: Color,
- pub patch_binaries_for_nix: bool,
+ pub patch_binaries_for_nix: Option<bool>,
pub stage0_metadata: Stage0Metadata,
pub stdout_is_tty: bool,
@@ -322,33 +322,23 @@ pub struct RustfmtMetadata {
pub version: String,
}
-#[derive(Clone, Debug)]
+#[derive(Clone, Debug, Default)]
pub enum RustfmtState {
SystemToolchain(PathBuf),
Downloaded(PathBuf),
Unavailable,
+ #[default]
LazyEvaluated,
}
-impl Default for RustfmtState {
- fn default() -> Self {
- RustfmtState::LazyEvaluated
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq)]
+#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub enum LlvmLibunwind {
+ #[default]
No,
InTree,
System,
}
-impl Default for LlvmLibunwind {
- fn default() -> Self {
- Self::No
- }
-}
-
impl FromStr for LlvmLibunwind {
type Err = String;
@@ -362,19 +352,14 @@ impl FromStr for LlvmLibunwind {
}
}
-#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum SplitDebuginfo {
Packed,
Unpacked,
+ #[default]
Off,
}
-impl Default for SplitDebuginfo {
- fn default() -> Self {
- SplitDebuginfo::Off
- }
-}
-
impl std::str::FromStr for SplitDebuginfo {
type Err = ();
@@ -547,11 +532,7 @@ pub struct Target {
impl Target {
pub fn from_triple(triple: &str) -> Self {
let mut target: Self = Default::default();
- if triple.contains("-none")
- || triple.contains("nvptx")
- || triple.contains("switch")
- || triple.contains("-uefi")
- {
+ if triple.contains("-none") || triple.contains("nvptx") || triple.contains("switch") {
target.no_std = true;
}
target
@@ -1276,7 +1257,8 @@ impl Config {
}
config.initial_rustc = if let Some(rustc) = build.rustc {
- config.check_build_rustc_version(&rustc);
+ // FIXME(#115065): re-enable this check
+ // config.check_build_rustc_version(&rustc);
PathBuf::from(rustc)
} else {
config.download_beta_toolchain();
@@ -1338,7 +1320,7 @@ impl Config {
set(&mut config.local_rebuild, build.local_rebuild);
set(&mut config.print_step_timings, build.print_step_timings);
set(&mut config.print_step_rusage, build.print_step_rusage);
- set(&mut config.patch_binaries_for_nix, build.patch_binaries_for_nix);
+ config.patch_binaries_for_nix = build.patch_binaries_for_nix;
config.verbose = cmp::max(config.verbose, flags.verbose as usize);
@@ -1528,7 +1510,7 @@ impl Config {
let asserts = llvm_assertions.unwrap_or(false);
config.llvm_from_ci = match llvm.download_ci_llvm {
Some(StringOrBool::String(s)) => {
- assert!(s == "if-available", "unknown option `{s}` for download-ci-llvm");
+ assert_eq!(s, "if-available", "unknown option `{s}` for download-ci-llvm");
crate::llvm::is_ci_llvm_available(&config, asserts)
}
Some(StringOrBool::Bool(b)) => b,
diff --git a/src/bootstrap/config/tests.rs b/src/bootstrap/config/tests.rs
index c340bb298..aac76cdcb 100644
--- a/src/bootstrap/config/tests.rs
+++ b/src/bootstrap/config/tests.rs
@@ -35,7 +35,7 @@ fn download_ci_llvm() {
));
}
-// FIXME(ozkanonur): extend scope of the test
+// FIXME(onur-ozkan): extend scope of the test
// refs:
// - https://github.com/rust-lang/rust/issues/109120
// - https://github.com/rust-lang/rust/pull/109162#issuecomment-1496782487
@@ -136,7 +136,7 @@ build-config = {}
"setting string value without quotes"
);
assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
- assert_eq!(config.deny_warnings, false, "setting boolean value");
+ assert!(!config.deny_warnings, "setting boolean value");
assert_eq!(
config.tools,
Some(["cargo".to_string()].into_iter().collect()),
@@ -181,13 +181,13 @@ fn profile_user_dist() {
#[test]
fn rust_optimize() {
- assert_eq!(parse("").rust_optimize.is_release(), true);
- assert_eq!(parse("rust.optimize = false").rust_optimize.is_release(), false);
- assert_eq!(parse("rust.optimize = true").rust_optimize.is_release(), true);
- assert_eq!(parse("rust.optimize = 0").rust_optimize.is_release(), false);
- assert_eq!(parse("rust.optimize = 1").rust_optimize.is_release(), true);
+ assert!(parse("").rust_optimize.is_release());
+ assert!(!parse("rust.optimize = false").rust_optimize.is_release());
+ assert!(parse("rust.optimize = true").rust_optimize.is_release());
+ assert!(!parse("rust.optimize = 0").rust_optimize.is_release());
+ assert!(parse("rust.optimize = 1").rust_optimize.is_release());
+ assert!(parse("rust.optimize = \"s\"").rust_optimize.is_release());
assert_eq!(parse("rust.optimize = 1").rust_optimize.get_opt_level(), Some("1".to_string()));
- assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.is_release(), true);
assert_eq!(parse("rust.optimize = \"s\"").rust_optimize.get_opt_level(), Some("s".to_string()));
}
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 15e8c1eb9..f469dbea6 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -58,6 +58,7 @@ o("clang", "llvm.clang", "build clang")
o("missing-tools", "dist.missing-tools", "allow failures when building tools")
o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++")
o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard")
+o("patch-binaries-for-nix", "build.patch-binaries-for-nix", "whether patch binaries for usage with Nix toolchains")
v("llvm-cflags", "llvm.cflags", "build LLVM with these extra compiler flags")
v("llvm-cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags")
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index a4135b06e..8e9614ec8 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -91,8 +91,8 @@ impl Config {
// NOTE: this intentionally comes after the Linux check:
// - patchelf only works with ELF files, so no need to run it on Mac or Windows
// - On other Unix systems, there is no stable syscall interface, so Nix doesn't manage the global libc.
- if self.patch_binaries_for_nix {
- return true;
+ if let Some(explicit_value) = self.patch_binaries_for_nix {
+ return explicit_value;
}
// Use `/etc/os-release` instead of `/etc/NIXOS`.
@@ -105,7 +105,16 @@ impl Config {
matches!(l.trim(), "ID=nixos" | "ID='nixos'" | "ID=\"nixos\"")
}),
};
- is_nixos && !Path::new("/lib").exists()
+ if !is_nixos {
+ let in_nix_shell = env::var("IN_NIX_SHELL");
+ if let Ok(in_nix_shell) = in_nix_shell {
+ eprintln!(
+ "The IN_NIX_SHELL environment variable is `{in_nix_shell}`; \
+ you may need to set `patch-binaries-for-nix=true` in config.toml"
+ );
+ }
+ }
+ is_nixos
});
if val {
eprintln!("info: You seem to be using Nix.");
@@ -216,6 +225,8 @@ impl Config {
"10", // timeout if speed is < 10 bytes/sec for > 30 seconds
"--connect-timeout",
"30", // timeout if cannot connect within 30 seconds
+ "-o",
+ tempfile.to_str().unwrap(),
"--retry",
"3",
"-SRf",
@@ -227,8 +238,6 @@ impl Config {
curl.arg("--progress-bar");
}
curl.arg(url);
- let f = File::create(tempfile).unwrap();
- curl.stdout(Stdio::from(f));
if !self.check_run(&mut curl) {
if self.build.contains("windows-msvc") {
eprintln!("Fallback to PowerShell");
@@ -432,7 +441,7 @@ impl Config {
}
pub(crate) fn download_beta_toolchain(&self) {
- self.verbose(&format!("downloading stage0 beta artifacts"));
+ self.verbose("downloading stage0 beta artifacts");
let date = &self.stage0_metadata.compiler.date;
let version = &self.stage0_metadata.compiler.version;
diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs
index d658be0b8..11f2762f7 100644
--- a/src/bootstrap/format.rs
+++ b/src/bootstrap/format.rs
@@ -127,8 +127,6 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
Err(_) => false,
};
- let mut paths = paths.to_vec();
-
if git_available {
let in_working_tree = match build
.config
@@ -201,8 +199,6 @@ pub fn format(build: &Builder<'_>, check: bool, paths: &[PathBuf]) {
"WARN: Something went wrong when running git commands:\n{err}\n\
Falling back to formatting all files."
);
- // Something went wrong when getting the version. Just format all the files.
- paths.push(".".into());
}
}
}
diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs
index b62aa9992..500b20b86 100644
--- a/src/bootstrap/install.rs
+++ b/src/bootstrap/install.rs
@@ -45,6 +45,23 @@ fn sanitize_sh(path: &Path) -> String {
}
}
+fn is_dir_writable_for_user(dir: &PathBuf) -> bool {
+ let tmp = dir.join(".tmp");
+ match fs::create_dir_all(&tmp) {
+ Ok(_) => {
+ fs::remove_dir_all(tmp).unwrap();
+ true
+ }
+ Err(e) => {
+ if e.kind() == std::io::ErrorKind::PermissionDenied {
+ false
+ } else {
+ panic!("Failed the write access check for the current user. {}", e);
+ }
+ }
+ }
+}
+
fn install_sh(
builder: &Builder<'_>,
package: &str,
@@ -56,6 +73,28 @@ fn install_sh(
let prefix = default_path(&builder.config.prefix, "/usr/local");
let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
+ let destdir_env = env::var_os("DESTDIR").map(PathBuf::from);
+
+ // Sanity checks on the write access of user.
+ //
+ // When the `DESTDIR` environment variable is present, there is no point to
+ // check write access for `prefix` and `sysconfdir` individually, as they
+ // are combined with the path from the `DESTDIR` environment variable. In
+ // this case, we only need to check the `DESTDIR` path, disregarding the
+ // `prefix` and `sysconfdir` paths.
+ if let Some(destdir) = &destdir_env {
+ assert!(is_dir_writable_for_user(destdir), "User doesn't have write access on DESTDIR.");
+ } else {
+ assert!(
+ is_dir_writable_for_user(&prefix),
+ "User doesn't have write access on `install.prefix` path in the `config.toml`.",
+ );
+ assert!(
+ is_dir_writable_for_user(&sysconfdir),
+ "User doesn't have write access on `install.sysconfdir` path in `config.toml`."
+ );
+ }
+
let datadir = prefix.join(default_path(&builder.config.datadir, "share"));
let docdir = prefix.join(default_path(&builder.config.docdir, "share/doc/rust"));
let mandir = prefix.join(default_path(&builder.config.mandir, "share/man"));
@@ -68,13 +107,13 @@ fn install_sh(
let mut cmd = Command::new(SHELL);
cmd.current_dir(&empty_dir)
.arg(sanitize_sh(&tarball.decompressed_output().join("install.sh")))
- .arg(format!("--prefix={}", prepare_dir(prefix)))
- .arg(format!("--sysconfdir={}", prepare_dir(sysconfdir)))
- .arg(format!("--datadir={}", prepare_dir(datadir)))
- .arg(format!("--docdir={}", prepare_dir(docdir)))
- .arg(format!("--bindir={}", prepare_dir(bindir)))
- .arg(format!("--libdir={}", prepare_dir(libdir)))
- .arg(format!("--mandir={}", prepare_dir(mandir)))
+ .arg(format!("--prefix={}", prepare_dir(&destdir_env, prefix)))
+ .arg(format!("--sysconfdir={}", prepare_dir(&destdir_env, sysconfdir)))
+ .arg(format!("--datadir={}", prepare_dir(&destdir_env, datadir)))
+ .arg(format!("--docdir={}", prepare_dir(&destdir_env, docdir)))
+ .arg(format!("--bindir={}", prepare_dir(&destdir_env, bindir)))
+ .arg(format!("--libdir={}", prepare_dir(&destdir_env, libdir)))
+ .arg(format!("--mandir={}", prepare_dir(&destdir_env, mandir)))
.arg("--disable-ldconfig");
builder.run(&mut cmd);
t!(fs::remove_dir_all(&empty_dir));
@@ -84,16 +123,16 @@ fn default_path(config: &Option<PathBuf>, default: &str) -> PathBuf {
config.as_ref().cloned().unwrap_or_else(|| PathBuf::from(default))
}
-fn prepare_dir(mut path: PathBuf) -> String {
+fn prepare_dir(destdir_env: &Option<PathBuf>, mut path: PathBuf) -> String {
// The DESTDIR environment variable is a standard way to install software in a subdirectory
// while keeping the original directory structure, even if the prefix or other directories
// contain absolute paths.
//
// More information on the environment variable is available here:
// https://www.gnu.org/prep/standards/html_node/DESTDIR.html
- if let Some(destdir) = env::var_os("DESTDIR").map(PathBuf::from) {
+ if let Some(destdir) = destdir_env {
let without_destdir = path.clone();
- path = destdir;
+ path = destdir.clone();
// Custom .join() which ignores disk roots.
for part in without_destdir.components() {
if let Component::Normal(s) = part {
diff --git a/src/bootstrap/job.rs b/src/bootstrap/job.rs
index 4fb00f65d..b0a97b540 100644
--- a/src/bootstrap/job.rs
+++ b/src/bootstrap/job.rs
@@ -134,7 +134,7 @@ pub unsafe fn setup(build: &mut Build) {
// If this failed, well at least we tried! An example of DuplicateHandle
// failing in the past has been when the wrong python2 package spawned this
// build system (e.g., the `python2` package in MSYS instead of
- // `mingw-w64-x86_64-python2`. Not sure why it failed, but the "failure
+ // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure
// mode" here is that we only clean everything up when the build system
// dies, not when the python parent does, so not too bad.
if r.is_err() {
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 4396bbc51..8b8d4b237 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -116,7 +116,7 @@ pub const VERSION: usize = 2;
/// Extra --check-cfg to add when building
/// (Mode restriction, config name, config values (if any))
-const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)] = &[
+const EXTRA_CHECK_CFGS: &[(Option<Mode>, &str, Option<&[&'static str]>)] = &[
(None, "bootstrap", None),
(Some(Mode::Rustc), "parallel_compiler", None),
(Some(Mode::ToolRustc), "parallel_compiler", None),
@@ -133,7 +133,9 @@ const EXTRA_CHECK_CFGS: &[(Option<Mode>, &'static str, Option<&[&'static str]>)]
// #[cfg(bootstrap)]
(Some(Mode::Std), "target_vendor", Some(&["unikraft"])),
(Some(Mode::Std), "target_env", Some(&["libnx"])),
- (Some(Mode::Std), "target_os", Some(&["teeos"])),
+ // #[cfg(bootstrap)] hurd
+ (Some(Mode::Std), "target_os", Some(&["teeos", "hurd"])),
+ (Some(Mode::Rustc), "target_os", Some(&["hurd"])),
// #[cfg(bootstrap)] mips32r6, mips64r6
(
Some(Mode::Std),
@@ -1019,7 +1021,7 @@ impl Build {
fn info(&self, msg: &str) {
match self.config.dry_run {
- DryRun::SelfCheck => return,
+ DryRun::SelfCheck => (),
DryRun::Disabled | DryRun::UserSelected => {
println!("{msg}");
}
@@ -1757,10 +1759,11 @@ to download LLVM rather than building it.
//
// In these cases we automatically enable Ninja if we find it in the
// environment.
- if !self.config.ninja_in_file && self.config.build.contains("msvc") {
- if cmd_finder.maybe_have("ninja").is_some() {
- return true;
- }
+ if !self.config.ninja_in_file
+ && self.config.build.contains("msvc")
+ && cmd_finder.maybe_have("ninja").is_some()
+ {
+ return true;
}
self.config.ninja_in_file
diff --git a/src/bootstrap/llvm.rs b/src/bootstrap/llvm.rs
index c841cb340..455683158 100644
--- a/src/bootstrap/llvm.rs
+++ b/src/bootstrap/llvm.rs
@@ -24,6 +24,7 @@ use crate::util::{self, exe, output, t, up_to_date};
use crate::{CLang, GitRepo, Kind};
use build_helper::ci::CiEnv;
+use build_helper::git::get_git_merge_base;
#[derive(Clone)]
pub struct LlvmResult {
@@ -128,13 +129,19 @@ pub fn prebuilt_llvm_config(
/// This retrieves the LLVM sha we *want* to use, according to git history.
pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String {
let llvm_sha = if is_git {
+ // We proceed in 2 steps. First we get the closest commit that is actually upstream. Then we
+ // walk back further to the last bors merge commit that actually changed LLVM. The first
+ // step will fail on CI because only the `auto` branch exists; we just fall back to `HEAD`
+ // in that case.
+ let closest_upstream =
+ get_git_merge_base(Some(&config.src)).unwrap_or_else(|_| "HEAD".into());
let mut rev_list = config.git();
rev_list.args(&[
PathBuf::from("rev-list"),
format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(),
"-n1".into(),
"--first-parent".into(),
- "HEAD".into(),
+ closest_upstream.into(),
"--".into(),
config.src.join("src/llvm-project"),
config.src.join("src/bootstrap/download-ci-llvm-stamp"),
@@ -148,7 +155,7 @@ pub(crate) fn detect_llvm_sha(config: &Config, is_git: bool) -> String {
"".to_owned()
};
- if &llvm_sha == "" {
+ if llvm_sha.is_empty() {
eprintln!("error: could not find commit hash for downloading LLVM");
eprintln!("help: maybe your repository history is too shallow?");
eprintln!("help: consider disabling `download-ci-llvm`");
@@ -201,10 +208,10 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
("x86_64-unknown-netbsd", false),
];
- if !supported_platforms.contains(&(&*config.build.triple, asserts)) {
- if asserts == true || !supported_platforms.contains(&(&*config.build.triple, true)) {
- return false;
- }
+ if !supported_platforms.contains(&(&*config.build.triple, asserts))
+ && (asserts || !supported_platforms.contains(&(&*config.build.triple, true)))
+ {
+ return false;
}
if is_ci_llvm_modified(config) {
@@ -490,11 +497,11 @@ impl Step for Llvm {
let mut cmd = Command::new(&res.llvm_config);
let version = output(cmd.arg("--version"));
let major = version.split('.').next().unwrap();
- let lib_name = match &llvm_version_suffix {
+
+ match &llvm_version_suffix {
Some(version_suffix) => format!("libLLVM-{major}{version_suffix}.{extension}"),
None => format!("libLLVM-{major}.{extension}"),
- };
- lib_name
+ }
};
// When building LLVM with LLVM_LINK_LLVM_DYLIB for macOS, an unversioned
@@ -591,9 +598,9 @@ fn configure_cmake(
} else if target.contains("linux") {
cfg.define("CMAKE_SYSTEM_NAME", "Linux");
} else {
- builder.info(
+ builder.info(&format!(
"could not determine CMAKE_SYSTEM_NAME from the target `{target}`, build may fail",
- );
+ ));
}
// When cross-compiling we should also set CMAKE_SYSTEM_VERSION, but in
@@ -696,14 +703,7 @@ fn configure_cmake(
cflags.push(" ");
cflags.push(s);
}
- // Some compiler features used by LLVM (such as thread locals) will not work on a min version below iOS 10.
- if target.contains("apple-ios") {
- if target.contains("86-") {
- cflags.push(" -miphonesimulator-version-min=10.0");
- } else {
- cflags.push(" -miphoneos-version-min=10.0");
- }
- }
+
if builder.config.llvm_clang_cl.is_some() {
cflags.push(&format!(" --target={target}"));
}
@@ -749,13 +749,15 @@ fn configure_cmake(
// For distribution we want the LLVM tools to be *statically* linked to libstdc++.
// We also do this if the user explicitly requested static libstdc++.
- if builder.config.llvm_static_stdcpp {
- if !target.contains("msvc") && !target.contains("netbsd") && !target.contains("solaris") {
- if target.contains("apple") || target.contains("windows") {
- ldflags.push_all("-static-libstdc++");
- } else {
- ldflags.push_all("-Wl,-Bsymbolic -static-libstdc++");
- }
+ if builder.config.llvm_static_stdcpp
+ && !target.contains("msvc")
+ && !target.contains("netbsd")
+ && !target.contains("solaris")
+ {
+ if target.contains("apple") || target.contains("windows") {
+ ldflags.push_all("-static-libstdc++");
+ } else {
+ ldflags.push_all("-Wl,-Bsymbolic -static-libstdc++");
}
}
@@ -1054,6 +1056,7 @@ fn supported_sanitizers(
"aarch64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
"aarch64-apple-ios" => darwin_libs("ios", &["asan", "tsan"]),
"aarch64-apple-ios-sim" => darwin_libs("iossim", &["asan", "tsan"]),
+ "aarch64-apple-ios-macabi" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
"aarch64-unknown-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]),
"aarch64-unknown-linux-gnu" => {
common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"])
@@ -1064,6 +1067,7 @@ fn supported_sanitizers(
"x86_64-apple-darwin" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
"x86_64-unknown-fuchsia" => common_libs("fuchsia", "x86_64", &["asan"]),
"x86_64-apple-ios" => darwin_libs("iossim", &["asan", "tsan"]),
+ "x86_64-apple-ios-macabi" => darwin_libs("osx", &["asan", "lsan", "tsan"]),
"x86_64-unknown-freebsd" => common_libs("freebsd", "x86_64", &["asan", "msan", "tsan"]),
"x86_64-unknown-netbsd" => {
common_libs("netbsd", "x86_64", &["asan", "lsan", "msan", "tsan"])
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index a9865e262..0b6707991 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -6,6 +6,13 @@ Q := @
BOOTSTRAP_ARGS :=
endif
+# Pass `-jN` to the bootstrap if it is specified.
+ifdef MAKEFLAGS
+ ifneq (,$(findstring -j, $(MAKEFLAGS)))
+ BOOTSTRAP_ARGS += $(filter -j%, $(MAKEFLAGS))
+ endif
+endif
+
BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py
all:
diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs
index 7e83b508e..0febdf250 100644
--- a/src/bootstrap/sanity.rs
+++ b/src/bootstrap/sanity.rs
@@ -62,6 +62,9 @@ impl Finder {
}
pub fn check(build: &mut Build) {
+ let skip_target_sanity =
+ env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some_and(|s| s == "1" || s == "true");
+
let path = env::var_os("PATH").unwrap_or_default();
// On Windows, quotes are invalid characters for filename paths, and if
// one is present as part of the PATH then that can lead to the system
@@ -92,20 +95,19 @@ pub fn check(build: &mut Build) {
.unwrap_or(true)
})
.any(|build_llvm_ourselves| build_llvm_ourselves);
+
let need_cmake = building_llvm || build.config.any_sanitizers_enabled();
- if need_cmake {
- if cmd_finder.maybe_have("cmake").is_none() {
- eprintln!(
- "
+ if need_cmake && cmd_finder.maybe_have("cmake").is_none() {
+ eprintln!(
+ "
Couldn't find required command: cmake
You should install cmake, or set `download-ci-llvm = true` in the
`[llvm]` section of `config.toml` to download LLVM rather
than building it.
"
- );
- crate::exit!(1);
- }
+ );
+ crate::exit!(1);
}
build.config.python = build
@@ -166,7 +168,7 @@ than building it.
// FIXME: it would be better to refactor this code to split necessary setup from pure sanity
// checks, and have a regular flag for skipping the latter. Also see
// <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>.
- if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() {
+ if skip_target_sanity {
continue;
}
@@ -199,13 +201,21 @@ than building it.
.entry(*target)
.or_insert_with(|| Target::from_triple(&target.triple));
- if target.contains("-none-") || target.contains("nvptx") {
- if build.no_std(*target) == Some(false) {
- panic!("All the *-none-* and nvptx* targets are no-std targets")
- }
+ if (target.contains("-none-") || target.contains("nvptx"))
+ && build.no_std(*target) == Some(false)
+ {
+ panic!("All the *-none-* and nvptx* targets are no-std targets")
+ }
+
+ // Some environments don't want or need these tools, such as when testing Miri.
+ // FIXME: it would be better to refactor this code to split necessary setup from pure sanity
+ // checks, and have a regular flag for skipping the latter. Also see
+ // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>.
+ if skip_target_sanity {
+ continue;
}
- // Make sure musl-root is valid
+ // Make sure musl-root is valid.
if target.contains("musl") && !target.contains("unikraft") {
// If this is a native target (host is also musl) and no musl-root is given,
// fall back to the system toolchain in /usr before giving up
@@ -227,14 +237,6 @@ than building it.
}
}
- // Some environments don't want or need these tools, such as when testing Miri.
- // FIXME: it would be better to refactor this code to split necessary setup from pure sanity
- // checks, and have a regular flag for skipping the latter. Also see
- // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>.
- if env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some() {
- continue;
- }
-
if need_cmake && target.contains("msvc") {
// There are three builds of cmake on windows: MSVC, MinGW, and
// Cygwin. The Cygwin build does not have generators for Visual
diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs
index 30730f504..ef0234957 100644
--- a/src/bootstrap/setup.rs
+++ b/src/bootstrap/setup.rs
@@ -33,6 +33,7 @@ static SETTINGS_HASHES: &[&str] = &[
"af1b5efe196aed007577899db9dae15d6dbc923d6fa42fa0934e68617ba9bbe0",
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
+ "b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
];
static RUST_ANALYZER_SETTINGS: &str = include_str!("../etc/rust_analyzer_settings.json");
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index d0d62db08..ba030f0f5 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -630,6 +630,10 @@ impl Step for Miri {
cargo.env("MIRI_SYSROOT", &miri_sysroot);
cargo.env("MIRI_HOST_SYSROOT", sysroot);
cargo.env("MIRI", &miri);
+ if builder.config.locked_deps {
+ // enforce lockfiles
+ cargo.env("CARGO_EXTRA_FLAGS", "--locked");
+ }
// Set the target.
cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
@@ -675,6 +679,9 @@ impl Step for Miri {
);
cargo.add_rustc_lib_path(builder, compiler);
cargo.arg("--").arg("miri").arg("test");
+ if builder.config.locked_deps {
+ cargo.arg("--locked");
+ }
cargo
.arg("--manifest-path")
.arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml"));
@@ -839,7 +846,7 @@ impl Step for RustdocTheme {
let rustdoc = builder.bootstrap_out.join("rustdoc");
let mut cmd = builder.tool_cmd(Tool::RustdocTheme);
cmd.arg(rustdoc.to_str().unwrap())
- .arg(builder.src.join("src/librustdoc/html/static/css/themes").to_str().unwrap())
+ .arg(builder.src.join("src/librustdoc/html/static/css/rustdoc.css").to_str().unwrap())
.env("RUSTC_STAGE", self.compiler.stage.to_string())
.env("RUSTC_SYSROOT", builder.sysroot(self.compiler))
.env("RUSTDOC_LIBDIR", builder.sysroot_libdir(self.compiler, self.compiler.host))
@@ -1132,16 +1139,14 @@ help: to skip test's attempt to check tidiness, pass `--skip src/tools/tidy` to
.map(|filename| builder.src.join("src/etc/completions").join(filename));
if builder.config.cmd.bless() {
builder.ensure(crate::run::GenerateCompletions);
- } else {
- if crate::flags::get_completion(shells::Bash, &bash).is_some()
- || crate::flags::get_completion(shells::Fish, &fish).is_some()
- || crate::flags::get_completion(shells::PowerShell, &powershell).is_some()
- {
- eprintln!(
- "x.py completions were changed; run `x.py run generate-completions` to update them"
- );
- crate::exit!(1);
- }
+ } else if crate::flags::get_completion(shells::Bash, &bash).is_some()
+ || crate::flags::get_completion(shells::Fish, &fish).is_some()
+ || crate::flags::get_completion(shells::PowerShell, &powershell).is_some()
+ {
+ eprintln!(
+ "x.py completions were changed; run `x.py run generate-completions` to update them"
+ );
+ crate::exit!(1);
}
}
@@ -1167,6 +1172,11 @@ impl Step for ExpandYamlAnchors {
/// appropriate configuration for all our CI providers. This step ensures the tool was called
/// by the user before committing CI changes.
fn run(self, builder: &Builder<'_>) {
+ // Note: `.github/` is not included in dist-src tarballs
+ if !builder.src.join(".github/workflows/ci.yml").exists() {
+ builder.info("Skipping YAML anchors check: GitHub Actions config not found");
+ return;
+ }
builder.info("Ensuring the YAML anchors in the GitHub Actions config were expanded");
builder.run_delaying_failure(
&mut builder.tool_cmd(Tool::ExpandYamlAnchors).arg("check").arg(&builder.src),
@@ -1328,6 +1338,12 @@ host_test!(RunMakeFullDeps {
default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" });
+default_test!(CoverageMap {
+ path: "tests/coverage-map",
+ mode: "coverage-map",
+ suite: "coverage-map"
+});
+
host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" });
host_test!(RunCoverageRustdoc {
path: "tests/run-coverage-rustdoc",
@@ -1360,7 +1376,7 @@ impl Step for MirOpt {
let run = |target| {
builder.ensure(Compiletest {
compiler: self.compiler,
- target: target,
+ target,
mode: "mir-opt",
suite: "mir-opt",
path: "tests/mir-opt",
@@ -1533,6 +1549,14 @@ note: if you're sure you want to do this, please open an issue as to why. In the
.arg(builder.ensure(tool::JsonDocLint { compiler: json_compiler, target }));
}
+ if mode == "coverage-map" {
+ let coverage_dump = builder.ensure(tool::CoverageDump {
+ compiler: compiler.with_stage(0),
+ target: compiler.host,
+ });
+ cmd.arg("--coverage-dump-path").arg(coverage_dump);
+ }
+
if mode == "run-make" || mode == "run-coverage" {
let rust_demangler = builder
.ensure(tool::RustDemangler {
@@ -2941,3 +2965,129 @@ impl Step for TestHelpers {
.compile("rust_test_helpers");
}
}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct CodegenCranelift {
+ compiler: Compiler,
+ target: TargetSelection,
+}
+
+impl Step for CodegenCranelift {
+ type Output = ();
+ const DEFAULT: bool = true;
+ const ONLY_HOSTS: bool = true;
+
+ fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+ run.paths(&["compiler/rustc_codegen_cranelift"])
+ }
+
+ fn make_run(run: RunConfig<'_>) {
+ let builder = run.builder;
+ let host = run.build_triple();
+ let compiler = run.builder.compiler_for(run.builder.top_stage, host, host);
+
+ if builder.doc_tests == DocTests::Only {
+ return;
+ }
+
+ let triple = run.target.triple;
+ let target_supported = if triple.contains("linux") {
+ triple.contains("x86_64") || triple.contains("aarch64") || triple.contains("s390x")
+ } else if triple.contains("darwin") || triple.contains("windows") {
+ triple.contains("x86_64")
+ } else {
+ false
+ };
+ if !target_supported {
+ builder.info("target not supported by rustc_codegen_cranelift. skipping");
+ return;
+ }
+
+ if builder.remote_tested(run.target) {
+ builder.info("remote testing is not supported by rustc_codegen_cranelift. skipping");
+ return;
+ }
+
+ if !builder.config.rust_codegen_backends.contains(&INTERNER.intern_str("cranelift")) {
+ builder.info("cranelift not in rust.codegen-backends. skipping");
+ return;
+ }
+
+ builder.ensure(CodegenCranelift { compiler, target: run.target });
+ }
+
+ fn run(self, builder: &Builder<'_>) {
+ let compiler = self.compiler;
+ let target = self.target;
+
+ builder.ensure(compile::Std::new(compiler, target));
+
+ // If we're not doing a full bootstrap but we're testing a stage2
+ // version of libstd, then what we're actually testing is the libstd
+ // produced in stage1. Reflect that here by updating the compiler that
+ // we're working with automatically.
+ let compiler = builder.compiler_for(compiler.stage, compiler.host, target);
+
+ let build_cargo = || {
+ let mut cargo = builder.cargo(
+ compiler,
+ Mode::Codegen, // Must be codegen to ensure dlopen on compiled dylibs works
+ SourceType::InTree,
+ target,
+ "run",
+ );
+ cargo.current_dir(&builder.src.join("compiler/rustc_codegen_cranelift"));
+ cargo
+ .arg("--manifest-path")
+ .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
+ compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
+
+ // Avoid incremental cache issues when changing rustc
+ cargo.env("CARGO_BUILD_INCREMENTAL", "false");
+
+ cargo
+ };
+
+ builder.info(&format!(
+ "{} cranelift stage{} ({} -> {})",
+ Kind::Test.description(),
+ compiler.stage,
+ &compiler.host,
+ target
+ ));
+ let _time = util::timeit(&builder);
+
+ // FIXME handle vendoring for source tarballs before removing the --skip-test below
+ let download_dir = builder.out.join("cg_clif_download");
+
+ /*
+ let mut prepare_cargo = build_cargo();
+ prepare_cargo.arg("--").arg("prepare").arg("--download-dir").arg(&download_dir);
+ #[allow(deprecated)]
+ builder.config.try_run(&mut prepare_cargo.into()).unwrap();
+ */
+
+ let mut cargo = build_cargo();
+ cargo
+ .arg("--")
+ .arg("test")
+ .arg("--download-dir")
+ .arg(&download_dir)
+ .arg("--out-dir")
+ .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_clif"))
+ .arg("--no-unstable-features")
+ .arg("--use-backend")
+ .arg("cranelift")
+ // Avoid having to vendor the standard library dependencies
+ .arg("--sysroot")
+ .arg("llvm")
+ // These tests depend on crates that are not yet vendored
+ // FIXME remove once vendoring is handled
+ .arg("--skip-test")
+ .arg("testsuite.extended_sysroot");
+ cargo.args(builder.config.test_args());
+
+ #[allow(deprecated)]
+ builder.config.try_run(&mut cargo.into()).unwrap();
+ }
+}
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index e6d27757a..f094dd9d7 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -306,6 +306,7 @@ bootstrap_tool!(
GenerateWindowsSys, "src/tools/generate-windows-sys", "generate-windows-sys";
RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = "test";
OptimizedDist, "src/tools/opt-dist", "opt-dist";
+ CoverageDump, "src/tools/coverage-dump", "coverage-dump";
);
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
@@ -601,7 +602,7 @@ pub struct RustAnalyzer {
}
impl RustAnalyzer {
- pub const ALLOW_FEATURES: &str =
+ pub const ALLOW_FEATURES: &'static str =
"proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink";
}