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;
#[derive(Eq, PartialOrd, Ord, PartialEq, Clone, Copy, Hash, Debug)]
pub struct Compiler {
stage: u32,
- host: Interned<String>,
+ host: TargetSelection,
}
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
verbosity: usize,
// Targets for which to build
- build: Interned<String>,
- hosts: Vec<Interned<String>>,
- targets: Vec<Interned<String>>,
+ build: TargetSelection,
+ hosts: Vec<TargetSelection>,
+ targets: Vec<TargetSelection>,
// Stage 0 (downloaded) compiler, lld and cargo or their local rust equivalents
initial_rustc: PathBuf,
// Runtime state filled in later on
// C/C++ compilers and archiver for all targets
- cc: HashMap<Interned<String>, cc::Tool>,
- cxx: HashMap<Interned<String>, cc::Tool>,
- ar: HashMap<Interned<String>, PathBuf>,
- ranlib: HashMap<Interned<String>, PathBuf>,
+ cc: HashMap<TargetSelection, cc::Tool>,
+ cxx: HashMap<TargetSelection, cc::Tool>,
+ ar: HashMap<TargetSelection, PathBuf>,
+ ranlib: HashMap<TargetSelection, PathBuf>,
// Miscellaneous
crates: HashMap<Interned<String>, Crate>,
is_sudo: bool,
delayed_failures: RefCell<Vec<String>>,
prerelease_version: Cell<Option<u32>>,
tool_artifacts:
- RefCell<HashMap<Interned<String>, HashMap<String, (&'static str, PathBuf, Vec<String>)>>>,
+ RefCell<HashMap<TargetSelection, HashMap<String, (&'static str, PathBuf, Vec<String>)>>>,
}
#[derive(Debug)]
output(
Command::new(&config.initial_rustc)
.arg("--target")
- .arg(config.build)
+ .arg(config.build.rustc_target_arg())
.arg("--print")
.arg("target-libdir"),
)
}
pub fn build_triple(&self) -> &[Interned<String>] {
- 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.
}
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
}
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<String>) -> 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<String>) -> 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<String>) -> 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<String>) -> 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<String>) -> 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<String>) -> Interned<PathBuf> {
- INTERNER.intern_path(self.out.join(&*target).join("md-doc"))
+ fn md_doc_out(&self, target: TargetSelection) -> Interned<PathBuf> {
+ INTERNER.intern_path(self.out.join(&*target.triple).join("md-doc"))
}
/// 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<String>) -> 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,
}
/// Returns the path to `FileCheck` binary for the specified target
- fn llvm_filecheck(&self, target: Interned<String>) -> 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 {
// 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 {
} 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<String>) -> 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<String>) -> PathBuf {
+ fn test_helpers_out(&self, target: TargetSelection) -> PathBuf {
self.native_dir(target).join("rust-test-helpers")
}
/// 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.
}
/// Returns the path to the C compiler for the target specified.
- fn cc(&self, target: Interned<String>) -> &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<String>, which: GitRepo) -> Vec<String> {
+ fn cflags(&self, target: TargetSelection, which: GitRepo) -> Vec<String> {
// 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]
// 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());
}
}
/// Returns the path to the `ar` archive utility for the target specified.
- fn ar(&self, target: Interned<String>) -> 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<String>) -> 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<String>) -> Result<&Path, String> {
+ fn cxx(&self, target: TargetSelection) -> Result<&Path, String> {
match self.cxx.get(&target) {
Some(p) => Ok(p.path()),
None => {
}
/// Returns the path to the linker for the given target if it needs to be overridden.
- fn linker(&self, target: Interned<String>, 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))
}
/// Returns if this target should statically link the C runtime, if specified
- fn crt_static(&self, target: Interned<String>) -> Option<bool> {
+ fn crt_static(&self, target: TargetSelection) -> Option<bool> {
if target.contains("pc-windows-msvc") {
Some(true)
} else {
}
/// Returns the "musl root" for this `target`, if defined
- fn musl_root(&self, target: Interned<String>) -> Option<&Path> {
+ fn musl_root(&self, target: TargetSelection) -> Option<&Path> {
self.config
.target_config
.get(&target)
}
/// Returns the "musl libdir" for this `target`.
- fn musl_libdir(&self, target: Interned<String>) -> Option<PathBuf> {
+ fn musl_libdir(&self, target: TargetSelection) -> Option<PathBuf> {
let t = self.config.target_config.get(&target)?;
if let libdir @ Some(_) = &t.musl_libdir {
return libdir.clone();
}
/// Returns the sysroot for the wasi target, if defined
- fn wasi_root(&self, target: Interned<String>) -> 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<String>) -> Option<bool> {
+ fn no_std(&self, target: TargetSelection) -> Option<bool> {
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<String>) -> 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()
///
/// 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<String>) -> 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)
}
///
/// 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<String>) -> 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)
self.rust_version()
}
- fn llvm_link_tools_dynamically(&self, target: Interned<String>) -> bool {
+ fn llvm_link_tools_dynamically(&self, target: TargetSelection) -> bool {
target.contains("linux-gnu") || target.contains("apple-darwin")
}