diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:11:28 +0000 |
commit | 94a0819fe3a0d679c3042a77bfe6a2afc505daea (patch) | |
tree | 2b827afe6a05f3538db3f7803a88c4587fe85648 /src/bootstrap/config.rs | |
parent | Adding upstream version 1.64.0+dfsg1. (diff) | |
download | rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.tar.xz rustc-94a0819fe3a0d679c3042a77bfe6a2afc505daea.zip |
Adding upstream version 1.66.0+dfsg1.upstream/1.66.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/bootstrap/config.rs')
-rw-r--r-- | src/bootstrap/config.rs | 189 |
1 files changed, 138 insertions, 51 deletions
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 4325a237c..a8c403675 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -73,6 +73,8 @@ pub struct Config { pub color: Color, pub patch_binaries_for_nix: bool, pub stage0_metadata: Stage0Metadata, + /// Whether to use the `c` feature of the `compiler_builtins` crate. + pub optimized_compiler_builtins: bool, pub on_fail: Option<String>, pub stage: u32, @@ -156,9 +158,12 @@ pub struct Config { pub rust_new_symbol_mangling: Option<bool>, pub rust_profile_use: Option<String>, pub rust_profile_generate: Option<String>, + pub rust_lto: RustcLto, pub llvm_profile_use: Option<String>, pub llvm_profile_generate: bool, pub llvm_libunwind_default: Option<LlvmLibunwind>, + pub llvm_bolt_profile_generate: bool, + pub llvm_bolt_profile_use: Option<String>, pub build: TargetSelection, pub hosts: Vec<TargetSelection>, @@ -315,6 +320,28 @@ impl SplitDebuginfo { } } +/// LTO mode used for compiling rustc itself. +#[derive(Default, Clone)] +pub enum RustcLto { + #[default] + ThinLocal, + Thin, + Fat, +} + +impl std::str::FromStr for RustcLto { + type Err = String; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "thin-local" => Ok(RustcLto::ThinLocal), + "thin" => Ok(RustcLto::Thin), + "fat" => Ok(RustcLto::Fat), + _ => Err(format!("Invalid value for rustc LTO: {}", s)), + } + } +} + #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct TargetSelection { pub triple: Interned<String>, @@ -388,6 +415,7 @@ impl PartialEq<&str> for TargetSelection { pub struct Target { /// Some(path to llvm-config) if using an external LLVM. pub llvm_config: Option<PathBuf>, + pub llvm_has_rust_patches: Option<bool>, /// Some(path to FileCheck) if one was specified. pub llvm_filecheck: Option<PathBuf>, pub llvm_libunwind: Option<LlvmLibunwind>, @@ -596,6 +624,7 @@ define_config! { bench_stage: Option<u32> = "bench-stage", patch_binaries_for_nix: Option<bool> = "patch-binaries-for-nix", metrics: Option<bool> = "metrics", + optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins", } } @@ -720,6 +749,7 @@ define_config! { profile_use: Option<String> = "profile-use", // ignored; this is set from an env var set by bootstrap.py download_rustc: Option<StringOrBool> = "download-rustc", + lto: Option<String> = "lto", } } @@ -733,6 +763,7 @@ define_config! { default_linker: Option<PathBuf> = "default-linker", linker: Option<String> = "linker", llvm_config: Option<String> = "llvm-config", + llvm_has_rust_patches: Option<bool> = "llvm-has-rust-patches", llvm_filecheck: Option<String> = "llvm-filecheck", llvm_libunwind: Option<String> = "llvm-libunwind", android_ndk: Option<String> = "android-ndk", @@ -770,21 +801,20 @@ impl Config { // set by build.rs config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE")); + let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); // Undo `src/bootstrap` config.src = manifest_dir.parent().unwrap().parent().unwrap().to_owned(); config.out = PathBuf::from("build"); - config.initial_cargo = PathBuf::from(env!("CARGO")); - config.initial_rustc = PathBuf::from(env!("RUSTC")); - config } pub fn parse(args: &[String]) -> Config { let flags = Flags::parse(&args); - let mut config = Config::default_opts(); + + // Set flags. config.exclude = flags.exclude.into_iter().map(|path| TaskPath::parse(path)).collect(); config.include_default_paths = flags.include_default_paths; config.rustc_error_format = flags.rustc_error_format; @@ -802,8 +832,68 @@ impl Config { } config.llvm_profile_use = flags.llvm_profile_use; config.llvm_profile_generate = flags.llvm_profile_generate; + config.llvm_bolt_profile_generate = flags.llvm_bolt_profile_generate; + config.llvm_bolt_profile_use = flags.llvm_bolt_profile_use; + + if config.llvm_bolt_profile_generate && config.llvm_bolt_profile_use.is_some() { + eprintln!( + "Cannot use both `llvm_bolt_profile_generate` and `llvm_bolt_profile_use` at the same time" + ); + crate::detail_exit(1); + } + + // Infer the rest of the configuration. + + // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary, + // running on a completely machine from where it was compiled. + let mut cmd = Command::new("git"); + // NOTE: we cannot support running from outside the repository because the only path we have available + // is set at compile time, which can be wrong if bootstrap was downloaded from source. + // We still support running outside the repository if we find we aren't in a git directory. + cmd.arg("rev-parse").arg("--show-toplevel"); + // Discard stderr because we expect this to fail when building from a tarball. + let output = cmd + .stderr(std::process::Stdio::null()) + .output() + .ok() + .and_then(|output| if output.status.success() { Some(output) } else { None }); + if let Some(output) = output { + let git_root = String::from_utf8(output.stdout).unwrap(); + // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes. + let git_root = PathBuf::from(git_root.trim()).canonicalize().unwrap(); + let s = git_root.to_str().unwrap(); + + // Bootstrap is quite bad at handling /? in front of paths + let src = match s.strip_prefix("\\\\?\\") { + Some(p) => PathBuf::from(p), + None => PathBuf::from(git_root), + }; + // If this doesn't have at least `stage0.json`, we guessed wrong. This can happen when, + // for example, the build directory is inside of another unrelated git directory. + // In that case keep the original `CARGO_MANIFEST_DIR` handling. + // + // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside + // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1. + if src.join("src").join("stage0.json").exists() { + config.src = src; + } + } else { + // We're building from a tarball, not git sources. + // We don't support pre-downloaded bootstrap in this case. + } + + if cfg!(test) { + // Use the build directory of the original x.py invocation, so that we can set `initial_rustc` properly. + config.out = Path::new( + &env::var_os("CARGO_TARGET_DIR").expect("cargo test directly is not supported"), + ) + .parent() + .unwrap() + .to_path_buf(); + } let stage0_json = t!(std::fs::read(&config.src.join("src").join("stage0.json"))); + config.stage0_metadata = t!(serde_json::from_slice::<Stage0Metadata>(&stage0_json)); #[cfg(test)] @@ -859,7 +949,6 @@ impl Config { let build = toml.build.unwrap_or_default(); - set(&mut config.initial_rustc, build.rustc.map(PathBuf::from)); set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from))); // NOTE: Bootstrap spawns various commands with different working directories. // To avoid writing to random places on the file system, `config.out` needs to be an absolute path. @@ -868,6 +957,16 @@ impl Config { config.out = crate::util::absolute(&config.out); } + config.initial_rustc = build + .rustc + .map(PathBuf::from) + .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/rustc")); + config.initial_cargo = build + .cargo + .map(PathBuf::from) + .unwrap_or_else(|| config.out.join(config.build.triple).join("stage0/bin/cargo")); + + // NOTE: it's important this comes *after* we set `initial_rustc` just above. if config.dry_run { let dir = config.out.join("tmp-dry-run"); t!(fs::create_dir_all(&dir)); @@ -914,6 +1013,7 @@ impl Config { 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); + set(&mut config.optimized_compiler_builtins, build.optimized_compiler_builtins); config.verbose = cmp::max(config.verbose, flags.verbose); @@ -990,42 +1090,7 @@ impl Config { config.llvm_from_ci = match llvm.download_ci_llvm { Some(StringOrBool::String(s)) => { assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s); - // This is currently all tier 1 targets and tier 2 targets with host tools - // (since others may not have CI artifacts) - // https://doc.rust-lang.org/rustc/platform-support.html#tier-1 - // FIXME: this is duplicated in bootstrap.py - let supported_platforms = [ - // tier 1 - "aarch64-unknown-linux-gnu", - "i686-pc-windows-gnu", - "i686-pc-windows-msvc", - "i686-unknown-linux-gnu", - "x86_64-unknown-linux-gnu", - "x86_64-apple-darwin", - "x86_64-pc-windows-gnu", - "x86_64-pc-windows-msvc", - // tier 2 with host tools - "aarch64-apple-darwin", - "aarch64-pc-windows-msvc", - "aarch64-unknown-linux-musl", - "arm-unknown-linux-gnueabi", - "arm-unknown-linux-gnueabihf", - "armv7-unknown-linux-gnueabihf", - "mips-unknown-linux-gnu", - "mips64-unknown-linux-gnuabi64", - "mips64el-unknown-linux-gnuabi64", - "mipsel-unknown-linux-gnu", - "powerpc-unknown-linux-gnu", - "powerpc64-unknown-linux-gnu", - "powerpc64le-unknown-linux-gnu", - "riscv64gc-unknown-linux-gnu", - "s390x-unknown-linux-gnu", - "x86_64-unknown-freebsd", - "x86_64-unknown-illumos", - "x86_64-unknown-linux-musl", - "x86_64-unknown-netbsd", - ]; - supported_platforms.contains(&&*config.build.triple) + crate::native::is_ci_llvm_available(&config, llvm_assertions.unwrap_or(false)) } Some(StringOrBool::Bool(b)) => b, None => false, @@ -1132,6 +1197,12 @@ impl Config { config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use); config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate); config.download_rustc_commit = download_ci_rustc_commit(&config, rust.download_rustc); + + config.rust_lto = rust + .lto + .as_deref() + .map(|value| RustcLto::from_str(value).unwrap()) + .unwrap_or_default(); } else { config.rust_profile_use = flags.rust_profile_use; config.rust_profile_generate = flags.rust_profile_generate; @@ -1144,6 +1215,7 @@ impl Config { if let Some(ref s) = cfg.llvm_config { target.llvm_config = Some(config.src.join(s)); } + target.llvm_has_rust_patches = cfg.llvm_has_rust_patches; if let Some(ref s) = cfg.llvm_filecheck { target.llvm_filecheck = Some(config.src.join(s)); } @@ -1176,6 +1248,7 @@ impl Config { if config.llvm_from_ci { let triple = &config.build.triple; + let ci_llvm_bin = config.ci_llvm_root().join("bin"); let mut build_target = config .target_config .entry(config.build) @@ -1183,7 +1256,6 @@ impl Config { check_ci_llvm!(build_target.llvm_config); check_ci_llvm!(build_target.llvm_filecheck); - let ci_llvm_bin = config.out.join(&*config.build.triple).join("ci-llvm/bin"); build_target.llvm_config = Some(ci_llvm_bin.join(exe("llvm-config", config.build))); build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", config.build))); } @@ -1312,11 +1384,22 @@ impl Config { git } - pub(crate) fn artifact_channel(&self, commit: &str) -> String { - let mut channel = self.git(); - channel.arg("show").arg(format!("{}:src/ci/channel", commit)); - let channel = output(&mut channel); - channel.trim().to_owned() + pub(crate) fn artifact_channel(&self, builder: &Builder<'_>, commit: &str) -> String { + if builder.rust_info.is_managed_git_subrepository() { + let mut channel = self.git(); + channel.arg("show").arg(format!("{}:src/ci/channel", commit)); + let channel = output(&mut channel); + channel.trim().to_owned() + } else if let Ok(channel) = fs::read_to_string(builder.src.join("src/ci/channel")) { + channel.trim().to_owned() + } else { + let src = builder.src.display(); + eprintln!("error: failed to determine artifact channel"); + eprintln!( + "help: either use git or ensure that {src}/src/ci/channel contains the name of the channel to use" + ); + panic!(); + } } /// Try to find the relative path of `bindir`, otherwise return it in full. @@ -1445,11 +1528,15 @@ impl Config { .get(&target) .and_then(|t| t.llvm_libunwind) .or(self.llvm_libunwind_default) - .unwrap_or(LlvmLibunwind::No) + .unwrap_or(if target.contains("fuchsia") { + LlvmLibunwind::InTree + } else { + LlvmLibunwind::No + }) } pub fn submodules(&self, rust_info: &GitInfo) -> bool { - self.submodules.unwrap_or(rust_info.is_git()) + self.submodules.unwrap_or(rust_info.is_managed_git_subrepository()) } } @@ -1461,7 +1548,7 @@ fn set<T>(field: &mut T, val: Option<T>) { fn threads_from_config(v: u32) -> u32 { match v { - 0 => num_cpus::get() as u32, + 0 => std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32, n => n, } } @@ -1554,7 +1641,7 @@ fn maybe_download_rustfmt(builder: &Builder<'_>) -> Option<PathBuf> { fn download_ci_rustc(builder: &Builder<'_>, commit: &str) { builder.verbose(&format!("using downloaded stage2 artifacts from CI (commit {commit})")); - let channel = builder.config.artifact_channel(commit); + let channel = builder.config.artifact_channel(builder, commit); let host = builder.config.build.triple; let bin_root = builder.out.join(host).join("ci-rustc"); let rustc_stamp = bin_root.join(".rustc-stamp"); |