From 8abbbe269ca8a8d3f52db8923edf860be900bf02 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Thu, 2 Jul 2020 17:00:19 -0400 Subject: [PATCH] Teach bootstrap about target files vs target triples `rustc` allows passing in predefined target triples as well as JSON target specification files. This change allows bootstrap to have the first inkling about those differences. This allows building a cross-compiler for an out-of-tree architecture (even though that compiler won't work for other reasons). Even if no one ever uses this functionality, I think the newtype around the `Interned` improves the readability of the code. --- src/bootstrap/builder.rs | 59 +++++++++--------- src/bootstrap/builder/tests.rs | 56 ++++++++--------- src/bootstrap/cc_detect.rs | 34 +++++----- src/bootstrap/check.rs | 18 +++--- src/bootstrap/clean.rs | 2 +- src/bootstrap/compile.rs | 45 +++++++------- src/bootstrap/config.rs | 84 ++++++++++++++++++++++--- src/bootstrap/dist.rs | 79 +++++++++++------------ src/bootstrap/doc.rs | 30 ++++----- src/bootstrap/flags.rs | 11 ++-- src/bootstrap/install.rs | 29 ++++----- src/bootstrap/lib.rs | 110 +++++++++++++++++---------------- src/bootstrap/native.rs | 39 ++++++------ src/bootstrap/sanity.rs | 6 +- src/bootstrap/test.rs | 69 +++++++++++---------- src/bootstrap/tool.rs | 26 ++++---- src/bootstrap/util.rs | 11 ++-- 17 files changed, 391 insertions(+), 317 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 3cbecbbaa06cb..10e8509c9bbdd 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -16,6 +16,7 @@ use build_helper::{output, t}; use crate::cache::{Cache, Interned, INTERNER}; use crate::check; use crate::compile; +use crate::config::TargetSelection; use crate::dist; use crate::doc; use crate::flags::Subcommand; @@ -86,8 +87,8 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash { pub struct RunConfig<'a> { pub builder: &'a Builder<'a>, - pub host: Interned, - pub target: Interned, + pub host: TargetSelection, + pub target: TargetSelection, pub path: PathBuf, } @@ -576,7 +577,7 @@ impl<'a> Builder<'a> { /// not take `Compiler` since all `Compiler` instances are meant to be /// obtained through this function, since it ensures that they are valid /// (i.e., built and assembled). - pub fn compiler(&self, stage: u32, host: Interned) -> Compiler { + pub fn compiler(&self, stage: u32, host: TargetSelection) -> Compiler { self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } }) } @@ -594,8 +595,8 @@ impl<'a> Builder<'a> { pub fn compiler_for( &self, stage: u32, - host: Interned, - target: Interned, + host: TargetSelection, + target: TargetSelection, ) -> Compiler { if self.build.force_use_stage1(Compiler { stage, host }, target) { self.compiler(1, self.config.build) @@ -610,15 +611,11 @@ impl<'a> Builder<'a> { /// Returns the libdir where the standard library and other artifacts are /// found for a compiler's sysroot. - pub fn sysroot_libdir( - &self, - compiler: Compiler, - target: Interned, - ) -> Interned { + pub fn sysroot_libdir(&self, compiler: Compiler, target: TargetSelection) -> Interned { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] struct Libdir { compiler: Compiler, - target: Interned, + target: TargetSelection, } impl Step for Libdir { type Output = Interned; @@ -633,7 +630,7 @@ impl<'a> Builder<'a> { .sysroot(self.compiler) .join(lib) .join("rustlib") - .join(self.target) + .join(self.target.triple) .join("lib"); let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); @@ -656,7 +653,7 @@ impl<'a> Builder<'a> { Some(relative_libdir) if compiler.stage >= 1 => { self.sysroot(compiler).join(relative_libdir) } - _ => self.sysroot(compiler).join(libdir(&compiler.host)), + _ => self.sysroot(compiler).join(libdir(compiler.host)), } } } @@ -668,11 +665,11 @@ impl<'a> Builder<'a> { /// Windows. pub fn libdir_relative(&self, compiler: Compiler) -> &Path { if compiler.is_snapshot(self) { - libdir(&self.config.build).as_ref() + libdir(self.config.build).as_ref() } else { match self.config.libdir_relative() { Some(relative_libdir) if compiler.stage >= 1 => relative_libdir, - _ => libdir(&compiler.host).as_ref(), + _ => libdir(compiler.host).as_ref(), } } } @@ -707,7 +704,7 @@ impl<'a> Builder<'a> { if compiler.is_snapshot(self) { self.initial_rustc.clone() } else { - self.sysroot(compiler).join("bin").join(exe("rustc", &compiler.host)) + self.sysroot(compiler).join("bin").join(exe("rustc", compiler.host)) } } @@ -741,7 +738,7 @@ impl<'a> Builder<'a> { /// /// Note that this returns `None` if LLVM is disabled, or if we're in a /// check build or dry-run, where there's no need to build all of LLVM. - fn llvm_config(&self, target: Interned) -> Option { + fn llvm_config(&self, target: TargetSelection) -> Option { if self.config.llvm_enabled() && self.kind != Kind::Check && !self.config.dry_run { let llvm_config = self.ensure(native::Llvm { target }); if llvm_config.is_file() { @@ -763,7 +760,7 @@ impl<'a> Builder<'a> { compiler: Compiler, mode: Mode, source_type: SourceType, - target: Interned, + target: TargetSelection, cmd: &str, ) -> Cargo { let mut cargo = Command::new(&self.initial_cargo); @@ -794,7 +791,7 @@ impl<'a> Builder<'a> { } if cmd != "install" { - cargo.arg("--target").arg(target); + cargo.arg("--target").arg(target.rustc_target_arg()); } else { assert_eq!(target, compiler.host); } @@ -820,7 +817,7 @@ impl<'a> Builder<'a> { compiler.stage }; - let mut rustflags = Rustflags::new(&target); + let mut rustflags = Rustflags::new(target); if stage != 0 { if let Ok(s) = env::var("CARGOFLAGS_NOT_BOOTSTRAP") { cargo.args(s.split_whitespace()); @@ -993,7 +990,7 @@ impl<'a> Builder<'a> { // argument manually via `-C link-args=-Wl,-rpath,...`. Plus isn't it // fun to pass a flag to a tool to pass a flag to pass a flag to a tool // to change a flag in a binary? - if self.config.rust_rpath && util::use_host_linker(&target) { + if self.config.rust_rpath && util::use_host_linker(target) { let rpath = if target.contains("apple") { // Note that we need to take one extra step on macOS to also pass // `-Wl,-instal_name,@rpath/...` to get things to work right. To @@ -1021,7 +1018,7 @@ impl<'a> Builder<'a> { } if let Some(target_linker) = self.linker(target, can_use_lld) { - let target = crate::envify(&target); + let target = crate::envify(&target.triple); cargo.env(&format!("CARGO_TARGET_{}_LINKER", target), target_linker); } if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc { @@ -1182,21 +1179,23 @@ impl<'a> Builder<'a> { } }; let cc = ccacheify(&self.cc(target)); - cargo.env(format!("CC_{}", target), &cc); + cargo.env(format!("CC_{}", target.triple), &cc); let cflags = self.cflags(target, GitRepo::Rustc).join(" "); - cargo.env(format!("CFLAGS_{}", target), cflags.clone()); + cargo.env(format!("CFLAGS_{}", target.triple), cflags.clone()); if let Some(ar) = self.ar(target) { let ranlib = format!("{} s", ar.display()); - cargo.env(format!("AR_{}", target), ar).env(format!("RANLIB_{}", target), ranlib); + cargo + .env(format!("AR_{}", target.triple), ar) + .env(format!("RANLIB_{}", target.triple), ranlib); } if let Ok(cxx) = self.cxx(target) { let cxx = ccacheify(&cxx); cargo - .env(format!("CXX_{}", target), &cxx) - .env(format!("CXXFLAGS_{}", target), cflags); + .env(format!("CXX_{}", target.triple), &cxx) + .env(format!("CXXFLAGS_{}", target.triple), cflags); } } @@ -1230,7 +1229,7 @@ impl<'a> Builder<'a> { // Environment variables *required* throughout the build // // FIXME: should update code to not require this env var - cargo.env("CFG_COMPILER_HOST_TRIPLE", target); + cargo.env("CFG_COMPILER_HOST_TRIPLE", target.triple); // Set this for all builds to make sure doc builds also get it. cargo.env("CFG_RELEASE_CHANNEL", &self.config.channel); @@ -1386,7 +1385,7 @@ mod tests; struct Rustflags(String); impl Rustflags { - fn new(target: &str) -> Rustflags { + fn new(target: TargetSelection) -> Rustflags { let mut ret = Rustflags(String::new()); // Inherit `RUSTFLAGS` by default ... @@ -1394,7 +1393,7 @@ impl Rustflags { // ... and also handle target-specific env RUSTFLAGS if they're // configured. - let target_specific = format!("CARGO_TARGET_{}_RUSTFLAGS", crate::envify(target)); + let target_specific = format!("CARGO_TARGET_{}_RUSTFLAGS", crate::envify(&target.triple)); ret.env(&target_specific); ret diff --git a/src/bootstrap/builder/tests.rs b/src/bootstrap/builder/tests.rs index 1e75e67af0c9e..69a54bec33b67 100644 --- a/src/bootstrap/builder/tests.rs +++ b/src/bootstrap/builder/tests.rs @@ -1,5 +1,5 @@ use super::*; -use crate::config::Config; +use crate::config::{Config, TargetSelection}; use std::thread; use pretty_assertions::assert_eq; @@ -17,16 +17,16 @@ fn configure(host: &[&str], target: &[&str]) -> Config { .join(&thread::current().name().unwrap_or("unknown").replace(":", "-")); t!(fs::create_dir_all(&dir)); config.out = dir; - config.build = INTERNER.intern_str("A"); + config.build = TargetSelection::from_user("A"); config.hosts = vec![config.build] .into_iter() - .chain(host.iter().map(|s| INTERNER.intern_str(s))) + .chain(host.iter().map(|s| TargetSelection::from_user(s))) .collect::>(); config.targets = config .hosts .clone() .into_iter() - .chain(target.iter().map(|s| INTERNER.intern_str(s))) + .chain(target.iter().map(|s| TargetSelection::from_user(s))) .collect::>(); config } @@ -41,7 +41,7 @@ fn dist_baseline() { let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - let a = INTERNER.intern_str("A"); + let a = TargetSelection::from_user("A"); assert_eq!(first(builder.cache.all::()), &[dist::Docs { host: a },]); assert_eq!(first(builder.cache.all::()), &[dist::Mingw { host: a },]); @@ -67,8 +67,8 @@ fn dist_with_targets() { let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); + let a = TargetSelection::from_user("A"); + let b = TargetSelection::from_user("B"); assert_eq!( first(builder.cache.all::()), @@ -98,8 +98,8 @@ fn dist_with_hosts() { let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); + let a = TargetSelection::from_user("A"); + let b = TargetSelection::from_user("B"); assert_eq!( first(builder.cache.all::()), @@ -128,8 +128,8 @@ fn dist_with_hosts() { #[test] fn dist_only_cross_host() { - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); + let a = TargetSelection::from_user("A"); + let b = TargetSelection::from_user("B"); let mut build = Build::new(configure(&["B"], &[])); build.config.docs = false; build.config.extended = true; @@ -156,9 +156,9 @@ fn dist_with_targets_and_hosts() { let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); + let a = TargetSelection::from_user("A"); + let b = TargetSelection::from_user("B"); + let c = TargetSelection::from_user("C"); assert_eq!( first(builder.cache.all::()), @@ -194,9 +194,9 @@ fn dist_with_target_flag() { let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); + let a = TargetSelection::from_user("A"); + let b = TargetSelection::from_user("B"); + let c = TargetSelection::from_user("C"); assert_eq!( first(builder.cache.all::()), @@ -224,8 +224,8 @@ fn dist_with_same_targets_and_hosts() { let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Dist), &[]); - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); + let a = TargetSelection::from_user("A"); + let b = TargetSelection::from_user("B"); assert_eq!( first(builder.cache.all::()), @@ -277,9 +277,9 @@ fn build_default() { let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); + let a = TargetSelection::from_user("A"); + let b = TargetSelection::from_user("B"); + let c = TargetSelection::from_user("C"); assert_eq!( first(builder.cache.all::()), @@ -318,9 +318,9 @@ fn build_with_target_flag() { let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]); - let a = INTERNER.intern_str("A"); - let b = INTERNER.intern_str("B"); - let c = INTERNER.intern_str("C"); + let a = TargetSelection::from_user("A"); + let b = TargetSelection::from_user("B"); + let c = TargetSelection::from_user("C"); assert_eq!( first(builder.cache.all::()), @@ -374,7 +374,7 @@ fn test_with_no_doc_stage0() { let build = Build::new(config); let mut builder = Builder::new(&build); - let host = INTERNER.intern_str("A"); + let host = TargetSelection::from_user("A"); builder .run_step_descriptions(&[StepDescription::from::()], &["src/libstd".into()]); @@ -428,7 +428,7 @@ fn doc_default() { let build = Build::new(config); let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]); - let a = INTERNER.intern_str("A"); + let a = TargetSelection::from_user("A"); // error_index_generator uses stage 1 to share rustdoc artifacts with the // rustdoc tool. @@ -466,7 +466,7 @@ fn test_docs() { let build = Build::new(config); let mut builder = Builder::new(&build); builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Test), &[]); - let a = INTERNER.intern_str("A"); + let a = TargetSelection::from_user("A"); // error_index_generator uses stage 1 to share rustdoc artifacts with the // rustdoc tool. diff --git a/src/bootstrap/cc_detect.rs b/src/bootstrap/cc_detect.rs index ab16ca3732c1f..7ff00d85dd2f2 100644 --- a/src/bootstrap/cc_detect.rs +++ b/src/bootstrap/cc_detect.rs @@ -28,16 +28,15 @@ use std::{env, iter}; use build_helper::output; -use crate::cache::Interned; -use crate::config::Target; +use crate::config::{Target, TargetSelection}; use crate::{Build, GitRepo}; // The `cc` crate doesn't provide a way to obtain a path to the detected archiver, // so use some simplified logic here. First we respect the environment variable `AR`, then // try to infer the archiver path from the C compiler path. // In the future this logic should be replaced by calling into the `cc` crate. -fn cc2ar(cc: &Path, target: &str) -> Option { - if let Some(ar) = env::var_os(format!("AR_{}", target.replace("-", "_"))) { +fn cc2ar(cc: &Path, target: TargetSelection) -> Option { + if let Some(ar) = env::var_os(format!("AR_{}", target.triple.replace("-", "_"))) { Some(PathBuf::from(ar)) } else if let Some(ar) = env::var_os("AR") { Some(PathBuf::from(ar)) @@ -79,8 +78,8 @@ pub fn find(build: &mut Build) { .opt_level(2) .warnings(false) .debug(false) - .target(&target) - .host(&build.build); + .target(&target.triple) + .host(&build.build.triple); match build.crt_static(target) { Some(a) => { cfg.static_crt(a); @@ -106,10 +105,10 @@ pub fn find(build: &mut Build) { let ar = if let ar @ Some(..) = config.and_then(|c| c.ar.clone()) { ar } else { - cc2ar(compiler.path(), &target) + cc2ar(compiler.path(), target) }; - build.cc.insert(target, compiler); + build.cc.insert(target, compiler.clone()); let cflags = build.cflags(target, GitRepo::Rustc); // If we use llvm-libunwind, we will need a C++ compiler as well for all targets @@ -120,8 +119,8 @@ pub fn find(build: &mut Build) { .warnings(false) .debug(false) .cpp(true) - .target(&target) - .host(&build.build); + .target(&target.triple) + .host(&build.build.triple); let cxx_configured = if let Some(cxx) = config.and_then(|c| c.cxx.as_ref()) { cfg.compiler(cxx); @@ -138,14 +137,14 @@ pub fn find(build: &mut Build) { build.cxx.insert(target, compiler); } - build.verbose(&format!("CC_{} = {:?}", &target, build.cc(target))); - build.verbose(&format!("CFLAGS_{} = {:?}", &target, cflags)); + build.verbose(&format!("CC_{} = {:?}", &target.triple, build.cc(target))); + build.verbose(&format!("CFLAGS_{} = {:?}", &target.triple, cflags)); if let Ok(cxx) = build.cxx(target) { - build.verbose(&format!("CXX_{} = {:?}", &target, cxx)); - build.verbose(&format!("CXXFLAGS_{} = {:?}", &target, cflags)); + build.verbose(&format!("CXX_{} = {:?}", &target.triple, cxx)); + build.verbose(&format!("CXXFLAGS_{} = {:?}", &target.triple, cflags)); } if let Some(ar) = ar { - build.verbose(&format!("AR_{} = {:?}", &target, ar)); + build.verbose(&format!("AR_{} = {:?}", &target.triple, ar)); build.ar.insert(target, ar); } } @@ -154,17 +153,18 @@ pub fn find(build: &mut Build) { fn set_compiler( cfg: &mut cc::Build, compiler: Language, - target: Interned, + target: TargetSelection, config: Option<&Target>, build: &Build, ) { - match &*target { + match &*target.triple { // When compiling for android we may have the NDK configured in the // config.toml in which case we look there. Otherwise the default // compiler already takes into account the triple in question. t if t.contains("android") => { if let Some(ndk) = config.and_then(|c| c.ndk.as_ref()) { let target = target + .triple .replace("armv7neon", "arm") .replace("armv7", "arm") .replace("thumbv7neon", "arm") diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 0d38d2eebe793..9f34bb4e6ccd7 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -1,15 +1,15 @@ //! Implementation of compiling the compiler and standard library, in "check"-based modes. use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, std_cargo}; +use crate::config::TargetSelection; use crate::tool::{prepare_tool_cargo, SourceType}; use crate::{Compiler, Mode}; use std::path::PathBuf; #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { - pub target: Interned, + pub target: TargetSelection, } fn args(kind: Kind) -> Vec { @@ -71,7 +71,7 @@ impl Step for Std { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustc { - pub target: Interned, + pub target: TargetSelection, } impl Step for Rustc { @@ -127,7 +127,7 @@ macro_rules! tool_check_step { ($name:ident, $path:expr, $source_type:expr) => { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct $name { - pub target: Interned, + pub target: TargetSelection, } impl Step for $name { @@ -163,8 +163,8 @@ macro_rules! tool_check_step { println!( "Checking {} artifacts ({} -> {})", stringify!($name).to_lowercase(), - &compiler.host, - target + &compiler.host.triple, + target.triple ); run_cargo( builder, @@ -184,7 +184,7 @@ macro_rules! tool_check_step { fn stamp( builder: &Builder<'_>, compiler: Compiler, - target: Interned, + target: TargetSelection, ) -> PathBuf { builder .cargo_out(compiler, Mode::ToolRustc, target) @@ -204,12 +204,12 @@ tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree); /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. -fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: Interned) -> PathBuf { +fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf { builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp") } /// Cargo's output path for librustc in a given stage, compiled by a particular /// compiler for the specified target. -fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: Interned) -> PathBuf { +fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf { builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp") } diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs index b4e58c06fdea9..f83dfe8e635e3 100644 --- a/src/bootstrap/clean.rs +++ b/src/bootstrap/clean.rs @@ -23,7 +23,7 @@ pub fn clean(build: &Build, all: bool) { rm_rf(&build.out.join("dist")); for host in &build.hosts { - let entries = match build.out.join(host).read_dir() { + let entries = match build.out.join(host.triple).read_dir() { Ok(iter) => iter, Err(_) => continue, }; diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 9b4926f28d4ed..f3063489c1854 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -22,6 +22,7 @@ use serde::Deserialize; use crate::builder::Cargo; use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; +use crate::config::TargetSelection; use crate::dist; use crate::native; use crate::tool::SourceType; @@ -30,7 +31,7 @@ use crate::{Compiler, DependencyType, GitRepo, Mode}; #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Std { - pub target: Interned, + pub target: TargetSelection, pub compiler: Compiler, } @@ -129,7 +130,7 @@ fn copy_and_stamp( fn copy_third_party_objects( builder: &Builder<'_>, compiler: &Compiler, - target: Interned, + target: TargetSelection, ) -> Vec<(PathBuf, DependencyType)> { let mut target_deps = vec![]; @@ -157,7 +158,7 @@ fn copy_third_party_objects( fn copy_self_contained_objects( builder: &Builder<'_>, compiler: &Compiler, - target: Interned, + target: TargetSelection, ) -> Vec<(PathBuf, DependencyType)> { // cfg(bootstrap) // Remove when upgrading bootstrap compiler. @@ -212,7 +213,7 @@ fn copy_self_contained_objects( /// Configure cargo to compile the standard library, adding appropriate env vars /// and such. -pub fn std_cargo(builder: &Builder<'_>, target: Interned, stage: u32, cargo: &mut Cargo) { +pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, cargo: &mut Cargo) { if let Some(target) = env::var_os("MACOSX_STD_DEPLOYMENT_TARGET") { cargo.env("MACOSX_DEPLOYMENT_TARGET", target); } @@ -307,7 +308,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: Interned, stage: u32, ca struct StdLink { pub compiler: Compiler, pub target_compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for StdLink { @@ -343,7 +344,7 @@ impl Step for StdLink { fn copy_sanitizers( builder: &Builder<'_>, compiler: &Compiler, - target: Interned, + target: TargetSelection, ) -> Vec { let runtimes: Vec = builder.ensure(native::Sanitizers { target }); @@ -378,7 +379,7 @@ fn copy_sanitizers( #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct StartupObjects { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for StartupObjects { @@ -425,7 +426,7 @@ impl Step for StartupObjects { .arg("--cfg") .arg("bootstrap") .arg("--target") - .arg(target) + .arg(target.rustc_target_arg()) .arg("--emit=obj") .arg("-o") .arg(dst_file) @@ -444,7 +445,7 @@ impl Step for StartupObjects { #[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustc { - pub target: Interned, + pub target: TargetSelection, pub compiler: Compiler, } @@ -524,7 +525,7 @@ impl Step for Rustc { } } -pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned) { +pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) { cargo .arg("--features") .arg(builder.rustc_features()) @@ -533,7 +534,7 @@ pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned, cargo: &mut Cargo, target: Interned) { +pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) { // Set some configuration variables picked up by build scripts and // the compiler alike cargo @@ -614,7 +615,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interne struct RustcLink { pub compiler: Compiler, pub target_compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for RustcLink { @@ -644,11 +645,7 @@ impl Step for RustcLink { /// Cargo's output path for the standard library in a given stage, compiled /// by a particular compiler for the specified target. -pub fn libstd_stamp( - builder: &Builder<'_>, - compiler: Compiler, - target: Interned, -) -> PathBuf { +pub fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf { builder.cargo_out(compiler, Mode::Std, target).join(".libstd.stamp") } @@ -657,7 +654,7 @@ pub fn libstd_stamp( pub fn librustc_stamp( builder: &Builder<'_>, compiler: Compiler, - target: Interned, + target: TargetSelection, ) -> PathBuf { builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp") } @@ -665,7 +662,7 @@ pub fn librustc_stamp( pub fn compiler_file( builder: &Builder<'_>, compiler: &Path, - target: Interned, + target: TargetSelection, file: &str, ) -> PathBuf { let mut cmd = Command::new(compiler); @@ -696,9 +693,9 @@ impl Step for Sysroot { fn run(self, builder: &Builder<'_>) -> Interned { let compiler = self.compiler; let sysroot = if compiler.stage == 0 { - builder.out.join(&compiler.host).join("stage0-sysroot") + builder.out.join(&compiler.host.triple).join("stage0-sysroot") } else { - builder.out.join(&compiler.host).join(format!("stage{}", compiler.stage)) + builder.out.join(&compiler.host.triple).join(format!("stage{}", compiler.stage)) }; let _ = fs::remove_dir_all(&sysroot); t!(fs::create_dir_all(&sysroot)); @@ -812,8 +809,8 @@ impl Step for Assemble { let libdir = builder.sysroot_libdir(target_compiler, target_compiler.host); if let Some(lld_install) = lld_install { - let src_exe = exe("lld", &target_compiler.host); - let dst_exe = exe("rust-lld", &target_compiler.host); + let src_exe = exe("lld", target_compiler.host); + let dst_exe = exe("rust-lld", target_compiler.host); // we prepend this bin directory to the user PATH when linking Rust binaries. To // avoid shadowing the system LLD we rename the LLD we provide to `rust-lld`. let dst = libdir.parent().unwrap().join("bin"); @@ -828,7 +825,7 @@ impl Step for Assemble { // Link the compiler binary itself into place let out_dir = builder.cargo_out(build_compiler, Mode::Rustc, host); - let rustc = out_dir.join(exe("rustc_binary", &*host)); + let rustc = out_dir.join(exe("rustc_binary", host)); let bindir = sysroot.join("bin"); t!(fs::create_dir_all(&bindir)); let compiler = builder.rustc(target_compiler); diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index ff545a6ddcf47..68e1e5e3d73ea 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -7,6 +7,7 @@ use std::cmp; use std::collections::{HashMap, HashSet}; use std::env; use std::ffi::OsString; +use std::fmt; use std::fs; use std::path::{Path, PathBuf}; use std::process; @@ -39,7 +40,7 @@ pub struct Config { pub docs: bool, pub locked_deps: bool, pub vendor: bool, - pub target_config: HashMap, Target>, + pub target_config: HashMap, pub full_bootstrap: bool, pub extended: bool, pub tools: Option>, @@ -112,9 +113,9 @@ pub struct Config { pub rust_thin_lto_import_instr_limit: Option, pub rust_remap_debuginfo: bool, - pub build: Interned, - pub hosts: Vec>, - pub targets: Vec>, + pub build: TargetSelection, + pub hosts: Vec, + pub targets: Vec, pub local_rebuild: bool, pub jemalloc: bool, pub control_flow_guard: bool, @@ -158,6 +159,67 @@ pub struct Config { pub out: PathBuf, } +#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct TargetSelection { + pub triple: Interned, + file: Option>, +} + +impl TargetSelection { + pub fn from_user(selection: &str) -> Self { + let path = Path::new(selection); + + let (triple, file) = if path.exists() { + let triple = path + .file_stem() + .expect("Target specification file has no file stem") + .to_str() + .expect("Target specification file is not UTF-8"); + + (triple, Some(selection)) + } else { + (selection, None) + }; + + let triple = INTERNER.intern_str(triple); + let file = file.map(|f| INTERNER.intern_str(f)); + + Self { triple, file } + } + + pub fn rustc_target_arg(&self) -> &str { + self.file.as_ref().unwrap_or(&self.triple) + } + + pub fn contains(&self, needle: &str) -> bool { + self.triple.contains(needle) + } + + pub fn starts_with(&self, needle: &str) -> bool { + self.triple.starts_with(needle) + } + + pub fn ends_with(&self, needle: &str) -> bool { + self.triple.ends_with(needle) + } +} + +impl fmt::Display for TargetSelection { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.triple)?; + if let Some(file) = self.file { + write!(f, "({})", file)?; + } + Ok(()) + } +} + +impl PartialEq<&str> for TargetSelection { + fn eq(&self, other: &&str) -> bool { + self.triple == *other + } +} + /// Per-target configuration stored in the global configuration structure. #[derive(Default)] pub struct Target { @@ -403,7 +465,7 @@ impl Config { config.missing_tools = false; // set by bootstrap.py - config.build = INTERNER.intern_str(&env::var("BUILD").expect("'BUILD' to be set")); + config.build = TargetSelection::from_user(&env::var("BUILD").expect("'BUILD' to be set")); config.src = Config::path_from_python("SRC"); config.out = Config::path_from_python("BUILD_DIR"); @@ -464,14 +526,16 @@ impl Config { let build = toml.build.clone().unwrap_or_default(); // set by bootstrap.py config.hosts.push(config.build.clone()); - for host in build.host.iter() { - let host = INTERNER.intern_str(host); + for host in build.host.iter().map(|h| TargetSelection::from_user(h)) { if !config.hosts.contains(&host) { config.hosts.push(host); } } - for target in - config.hosts.iter().cloned().chain(build.target.iter().map(|s| INTERNER.intern_str(s))) + for target in config + .hosts + .iter() + .copied() + .chain(build.target.iter().map(|h| TargetSelection::from_user(h))) { if !config.targets.contains(&target) { config.targets.push(target); @@ -637,7 +701,7 @@ impl Config { target.wasi_root = cfg.wasi_root.clone().map(PathBuf::from); target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from); - config.target_config.insert(INTERNER.intern_string(triple.clone()), target); + config.target_config.insert(TargetSelection::from_user(triple), target); } } diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 5d2fcba7feaba..af30747a9592e 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -20,6 +20,7 @@ use crate::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::channel; use crate::compile; +use crate::config::TargetSelection; use crate::tool::{self, Tool}; use crate::util::{exe, is_dylib, timeit}; use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS}; @@ -68,7 +69,7 @@ fn missing_tool(tool_name: &str, skip: bool) { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Docs { - pub host: Interned, + pub host: TargetSelection, } impl Step for Docs { @@ -131,7 +132,7 @@ impl Step for Docs { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustcDocs { - pub host: Interned, + pub host: TargetSelection, } impl Step for RustcDocs { @@ -210,11 +211,11 @@ fn find_files(files: &[&str], path: &[PathBuf]) -> Vec { fn make_win_dist( rust_root: &Path, plat_root: &Path, - target_triple: Interned, + target: TargetSelection, builder: &Builder<'_>, ) { //Ask gcc where it keeps its stuff - let mut cmd = Command::new(builder.cc(target_triple)); + let mut cmd = Command::new(builder.cc(target)); cmd.arg("-print-search-dirs"); let gcc_out = output(&mut cmd); @@ -234,16 +235,16 @@ fn make_win_dist( } } - let compiler = if target_triple == "i686-pc-windows-gnu" { + let compiler = if target == "i686-pc-windows-gnu" { "i686-w64-mingw32-gcc.exe" - } else if target_triple == "x86_64-pc-windows-gnu" { + } else if target == "x86_64-pc-windows-gnu" { "x86_64-w64-mingw32-gcc.exe" } else { "gcc.exe" }; let target_tools = [compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"]; let mut rustc_dlls = vec!["libwinpthread-1.dll"]; - if target_triple.starts_with("i686-") { + if target.starts_with("i686-") { rustc_dlls.push("libgcc_s_dw2-1.dll"); } else { rustc_dlls.push("libgcc_s_seh-1.dll"); @@ -311,7 +312,7 @@ fn make_win_dist( let target_bin_dir = plat_root .join("lib") .join("rustlib") - .join(target_triple) + .join(target.triple) .join("bin") .join("self-contained"); fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed"); @@ -331,7 +332,7 @@ fn make_win_dist( let target_lib_dir = plat_root .join("lib") .join("rustlib") - .join(target_triple) + .join(target.triple) .join("lib") .join("self-contained"); fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed"); @@ -342,7 +343,7 @@ fn make_win_dist( #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Mingw { - pub host: Interned, + pub host: TargetSelection, } impl Step for Mingw { @@ -530,11 +531,11 @@ impl Step for Rustc { // Copy over lld if it's there if builder.config.lld_enabled { - let exe = exe("rust-lld", &compiler.host); + let exe = exe("rust-lld", compiler.host); let src = builder.sysroot_libdir(compiler, host).parent().unwrap().join("bin").join(&exe); // for the rationale about this rename check `compile::copy_lld_to_sysroot` - let dst = image.join("lib/rustlib").join(&*host).join("bin").join(&exe); + let dst = image.join("lib/rustlib").join(&*host.triple).join("bin").join(&exe); t!(fs::create_dir_all(&dst.parent().unwrap())); builder.copy(&src, &dst); } @@ -592,7 +593,7 @@ impl Step for Rustc { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct DebuggerScripts { pub sysroot: Interned, - pub host: Interned, + pub host: TargetSelection, } impl Step for DebuggerScripts { @@ -662,8 +663,8 @@ fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool { } /// Copy stamped files into an image's `target/lib` directory. -fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &Path) { - let dst = image.join("lib/rustlib").join(target).join("lib"); +fn copy_target_libs(builder: &Builder<'_>, target: TargetSelection, image: &Path, stamp: &Path) { + let dst = image.join("lib/rustlib").join(target.triple).join("lib"); let self_contained_dst = dst.join("self-contained"); t!(fs::create_dir_all(&dst)); t!(fs::create_dir_all(&self_contained_dst)); @@ -679,7 +680,7 @@ fn copy_target_libs(builder: &Builder<'_>, target: &str, image: &Path, stamp: &P #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for Std { @@ -718,7 +719,7 @@ impl Step for Std { let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); let stamp = compile::libstd_stamp(builder, compiler_to_use, target); - copy_target_libs(builder, &target, &image, &stamp); + copy_target_libs(builder, target, &image, &stamp); let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -747,7 +748,7 @@ impl Step for Std { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustcDev { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for RustcDev { @@ -787,7 +788,7 @@ impl Step for RustcDev { let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); let stamp = compile::librustc_stamp(builder, compiler_to_use, target); - copy_target_libs(builder, &target, &image, &stamp); + copy_target_libs(builder, target, &image, &stamp); let mut cmd = rust_installer(builder); cmd.arg("generate") @@ -818,7 +819,7 @@ impl Step for RustcDev { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Analysis { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for Analysis { @@ -861,12 +862,12 @@ impl Step for Analysis { let src = builder .stage_out(compiler, Mode::Std) - .join(target) + .join(target.triple) .join(builder.cargo_dir()) .join("deps"); let image_src = src.join("save-analysis"); - let dst = image.join("lib/rustlib").join(target).join("analysis"); + let dst = image.join("lib/rustlib").join(target.triple).join("analysis"); t!(fs::create_dir_all(&dst)); builder.info(&format!("image_src: {:?}, dst: {:?}", image_src, dst)); builder.cp_r(&image_src, &dst); @@ -1163,7 +1164,7 @@ pub fn sanitize_sh(path: &Path) -> String { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Cargo { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for Cargo { @@ -1255,7 +1256,7 @@ impl Step for Cargo { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rls { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for Rls { @@ -1345,7 +1346,7 @@ impl Step for Rls { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustAnalyzer { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for RustAnalyzer { @@ -1432,7 +1433,7 @@ impl Step for RustAnalyzer { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Clippy { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for Clippy { @@ -1523,7 +1524,7 @@ impl Step for Clippy { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Miri { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for Miri { @@ -1620,7 +1621,7 @@ impl Step for Miri { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustfmt { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for Rustfmt { @@ -1714,8 +1715,8 @@ impl Step for Rustfmt { #[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)] pub struct Extended { stage: u32, - host: Interned, - target: Interned, + host: TargetSelection, + target: TargetSelection, } impl Step for Extended { @@ -2255,7 +2256,7 @@ impl Step for Extended { } } -fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: Interned) { +fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) { let mut parts = channel::CFG_RELEASE_NUM.split('.'); cmd.env("CFG_RELEASE_INFO", builder.rust_version()) .env("CFG_RELEASE_NUM", channel::CFG_RELEASE_NUM) @@ -2266,7 +2267,7 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: Interned) { .env("CFG_VER_BUILD", "0") // just needed to build .env("CFG_PACKAGE_VERS", builder.rust_package_vers()) .env("CFG_PACKAGE_NAME", pkgname(builder, "rust")) - .env("CFG_BUILD", target) + .env("CFG_BUILD", target.triple) .env("CFG_CHANNEL", &builder.config.channel); if target.contains("windows-gnu") { @@ -2348,7 +2349,7 @@ impl Step for HashSign { /// /// Note: This function does not yet support Windows, but we also don't support /// linking LLVM tools dynamically on Windows yet. -fn maybe_install_llvm(builder: &Builder<'_>, target: Interned, dst_libdir: &Path) { +fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) { let src_libdir = builder.llvm_out(target).join("lib"); if target.contains("apple-darwin") { @@ -2373,13 +2374,13 @@ fn maybe_install_llvm(builder: &Builder<'_>, target: Interned, dst_libdi } /// Maybe add libLLVM.so to the target lib-dir for linking. -pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: Interned, sysroot: &Path) { - let dst_libdir = sysroot.join("lib/rustlib").join(&*target).join("lib"); +pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) { + let dst_libdir = sysroot.join("lib/rustlib").join(&*target.triple).join("lib"); maybe_install_llvm(builder, target, &dst_libdir); } /// Maybe add libLLVM.so to the runtime lib-dir for rustc itself. -pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: Interned, sysroot: &Path) { +pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) { let dst_libdir = sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target })); maybe_install_llvm(builder, target, &dst_libdir); @@ -2387,7 +2388,7 @@ pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: Interned, + pub target: TargetSelection, } impl Step for LlvmTools { @@ -2425,10 +2426,10 @@ impl Step for LlvmTools { // Prepare the image directory let src_bindir = builder.llvm_out(target).join("bin"); - let dst_bindir = image.join("lib/rustlib").join(&*target).join("bin"); + let dst_bindir = image.join("lib/rustlib").join(&*target.triple).join("bin"); t!(fs::create_dir_all(&dst_bindir)); for tool in LLVM_TOOLS { - let exe = src_bindir.join(exe(tool, &target)); + let exe = src_bindir.join(exe(tool, target)); builder.install(&exe, &dst_bindir, 0o755); } diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 582bc9da0e804..054daa3cf4814 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -18,7 +18,7 @@ use build_helper::{t, up_to_date}; use crate::builder::{Builder, Compiler, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; -use crate::config::Config; +use crate::config::{Config, TargetSelection}; use crate::tool::{self, prepare_tool_cargo, SourceType, Tool}; use crate::util::symlink_dir; @@ -27,7 +27,7 @@ macro_rules! book { $( #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $name { - target: Interned, + target: TargetSelection, } impl Step for $name { @@ -101,7 +101,7 @@ fn is_explicit_request(builder: &Builder<'_>, path: &str) -> bool { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct UnstableBook { - target: Interned, + target: TargetSelection, } impl Step for UnstableBook { @@ -129,7 +129,7 @@ impl Step for UnstableBook { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] struct RustbookSrc { - target: Interned, + target: TargetSelection, name: Interned, src: Interned, } @@ -169,7 +169,7 @@ impl Step for RustbookSrc { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct TheBook { compiler: Compiler, - target: Interned, + target: TargetSelection, } impl Step for TheBook { @@ -241,7 +241,7 @@ impl Step for TheBook { fn invoke_rustdoc( builder: &Builder<'_>, compiler: Compiler, - target: Interned, + target: TargetSelection, markdown: &str, ) { let out = builder.doc_out(target); @@ -277,7 +277,7 @@ fn invoke_rustdoc( #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Standalone { compiler: Compiler, - target: Interned, + target: TargetSelection, } impl Step for Standalone { @@ -386,7 +386,7 @@ impl Step for Standalone { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Std { pub stage: u32, - pub target: Interned, + pub target: TargetSelection, } impl Step for Std { @@ -415,7 +415,7 @@ impl Step for Std { let compiler = builder.compiler(stage, builder.config.build); builder.ensure(compile::Std { compiler, target }); - let out_dir = builder.stage_out(compiler, Mode::Std).join(target).join("doc"); + let out_dir = builder.stage_out(compiler, Mode::Std).join(target.triple).join("doc"); // Here what we're doing is creating a *symlink* (directory junction on // Windows) to the final output location. This is not done as an @@ -487,7 +487,7 @@ impl Step for Std { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustc { stage: u32, - target: Interned, + target: TargetSelection, } impl Step for Rustc { @@ -531,7 +531,7 @@ impl Step for Rustc { // We do not symlink to the same shared folder that already contains std library // documentation from previous steps as we do not want to include that. - let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target).join("doc"); + let out_dir = builder.stage_out(compiler, Mode::Rustc).join(target.triple).join("doc"); t!(symlink_dir_force(&builder.config, &out, &out_dir)); // Build cargo command. @@ -568,7 +568,7 @@ impl Step for Rustc { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Rustdoc { stage: u32, - target: Interned, + target: TargetSelection, } impl Step for Rustdoc { @@ -613,7 +613,7 @@ impl Step for Rustdoc { builder.ensure(tool::Rustdoc { compiler }); // Symlink compiler docs to the output directory of rustdoc documentation. - let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target).join("doc"); + let out_dir = builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"); t!(fs::create_dir_all(&out_dir)); t!(symlink_dir_force(&builder.config, &out, &out_dir)); @@ -641,7 +641,7 @@ impl Step for Rustdoc { #[derive(Ord, PartialOrd, Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct ErrorIndex { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for ErrorIndex { @@ -681,7 +681,7 @@ impl Step for ErrorIndex { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct UnstableBookGen { - target: Interned, + target: TargetSelection, } impl Step for UnstableBookGen { diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index f477c75293385..1055689c81e6a 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -10,8 +10,7 @@ use std::process; use getopts::Options; use crate::builder::Builder; -use crate::cache::{Interned, INTERNER}; -use crate::config::Config; +use crate::config::{Config, TargetSelection}; use crate::{Build, DocTests}; /// Deserialized version of all flags for this compile. @@ -21,8 +20,8 @@ pub struct Flags { pub stage: Option, pub keep_stage: Vec, - pub host: Vec>, - pub target: Vec>, + pub host: Vec, + pub target: Vec, pub config: Option, pub jobs: Option, pub cmd: Subcommand, @@ -532,11 +531,11 @@ Arguments: .collect(), host: split(&matches.opt_strs("host")) .into_iter() - .map(|x| INTERNER.intern_string(x)) + .map(|x| TargetSelection::from_user(&x)) .collect::>(), target: split(&matches.opt_strs("target")) .into_iter() - .map(|x| INTERNER.intern_string(x)) + .map(|x| TargetSelection::from_user(&x)) .collect::>(), config: cfg_file, jobs: matches.opt_str("jobs").map(|j| j.parse().expect("`jobs` should be a number")), diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index 7026b25d1b984..7266625ff39f8 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -14,46 +14,47 @@ use crate::dist::{self, pkgname, sanitize_sh, tmpdir}; use crate::Compiler; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; -use crate::config::Config; +use crate::config::{Config, TargetSelection}; -pub fn install_docs(builder: &Builder<'_>, stage: u32, host: Interned) { +pub fn install_docs(builder: &Builder<'_>, stage: u32, host: TargetSelection) { install_sh(builder, "docs", "rust-docs", stage, Some(host)); } -pub fn install_std(builder: &Builder<'_>, stage: u32, target: Interned) { +pub fn install_std(builder: &Builder<'_>, stage: u32, target: TargetSelection) { install_sh(builder, "std", "rust-std", stage, Some(target)); } -pub fn install_cargo(builder: &Builder<'_>, stage: u32, host: Interned) { +pub fn install_cargo(builder: &Builder<'_>, stage: u32, host: TargetSelection) { install_sh(builder, "cargo", "cargo", stage, Some(host)); } -pub fn install_rls(builder: &Builder<'_>, stage: u32, host: Interned) { +pub fn install_rls(builder: &Builder<'_>, stage: u32, host: TargetSelection) { install_sh(builder, "rls", "rls", stage, Some(host)); } -pub fn install_rust_analyzer(builder: &Builder<'_>, stage: u32, host: Interned) { + +pub fn install_rust_analyzer(builder: &Builder<'_>, stage: u32, host: TargetSelection) { install_sh(builder, "rust-analyzer", "rust-analyzer", stage, Some(host)); } -pub fn install_clippy(builder: &Builder<'_>, stage: u32, host: Interned) { + +pub fn install_clippy(builder: &Builder<'_>, stage: u32, host: TargetSelection) { install_sh(builder, "clippy", "clippy", stage, Some(host)); } -pub fn install_miri(builder: &Builder<'_>, stage: u32, host: Interned) { +pub fn install_miri(builder: &Builder<'_>, stage: u32, host: TargetSelection) { install_sh(builder, "miri", "miri", stage, Some(host)); } -pub fn install_rustfmt(builder: &Builder<'_>, stage: u32, host: Interned) { +pub fn install_rustfmt(builder: &Builder<'_>, stage: u32, host: TargetSelection) { install_sh(builder, "rustfmt", "rustfmt", stage, Some(host)); } -pub fn install_analysis(builder: &Builder<'_>, stage: u32, host: Interned) { +pub fn install_analysis(builder: &Builder<'_>, stage: u32, host: TargetSelection) { install_sh(builder, "analysis", "rust-analysis", stage, Some(host)); } pub fn install_src(builder: &Builder<'_>, stage: u32) { install_sh(builder, "src", "rust-src", stage, None); } -pub fn install_rustc(builder: &Builder<'_>, stage: u32, host: Interned) { +pub fn install_rustc(builder: &Builder<'_>, stage: u32, host: TargetSelection) { install_sh(builder, "rustc", "rustc", stage, Some(host)); } @@ -62,7 +63,7 @@ fn install_sh( package: &str, name: &str, stage: u32, - host: Option>, + host: Option, ) { builder.info(&format!("Install {} stage{} ({:?})", package, stage, host)); @@ -150,7 +151,7 @@ macro_rules! install { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $name { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl $name { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 783a64c3581f9..05c63734b82ae 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -123,6 +123,7 @@ use std::os::windows::fs::symlink_file; use build_helper::{mtime, output, run, run_suppressed, t, try_run, try_run_suppressed}; use filetime::FileTime; +use crate::config::TargetSelection; use crate::util::{exe, libdir, CiEnv}; mod builder; @@ -187,7 +188,7 @@ const LLVM_TOOLS: &[&str] = &[ #[derive(Eq, PartialOrd, Ord, PartialEq, Clone, Copy, Hash, Debug)] pub struct Compiler { stage: u32, - host: Interned, + host: TargetSelection, } #[derive(PartialEq, Eq, Copy, Clone, Debug)] @@ -236,9 +237,9 @@ pub struct Build { verbosity: usize, // Targets for which to build - build: Interned, - hosts: Vec>, - targets: Vec>, + build: TargetSelection, + hosts: Vec, + targets: Vec, // Stage 0 (downloaded) compiler, lld and cargo or their local rust equivalents initial_rustc: PathBuf, @@ -248,10 +249,10 @@ pub struct Build { // Runtime state filled in later on // C/C++ compilers and archiver for all targets - cc: HashMap, cc::Tool>, - cxx: HashMap, cc::Tool>, - ar: HashMap, PathBuf>, - ranlib: HashMap, PathBuf>, + cc: HashMap, + cxx: HashMap, + ar: HashMap, + ranlib: HashMap, // Miscellaneous crates: HashMap, Crate>, is_sudo: bool, @@ -259,7 +260,7 @@ pub struct Build { delayed_failures: RefCell>, prerelease_version: Cell>, tool_artifacts: - RefCell, HashMap)>>>, + RefCell)>>>, } #[derive(Debug)] @@ -365,7 +366,7 @@ impl Build { output( Command::new(&config.initial_rustc) .arg("--target") - .arg(config.build) + .arg(config.build.rustc_target_arg()) .arg("--print") .arg("target-libdir"), ) @@ -453,7 +454,7 @@ impl Build { } pub fn build_triple(&self) -> &[Interned] { - unsafe { slice::from_raw_parts(&self.build, 1) } + slice::from_ref(&self.build.triple) } /// Executes the entire build, as configured by the flags and configuration. @@ -558,7 +559,10 @@ impl Build { } fn tools_dir(&self, compiler: Compiler) -> PathBuf { - let out = self.out.join(&*compiler.host).join(format!("stage{}-tools-bin", compiler.stage)); + let out = self + .out + .join(&*compiler.host.triple) + .join(format!("stage{}-tools-bin", compiler.stage)); t!(fs::create_dir_all(&out)); out } @@ -575,54 +579,54 @@ impl Build { Mode::ToolBootstrap => "-bootstrap-tools", Mode::ToolStd | Mode::ToolRustc => "-tools", }; - self.out.join(&*compiler.host).join(format!("stage{}{}", compiler.stage, suffix)) + self.out.join(&*compiler.host.triple).join(format!("stage{}{}", compiler.stage, suffix)) } /// Returns the root output directory for all Cargo output in a given stage, /// running a particular compiler, whether or not we're building the /// standard library, and targeting the specified architecture. - fn cargo_out(&self, compiler: Compiler, mode: Mode, target: Interned) -> PathBuf { - self.stage_out(compiler, mode).join(&*target).join(self.cargo_dir()) + fn cargo_out(&self, compiler: Compiler, mode: Mode, target: TargetSelection) -> PathBuf { + self.stage_out(compiler, mode).join(&*target.triple).join(self.cargo_dir()) } /// Root output directory for LLVM compiled for `target` /// /// Note that if LLVM is configured externally then the directory returned /// will likely be empty. - fn llvm_out(&self, target: Interned) -> PathBuf { - self.out.join(&*target).join("llvm") + fn llvm_out(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("llvm") } - fn lld_out(&self, target: Interned) -> PathBuf { - self.out.join(&*target).join("lld") + fn lld_out(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("lld") } /// Output directory for all documentation for a target - fn doc_out(&self, target: Interned) -> PathBuf { - self.out.join(&*target).join("doc") + fn doc_out(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("doc") } /// Output directory for all documentation for a target - fn compiler_doc_out(&self, target: Interned) -> PathBuf { - self.out.join(&*target).join("compiler-doc") + fn compiler_doc_out(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("compiler-doc") } /// Output directory for some generated md crate documentation for a target (temporary) - fn md_doc_out(&self, target: Interned) -> Interned { - INTERNER.intern_path(self.out.join(&*target).join("md-doc")) + fn md_doc_out(&self, target: TargetSelection) -> Interned { + INTERNER.intern_path(self.out.join(&*target.triple).join("md-doc")) } /// Output directory for all crate documentation for a target (temporary) /// /// The artifacts here are then copied into `doc_out` above. - fn crate_doc_out(&self, target: Interned) -> PathBuf { - self.out.join(&*target).join("crate-docs") + fn crate_doc_out(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("crate-docs") } /// Returns `true` if no custom `llvm-config` is set for the specified target. /// /// If no custom `llvm-config` was specified then Rust's llvm will be used. - fn is_rust_llvm(&self, target: Interned) -> bool { + fn is_rust_llvm(&self, target: TargetSelection) -> bool { match self.config.target_config.get(&target) { Some(ref c) => c.llvm_config.is_none(), None => true, @@ -630,13 +634,13 @@ impl Build { } /// Returns the path to `FileCheck` binary for the specified target - fn llvm_filecheck(&self, target: Interned) -> PathBuf { + fn llvm_filecheck(&self, target: TargetSelection) -> PathBuf { let target_config = self.config.target_config.get(&target); if let Some(s) = target_config.and_then(|c| c.llvm_filecheck.as_ref()) { s.to_path_buf() } else if let Some(s) = target_config.and_then(|c| c.llvm_config.as_ref()) { let llvm_bindir = output(Command::new(s).arg("--bindir")); - let filecheck = Path::new(llvm_bindir.trim()).join(exe("FileCheck", &*target)); + let filecheck = Path::new(llvm_bindir.trim()).join(exe("FileCheck", target)); if filecheck.exists() { filecheck } else { @@ -644,7 +648,7 @@ impl Build { // llvm subdirectory of the libdir. let llvm_libdir = output(Command::new(s).arg("--libdir")); let lib_filecheck = - Path::new(llvm_libdir.trim()).join("llvm").join(exe("FileCheck", &*target)); + Path::new(llvm_libdir.trim()).join("llvm").join(exe("FileCheck", target)); if lib_filecheck.exists() { lib_filecheck } else { @@ -669,18 +673,18 @@ impl Build { } else { base }; - base.join("bin").join(exe("FileCheck", &*target)) + base.join("bin").join(exe("FileCheck", target)) } } /// Directory for libraries built from C/C++ code and shared between stages. - fn native_dir(&self, target: Interned) -> PathBuf { - self.out.join(&*target).join("native") + fn native_dir(&self, target: TargetSelection) -> PathBuf { + self.out.join(&*target.triple).join("native") } /// Root output directory for rust_test_helpers library compiled for /// `target` - fn test_helpers_out(&self, target: Interned) -> PathBuf { + fn test_helpers_out(&self, target: TargetSelection) -> PathBuf { self.native_dir(target).join("rust-test-helpers") } @@ -693,7 +697,7 @@ impl Build { /// Returns the libdir of the snapshot compiler. fn rustc_snapshot_libdir(&self) -> PathBuf { - self.rustc_snapshot_sysroot().join(libdir(&self.config.build)) + self.rustc_snapshot_sysroot().join(libdir(self.config.build)) } /// Returns the sysroot of the snapshot compiler. @@ -791,13 +795,13 @@ impl Build { } /// Returns the path to the C compiler for the target specified. - fn cc(&self, target: Interned) -> &Path { + fn cc(&self, target: TargetSelection) -> &Path { self.cc[&target].path() } /// Returns a list of flags to pass to the C compiler for the target /// specified. - fn cflags(&self, target: Interned, which: GitRepo) -> Vec { + fn cflags(&self, target: TargetSelection, which: GitRepo) -> Vec { // Filter out -O and /O (the optimization flags) that we picked up from // cc-rs because the build scripts will determine that for themselves. let mut base = self.cc[&target] @@ -818,7 +822,7 @@ impl Build { // Work around an apparently bad MinGW / GCC optimization, // See: http://lists.llvm.org/pipermail/cfe-dev/2016-December/051980.html // See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78936 - if &*target == "i686-pc-windows-gnu" { + if &*target.triple == "i686-pc-windows-gnu" { base.push("-fno-omit-frame-pointer".into()); } @@ -836,17 +840,17 @@ impl Build { } /// Returns the path to the `ar` archive utility for the target specified. - fn ar(&self, target: Interned) -> Option<&Path> { + fn ar(&self, target: TargetSelection) -> Option<&Path> { self.ar.get(&target).map(|p| &**p) } /// Returns the path to the `ranlib` utility for the target specified. - fn ranlib(&self, target: Interned) -> Option<&Path> { + fn ranlib(&self, target: TargetSelection) -> Option<&Path> { self.ranlib.get(&target).map(|p| &**p) } /// Returns the path to the C++ compiler for the target specified. - fn cxx(&self, target: Interned) -> Result<&Path, String> { + fn cxx(&self, target: TargetSelection) -> Result<&Path, String> { match self.cxx.get(&target) { Some(p) => Ok(p.path()), None => { @@ -856,12 +860,12 @@ impl Build { } /// Returns the path to the linker for the given target if it needs to be overridden. - fn linker(&self, target: Interned, can_use_lld: bool) -> Option<&Path> { + fn linker(&self, target: TargetSelection, can_use_lld: bool) -> Option<&Path> { if let Some(linker) = self.config.target_config.get(&target).and_then(|c| c.linker.as_ref()) { Some(linker) } else if target != self.config.build - && util::use_host_linker(&target) + && util::use_host_linker(target) && !target.contains("msvc") { Some(self.cc(target)) @@ -873,7 +877,7 @@ impl Build { } /// Returns if this target should statically link the C runtime, if specified - fn crt_static(&self, target: Interned) -> Option { + fn crt_static(&self, target: TargetSelection) -> Option { if target.contains("pc-windows-msvc") { Some(true) } else { @@ -882,7 +886,7 @@ impl Build { } /// Returns the "musl root" for this `target`, if defined - fn musl_root(&self, target: Interned) -> Option<&Path> { + fn musl_root(&self, target: TargetSelection) -> Option<&Path> { self.config .target_config .get(&target) @@ -892,7 +896,7 @@ impl Build { } /// Returns the "musl libdir" for this `target`. - fn musl_libdir(&self, target: Interned) -> Option { + fn musl_libdir(&self, target: TargetSelection) -> Option { let t = self.config.target_config.get(&target)?; if let libdir @ Some(_) = &t.musl_libdir { return libdir.clone(); @@ -901,18 +905,18 @@ impl Build { } /// Returns the sysroot for the wasi target, if defined - fn wasi_root(&self, target: Interned) -> Option<&Path> { + fn wasi_root(&self, target: TargetSelection) -> Option<&Path> { self.config.target_config.get(&target).and_then(|t| t.wasi_root.as_ref()).map(|p| &**p) } /// Returns `true` if this is a no-std `target`, if defined - fn no_std(&self, target: Interned) -> Option { + fn no_std(&self, target: TargetSelection) -> Option { self.config.target_config.get(&target).map(|t| t.no_std) } /// Returns `true` if the target will be tested using the `remote-test-client` /// and `remote-test-server` binaries. - fn remote_tested(&self, target: Interned) -> bool { + fn remote_tested(&self, target: TargetSelection) -> bool { self.qemu_rootfs(target).is_some() || target.contains("android") || env::var_os("TEST_DEVICE_ADDR").is_some() @@ -923,7 +927,7 @@ impl Build { /// /// If `Some` is returned then that means that tests for this target are /// emulated with QEMU and binaries will need to be shipped to the emulator. - fn qemu_rootfs(&self, target: Interned) -> Option<&Path> { + fn qemu_rootfs(&self, target: TargetSelection) -> Option<&Path> { self.config.target_config.get(&target).and_then(|t| t.qemu_rootfs.as_ref()).map(|p| &**p) } @@ -955,7 +959,7 @@ impl Build { /// /// When all of these conditions are met the build will lift artifacts from /// the previous stage forward. - fn force_use_stage1(&self, compiler: Compiler, target: Interned) -> bool { + fn force_use_stage1(&self, compiler: Compiler, target: TargetSelection) -> bool { !self.config.full_bootstrap && compiler.stage >= 2 && (self.hosts.iter().any(|h| *h == target) || target == self.build) @@ -1065,7 +1069,7 @@ impl Build { self.rust_version() } - fn llvm_link_tools_dynamically(&self, target: Interned) -> bool { + fn llvm_link_tools_dynamically(&self, target: TargetSelection) -> bool { target.contains("linux-gnu") || target.contains("apple-darwin") } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index e8ec575ea3746..bc71242b619db 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -19,8 +19,8 @@ use std::process::Command; use build_helper::{output, t}; use crate::builder::{Builder, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; use crate::channel; +use crate::config::TargetSelection; use crate::util::{self, exe}; use crate::GitRepo; use build_helper::up_to_date; @@ -41,7 +41,7 @@ pub struct Meta { // if not). pub fn prebuilt_llvm_config( builder: &Builder<'_>, - target: Interned, + target: TargetSelection, ) -> Result { // If we're using a custom LLVM bail out here, but we can only use a // custom LLVM for the build triple. @@ -54,13 +54,14 @@ pub fn prebuilt_llvm_config( let root = "src/llvm-project/llvm"; let out_dir = builder.llvm_out(target); + let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build); if !builder.config.build.contains("msvc") || builder.config.ninja { llvm_config_ret_dir.push("build"); } llvm_config_ret_dir.push("bin"); - let build_llvm_config = llvm_config_ret_dir.join(exe("llvm-config", &*builder.config.build)); + let build_llvm_config = llvm_config_ret_dir.join(exe("llvm-config", builder.config.build)); let stamp = out_dir.join("llvm-finished-building"); let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha()); @@ -93,7 +94,7 @@ pub fn prebuilt_llvm_config( #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Llvm { - pub target: Interned, + pub target: TargetSelection, } impl Step for Llvm { @@ -165,8 +166,8 @@ impl Step for Llvm { .define("LLVM_ENABLE_BINDINGS", "OFF") .define("LLVM_ENABLE_Z3_SOLVER", "OFF") .define("LLVM_PARALLEL_COMPILE_JOBS", builder.jobs().to_string()) - .define("LLVM_TARGET_ARCH", target.split('-').next().unwrap()) - .define("LLVM_DEFAULT_TARGET_TRIPLE", target); + .define("LLVM_TARGET_ARCH", target.triple.split('-').next().unwrap()) + .define("LLVM_DEFAULT_TARGET_TRIPLE", target.triple); if !target.contains("netbsd") { cfg.define("LLVM_ENABLE_ZLIB", "ON"); @@ -339,7 +340,7 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) { fn configure_cmake( builder: &Builder<'_>, - target: Interned, + target: TargetSelection, cfg: &mut cmake::Config, use_compiler_launcher: bool, ) { @@ -350,7 +351,7 @@ fn configure_cmake( if builder.config.ninja { cfg.generator("Ninja"); } - cfg.target(&target).host(&builder.config.build); + cfg.target(&target.triple).host(&builder.config.build.triple); let sanitize_cc = |cc: &Path| { if target.contains("msvc") { @@ -380,7 +381,7 @@ fn configure_cmake( cfg.define("CMAKE_C_COMPILER", sanitize_cc(&wrap_cc)) .define("CMAKE_CXX_COMPILER", sanitize_cc(&wrap_cc)); cfg.env("SCCACHE_PATH", builder.config.ccache.as_ref().unwrap()) - .env("SCCACHE_TARGET", target) + .env("SCCACHE_TARGET", target.triple) .env("SCCACHE_CC", &cc) .env("SCCACHE_CXX", &cxx); @@ -480,7 +481,7 @@ fn configure_cmake( #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Lld { - pub target: Interned, + pub target: TargetSelection, } impl Step for Lld { @@ -553,8 +554,8 @@ impl Step for Lld { // brittle and will break over time. If anyone knows better how to // cross-compile LLD it would be much appreciated to fix this! if target != builder.config.build { - cfg.env("LLVM_CONFIG_SHIM_REPLACE", &builder.config.build) - .env("LLVM_CONFIG_SHIM_REPLACE_WITH", &target) + cfg.env("LLVM_CONFIG_SHIM_REPLACE", &builder.config.build.triple) + .env("LLVM_CONFIG_SHIM_REPLACE_WITH", &target.triple) .define( "LLVM_TABLEGEN_EXE", llvm_config.with_file_name("llvm-tblgen").with_extension(EXE_EXTENSION), @@ -574,7 +575,7 @@ impl Step for Lld { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct TestHelpers { - pub target: Interned, + pub target: TargetSelection, } impl Step for TestHelpers { @@ -621,8 +622,8 @@ impl Step for TestHelpers { cfg.cargo_metadata(false) .out_dir(&dst) - .target(&target) - .host(&builder.config.build) + .target(&target.triple) + .host(&builder.config.build.triple) .opt_level(0) .warnings(false) .debug(false) @@ -633,7 +634,7 @@ impl Step for TestHelpers { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Sanitizers { - pub target: Interned, + pub target: TargetSelection, } impl Step for Sanitizers { @@ -684,7 +685,7 @@ impl Step for Sanitizers { let mut cfg = cmake::Config::new(&compiler_rt_dir); cfg.profile("Release"); - cfg.define("CMAKE_C_COMPILER_TARGET", self.target); + cfg.define("CMAKE_C_COMPILER_TARGET", self.target.triple); cfg.define("COMPILER_RT_BUILD_BUILTINS", "OFF"); cfg.define("COMPILER_RT_BUILD_CRT", "OFF"); cfg.define("COMPILER_RT_BUILD_LIBFUZZER", "OFF"); @@ -727,7 +728,7 @@ pub struct SanitizerRuntime { /// Returns sanitizers available on a given target. fn supported_sanitizers( out_dir: &Path, - target: Interned, + target: TargetSelection, channel: &str, ) -> Vec { let darwin_libs = |os: &str, components: &[&str]| -> Vec { @@ -753,7 +754,7 @@ fn supported_sanitizers( .collect() }; - match &*target { + match &*target.triple { "aarch64-fuchsia" => common_libs("fuchsia", "aarch64", &["asan"]), "aarch64-unknown-linux-gnu" => { common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan"]) diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 3301d41cfeefa..f89bef50de982 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -183,7 +183,11 @@ pub fn check(build: &mut Build) { panic!("the iOS target is only supported on macOS"); } - build.config.target_config.entry(target.clone()).or_insert(Target::from_triple(target)); + build + .config + .target_config + .entry(target.clone()) + .or_insert(Target::from_triple(&target.triple)); if target.contains("-none-") || target.contains("nvptx") { if build.no_std(*target) == Some(false) { diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 1916d96bed71d..b6641180c92c0 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -16,6 +16,7 @@ use build_helper::{self, output, t}; use crate::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; use crate::compile; +use crate::config::TargetSelection; use crate::dist; use crate::flags::Subcommand; use crate::native; @@ -93,7 +94,7 @@ fn try_run_quiet(builder: &Builder<'_>, cmd: &mut Command) -> bool { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Linkcheck { - host: Interned, + host: TargetSelection, } impl Step for Linkcheck { @@ -115,7 +116,7 @@ impl Step for Linkcheck { let _time = util::timeit(&builder); try_run( builder, - builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host).join("doc")), + builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")), ); } @@ -132,7 +133,7 @@ impl Step for Linkcheck { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Cargotest { stage: u32, - host: Interned, + host: TargetSelection, } impl Step for Cargotest { @@ -177,7 +178,7 @@ impl Step for Cargotest { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Cargo { stage: u32, - host: Interned, + host: TargetSelection, } impl Step for Cargo { @@ -230,7 +231,7 @@ impl Step for Cargo { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rls { stage: u32, - host: Interned, + host: TargetSelection, } impl Step for Rls { @@ -281,7 +282,7 @@ impl Step for Rls { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Rustfmt { stage: u32, - host: Interned, + host: TargetSelection, } impl Step for Rustfmt { @@ -338,7 +339,7 @@ impl Step for Rustfmt { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Miri { stage: u32, - host: Interned, + host: TargetSelection, } impl Step for Miri { @@ -464,7 +465,7 @@ impl Step for Miri { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct CompiletestTest { - host: Interned, + host: TargetSelection, } impl Step for CompiletestTest { @@ -501,7 +502,7 @@ impl Step for CompiletestTest { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct Clippy { stage: u32, - host: Interned, + host: TargetSelection, } impl Step for Clippy { @@ -542,8 +543,10 @@ impl Step for Clippy { cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler)); cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler)); let host_libs = builder.stage_out(compiler, Mode::ToolRustc).join(builder.cargo_dir()); - let target_libs = - builder.stage_out(compiler, Mode::ToolRustc).join(&self.host).join(builder.cargo_dir()); + let target_libs = builder + .stage_out(compiler, Mode::ToolRustc) + .join(&self.host.triple) + .join(builder.cargo_dir()); cargo.env("HOST_LIBS", host_libs); cargo.env("TARGET_LIBS", target_libs); // clippy tests need to find the driver @@ -607,7 +610,7 @@ impl Step for RustdocTheme { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustdocJSStd { - pub target: Interned, + pub target: TargetSelection, } impl Step for RustdocJSStd { @@ -646,8 +649,8 @@ impl Step for RustdocJSStd { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustdocJSNotStd { - pub host: Interned, - pub target: Interned, + pub host: TargetSelection, + pub target: TargetSelection, pub compiler: Compiler, } @@ -683,8 +686,8 @@ impl Step for RustdocJSNotStd { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RustdocUi { - pub host: Interned, - pub target: Interned, + pub host: TargetSelection, + pub target: TargetSelection, pub compiler: Compiler, } @@ -785,8 +788,8 @@ impl Step for ExpandYamlAnchors { } } -fn testdir(builder: &Builder<'_>, host: Interned) -> PathBuf { - builder.out.join(host).join("test") +fn testdir(builder: &Builder<'_>, host: TargetSelection) -> PathBuf { + builder.out.join(host.triple).join("test") } macro_rules! default_test { @@ -855,7 +858,7 @@ macro_rules! test_definitions { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct $name { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for $name { @@ -943,7 +946,7 @@ default_test!(Assembly { path: "src/test/assembly", mode: "assembly", suite: "as #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] struct Compiletest { compiler: Compiler, - target: Interned, + target: TargetSelection, mode: &'static str, suite: &'static str, path: &'static str, @@ -1023,8 +1026,8 @@ impl Step for Compiletest { cmd.arg("--build-base").arg(testdir(builder, compiler.host).join(suite)); cmd.arg("--stage-id").arg(format!("stage{}-{}", compiler.stage, target)); cmd.arg("--mode").arg(mode); - cmd.arg("--target").arg(target); - cmd.arg("--host").arg(&*compiler.host); + cmd.arg("--target").arg(target.rustc_target_arg()); + cmd.arg("--host").arg(&*compiler.host.triple); cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.build)); if builder.config.cmd.bless() { @@ -1543,7 +1546,7 @@ impl Step for RustcGuide { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct CrateLibrustc { compiler: Compiler, - target: Interned, + target: TargetSelection, test_kind: TestKind, krate: Interned, } @@ -1589,7 +1592,7 @@ impl Step for CrateLibrustc { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct CrateNotDefault { compiler: Compiler, - target: Interned, + target: TargetSelection, test_kind: TestKind, krate: &'static str, } @@ -1638,7 +1641,7 @@ impl Step for CrateNotDefault { #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Crate { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, pub mode: Mode, pub test_kind: TestKind, pub krate: Interned, @@ -1750,17 +1753,17 @@ impl Step for Crate { if target.contains("emscripten") { cargo.env( - format!("CARGO_TARGET_{}_RUNNER", envify(&target)), + format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), builder.config.nodejs.as_ref().expect("nodejs not configured"), ); } else if target.starts_with("wasm32") { let node = builder.config.nodejs.as_ref().expect("nodejs not configured"); let runner = format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display()); - cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target)), &runner); + cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner); } else if builder.remote_tested(target) { cargo.env( - format!("CARGO_TARGET_{}_RUNNER", envify(&target)), + format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()), ); } @@ -1776,7 +1779,7 @@ impl Step for Crate { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct CrateRustdoc { - host: Interned, + host: TargetSelection, test_kind: TestKind, } @@ -1883,7 +1886,7 @@ impl Step for CrateRustdoc { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct RemoteCopyLibs { compiler: Compiler, - target: Interned, + target: TargetSelection, } impl Step for RemoteCopyLibs { @@ -1911,7 +1914,7 @@ impl Step for RemoteCopyLibs { // Spawn the emulator and wait for it to come online let tool = builder.tool_exe(Tool::RemoteTestClient); let mut cmd = Command::new(&tool); - cmd.arg("spawn-emulator").arg(target).arg(&server).arg(builder.out.join("tmp")); + cmd.arg("spawn-emulator").arg(target.triple).arg(&server).arg(builder.out.join("tmp")); if let Some(rootfs) = builder.qemu_rootfs(target) { cmd.arg(rootfs); } @@ -1966,7 +1969,9 @@ impl Step for Distcheck { .current_dir(&dir), ); builder.run( - Command::new(build_helper::make(&builder.config.build)).arg("check").current_dir(&dir), + Command::new(build_helper::make(&builder.config.build.triple)) + .arg("check") + .current_dir(&dir), ); // Now make sure that rust-src has all of libstd's dependencies diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 450b534d5dfdb..f66061975d64d 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -7,10 +7,10 @@ use std::process::{exit, Command}; use build_helper::t; use crate::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun, Step}; -use crate::cache::Interned; use crate::channel; use crate::channel::GitInfo; use crate::compile; +use crate::config::TargetSelection; use crate::toolstate::ToolState; use crate::util::{add_dylib_path, exe}; use crate::Compiler; @@ -25,7 +25,7 @@ pub enum SourceType { #[derive(Debug, Clone, Hash, PartialEq, Eq)] struct ToolBuild { compiler: Compiler, - target: Interned, + target: TargetSelection, tool: &'static str, path: &'static str, mode: Mode, @@ -111,7 +111,7 @@ impl Step for ToolBuild { .and_then(|p| p.file_name()) .and_then(|p| p.to_str()) .unwrap(); - if maybe_target != &*target { + if maybe_target != &*target.triple { continue; } } @@ -208,8 +208,8 @@ impl Step for ToolBuild { } } else { let cargo_out = - builder.cargo_out(compiler, self.mode, target).join(exe(tool, &compiler.host)); - let bin = builder.tools_dir(compiler).join(exe(tool, &compiler.host)); + builder.cargo_out(compiler, self.mode, target).join(exe(tool, compiler.host)); + let bin = builder.tools_dir(compiler).join(exe(tool, compiler.host)); builder.copy(&cargo_out, &bin); Some(bin) } @@ -220,7 +220,7 @@ pub fn prepare_tool_cargo( builder: &Builder<'_>, compiler: Compiler, mode: Mode, - target: Interned, + target: TargetSelection, command: &'static str, path: &'static str, source_type: SourceType, @@ -303,7 +303,7 @@ macro_rules! bootstrap_tool { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct $name { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for $name { @@ -416,7 +416,7 @@ impl Step for ErrorIndex { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct RemoteTestServer { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for RemoteTestServer { @@ -476,7 +476,7 @@ impl Step for Rustdoc { if !target_compiler.is_snapshot(builder) { panic!("rustdoc in stage 0 must be snapshot rustdoc"); } - return builder.initial_rustc.with_file_name(exe("rustdoc", &target_compiler.host)); + return builder.initial_rustc.with_file_name(exe("rustdoc", target_compiler.host)); } let target = target_compiler.host; // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise @@ -514,14 +514,14 @@ impl Step for Rustdoc { // rustdoc a different name. let tool_rustdoc = builder .cargo_out(build_compiler, Mode::ToolRustc, target) - .join(exe("rustdoc_tool_binary", &target_compiler.host)); + .join(exe("rustdoc_tool_binary", target_compiler.host)); // don't create a stage0-sysroot/bin directory. if target_compiler.stage > 0 { let sysroot = builder.sysroot(target_compiler); let bindir = sysroot.join("bin"); t!(fs::create_dir_all(&bindir)); - let bin_rustdoc = bindir.join(exe("rustdoc", &*target_compiler.host)); + let bin_rustdoc = bindir.join(exe("rustdoc", target_compiler.host)); let _ = fs::remove_file(&bin_rustdoc); builder.copy(&tool_rustdoc, &bin_rustdoc); bin_rustdoc @@ -534,7 +534,7 @@ impl Step for Rustdoc { #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub struct Cargo { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, } impl Step for Cargo { @@ -583,7 +583,7 @@ macro_rules! tool_extended { #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct $name { pub compiler: Compiler, - pub target: Interned, + pub target: TargetSelection, pub extra_features: Vec, } diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs index 2bc6f1939d97b..a307ef39d03a8 100644 --- a/src/bootstrap/util.rs +++ b/src/bootstrap/util.rs @@ -14,17 +14,16 @@ use std::time::Instant; use build_helper::t; use crate::builder::Builder; -use crate::cache::Interned; -use crate::config::Config; +use crate::config::{Config, TargetSelection}; /// Returns the `name` as the filename of a static library for `target`. -pub fn staticlib(name: &str, target: &str) -> String { +pub fn staticlib(name: &str, target: TargetSelection) -> String { if target.contains("windows") { format!("{}.lib", name) } else { format!("lib{}.a", name) } } /// Given an executable called `name`, return the filename for the /// executable for a particular target. -pub fn exe(name: &str, target: &str) -> String { +pub fn exe(name: &str, target: TargetSelection) -> String { if target.contains("windows") { format!("{}.exe", name) } else { name.to_string() } } @@ -35,7 +34,7 @@ pub fn is_dylib(name: &str) -> bool { /// Returns the corresponding relative library directory that the compiler's /// dylibs will be found in. -pub fn libdir(target: &str) -> &'static str { +pub fn libdir(target: TargetSelection) -> &'static str { if target.contains("windows") { "bin" } else { "lib" } } @@ -294,7 +293,7 @@ pub fn forcing_clang_based_tests() -> bool { } } -pub fn use_host_linker(target: &Interned) -> bool { +pub fn use_host_linker(target: TargetSelection) -> bool { // FIXME: this information should be gotten by checking the linker flavor // of the rustc target !(target.contains("emscripten")