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;
use crate::util::{exe, is_dylib, symlink_dir};
-use crate::{Compiler, GitRepo, Mode};
-
-use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
-use crate::cache::{Interned, INTERNER};
+use crate::{Compiler, DependencyType, GitRepo, Mode};
#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Std {
- pub target: Interned<String>,
+ pub target: TargetSelection,
pub compiler: Compiler,
}
// Even if we're not building std this stage, the new sysroot must
// still contain the third party objects needed by various targets.
copy_third_party_objects(builder, &compiler, target);
+ copy_self_contained_objects(builder, &compiler, target);
builder.ensure(StdLink {
compiler: compiler_to_use,
return;
}
- target_deps.extend(copy_third_party_objects(builder, &compiler, target).into_iter());
+ target_deps.extend(copy_third_party_objects(builder, &compiler, target));
+ target_deps.extend(copy_self_contained_objects(builder, &compiler, target));
- let mut cargo = builder.cargo(compiler, Mode::Std, target, "build");
+ let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build");
std_cargo(builder, target, compiler.stage, &mut cargo);
builder.info(&format!(
}
}
+fn copy_and_stamp(
+ builder: &Builder<'_>,
+ libdir: &Path,
+ sourcedir: &Path,
+ name: &str,
+ target_deps: &mut Vec<(PathBuf, DependencyType)>,
+ dependency_type: DependencyType,
+) {
+ let target = libdir.join(name);
+ builder.copy(&sourcedir.join(name), &target);
+
+ target_deps.push((target, dependency_type));
+}
+
/// Copies third party objects needed by various targets.
fn copy_third_party_objects(
builder: &Builder<'_>,
compiler: &Compiler,
- target: Interned<String>,
-) -> Vec<PathBuf> {
- let libdir = builder.sysroot_libdir(*compiler, target);
-
+ target: TargetSelection,
+) -> Vec<(PathBuf, DependencyType)> {
let mut target_deps = vec![];
- let mut copy_and_stamp = |sourcedir: &Path, name: &str| {
- let target = libdir.join(name);
- builder.copy(&sourcedir.join(name), &target);
- target_deps.push(target);
- };
+ // FIXME: remove this in 2021
+ if target == "x86_64-fortanix-unknown-sgx" {
+ if env::var_os("X86_FORTANIX_SGX_LIBS").is_some() {
+ builder.info("Warning: X86_FORTANIX_SGX_LIBS environment variable is ignored, libunwind is now compiled as part of rustbuild");
+ }
+ }
+
+ if builder.config.sanitizers && compiler.stage != 0 {
+ // The sanitizers are only copied in stage1 or above,
+ // to avoid creating dependency on LLVM.
+ target_deps.extend(
+ copy_sanitizers(builder, &compiler, target)
+ .into_iter()
+ .map(|d| (d, DependencyType::Target)),
+ );
+ }
+
+ target_deps
+}
+
+/// Copies third party objects needed by various targets for self-contained linkage.
+fn copy_self_contained_objects(
+ builder: &Builder<'_>,
+ compiler: &Compiler,
+ target: TargetSelection,
+) -> Vec<(PathBuf, DependencyType)> {
+ let libdir_self_contained = builder.sysroot_libdir(*compiler, target).join("self-contained");
+ t!(fs::create_dir_all(&libdir_self_contained));
+ let mut target_deps = vec![];
// Copies the CRT objects.
//
// To do that we have to distribute musl startup objects as a part of Rust toolchain
// and link with them manually in the self-contained mode.
if target.contains("musl") {
- let srcdir = builder.musl_root(target).unwrap().join("lib");
+ let srcdir = builder.musl_libdir(target).unwrap();
for &obj in &["crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
- copy_and_stamp(&srcdir, obj);
+ copy_and_stamp(
+ builder,
+ &libdir_self_contained,
+ &srcdir,
+ obj,
+ &mut target_deps,
+ DependencyType::TargetSelfContained,
+ );
}
} else if target.ends_with("-wasi") {
let srcdir = builder.wasi_root(target).unwrap().join("lib/wasm32-wasi");
- copy_and_stamp(&srcdir, "crt1.o");
- }
-
- // Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx.
- //
- // This target needs to be linked to Fortanix's port of llvm's libunwind.
- // libunwind requires support for rwlock and printing to stderr,
- // which is provided by std for this target.
- if target == "x86_64-fortanix-unknown-sgx" {
- let src_path_env = "X86_FORTANIX_SGX_LIBS";
- let src =
- env::var(src_path_env).unwrap_or_else(|_| panic!("{} not found in env", src_path_env));
- copy_and_stamp(Path::new(&src), "libunwind.a");
- }
-
- if builder.config.sanitizers && compiler.stage != 0 {
- // The sanitizers are only copied in stage1 or above,
- // to avoid creating dependency on LLVM.
- target_deps.extend(copy_sanitizers(builder, &compiler, target));
+ copy_and_stamp(
+ builder,
+ &libdir_self_contained,
+ &srcdir,
+ "crt1.o",
+ &mut target_deps,
+ DependencyType::TargetSelfContained,
+ );
+ } else if target.contains("windows-gnu") {
+ for obj in ["crt2.o", "dllcrt2.o"].iter() {
+ let src = compiler_file(builder, builder.cc(target), target, obj);
+ let target = libdir_self_contained.join(obj);
+ builder.copy(&src, &target);
+ target_deps.push((target, DependencyType::TargetSelfContained));
+ }
}
target_deps
/// Configure cargo to compile the standard library, adding appropriate env vars
/// and such.
-pub fn std_cargo(builder: &Builder<'_>, target: Interned<String>, 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);
}
cargo
.args(&["-p", "alloc"])
.arg("--manifest-path")
- .arg(builder.src.join("src/liballoc/Cargo.toml"))
+ .arg(builder.src.join("library/alloc/Cargo.toml"))
.arg("--features")
.arg("compiler-builtins-mem compiler-builtins-c");
} else {
.arg("--features")
.arg(features)
.arg("--manifest-path")
- .arg(builder.src.join("src/libtest/Cargo.toml"));
+ .arg(builder.src.join("library/test/Cargo.toml"));
// Help the libc crate compile by assisting it in finding various
// sysroot native libraries.
if target.contains("musl") {
- if let Some(p) = builder.musl_root(target) {
- let root = format!("native={}/lib", p.to_str().unwrap());
+ if let Some(p) = builder.musl_libdir(target) {
+ let root = format!("native={}", p.to_str().unwrap());
cargo.rustflag("-L").rustflag(&root);
}
}
if stage >= 1 {
cargo.rustflag("-Cembed-bitcode=yes");
}
+
+ // By default, rustc does not include unwind tables unless they are required
+ // for a particular target. They are not required by RISC-V targets, but
+ // compiling the standard library with them means that users can get
+ // backtraces without having to recompile the standard library themselves.
+ //
+ // This choice was discussed in https://github.com/rust-lang/rust/pull/69890
+ if target.contains("riscv") {
+ cargo.rustflag("-Cforce-unwind-tables=yes");
+ }
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct StdLink {
pub compiler: Compiler,
pub target_compiler: Compiler,
- pub target: Interned<String>,
+ pub target: TargetSelection,
}
impl Step for StdLink {
fn copy_sanitizers(
builder: &Builder<'_>,
compiler: &Compiler,
- target: Interned<String>,
+ target: TargetSelection,
) -> Vec<PathBuf> {
let runtimes: Vec<native::SanitizerRuntime> = builder.ensure(native::Sanitizers { target });
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct StartupObjects {
pub compiler: Compiler,
- pub target: Interned<String>,
+ pub target: TargetSelection,
}
impl Step for StartupObjects {
- type Output = Vec<PathBuf>;
+ type Output = Vec<(PathBuf, DependencyType)>;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.path("src/rtstartup")
+ run.path("library/rtstartup")
}
fn make_run(run: RunConfig<'_>) {
/// They don't require any library support as they're just plain old object
/// files, so we just use the nightly snapshot compiler to always build them (as
/// no other compilers are guaranteed to be available).
- fn run(self, builder: &Builder<'_>) -> Vec<PathBuf> {
+ fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
let for_compiler = self.compiler;
let target = self.target;
if !target.contains("windows-gnu") {
let mut target_deps = vec![];
- let src_dir = &builder.src.join("src/rtstartup");
+ let src_dir = &builder.src.join("library").join("rtstartup");
let dst_dir = &builder.native_dir(target).join("rtstartup");
let sysroot_dir = &builder.sysroot_libdir(for_compiler, target);
t!(fs::create_dir_all(dst_dir));
.arg("--cfg")
.arg("bootstrap")
.arg("--target")
- .arg(target)
+ .arg(target.rustc_target_arg())
.arg("--emit=obj")
.arg("-o")
.arg(dst_file)
let target = sysroot_dir.join((*file).to_string() + ".o");
builder.copy(dst_file, &target);
- target_deps.push(target);
- }
-
- for obj in ["crt2.o", "dllcrt2.o"].iter() {
- let src = compiler_file(builder, builder.cc(target), target, obj);
- let target = sysroot_dir.join(obj);
- builder.copy(&src, &target);
- target_deps.push(target);
+ target_deps.push((target, DependencyType::Target));
}
target_deps
#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rustc {
- pub target: Interned<String>,
+ pub target: TargetSelection,
pub compiler: Compiler,
}
impl Step for Rustc {
type Output = ();
const ONLY_HOSTS: bool = true;
- const DEFAULT: bool = true;
+ const DEFAULT: bool = false;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
- run.all_krates("rustc-main")
+ run.path("src/rustc")
}
fn make_run(run: RunConfig<'_>) {
target: builder.config.build,
});
- let mut cargo = builder.cargo(compiler, Mode::Rustc, target, "build");
+ let mut cargo = builder.cargo(compiler, Mode::Rustc, SourceType::InTree, target, "build");
rustc_cargo(builder, &mut cargo, target);
builder.info(&format!(
}
}
-pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) {
+pub fn rustc_cargo(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
cargo
.arg("--features")
.arg(builder.rustc_features())
rustc_cargo_env(builder, cargo, target);
}
-pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: Interned<String>) {
+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
struct RustcLink {
pub compiler: Compiler,
pub target_compiler: Compiler,
- pub target: Interned<String>,
+ pub target: TargetSelection,
}
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<String>,
-) -> PathBuf {
+pub fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
builder.cargo_out(compiler, Mode::Std, target).join(".libstd.stamp")
}
pub fn librustc_stamp(
builder: &Builder<'_>,
compiler: Compiler,
- target: Interned<String>,
+ target: TargetSelection,
) -> PathBuf {
builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc.stamp")
}
pub fn compiler_file(
builder: &Builder<'_>,
compiler: &Path,
- target: Interned<String>,
+ target: TargetSelection,
file: &str,
) -> PathBuf {
let mut cmd = Command::new(compiler);
fn run(self, builder: &Builder<'_>) -> Interned<PathBuf> {
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));
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");
// 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);
sysroot_host_dst: &Path,
stamp: &Path,
) {
+ let self_contained_dst = &sysroot_dst.join("self-contained");
t!(fs::create_dir_all(&sysroot_dst));
t!(fs::create_dir_all(&sysroot_host_dst));
- for (path, host) in builder.read_stamp_file(stamp) {
- if host {
- builder.copy(&path, &sysroot_host_dst.join(path.file_name().unwrap()));
- } else {
- builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
- }
+ t!(fs::create_dir_all(&self_contained_dst));
+ for (path, dependency_type) in builder.read_stamp_file(stamp) {
+ let dst = match dependency_type {
+ DependencyType::Host => sysroot_host_dst,
+ DependencyType::Target => sysroot_dst,
+ DependencyType::TargetSelfContained => self_contained_dst,
+ };
+ builder.copy(&path, &dst.join(path.file_name().unwrap()));
}
}
cargo: Cargo,
tail_args: Vec<String>,
stamp: &Path,
- additional_target_deps: Vec<PathBuf>,
+ additional_target_deps: Vec<(PathBuf, DependencyType)>,
is_check: bool,
) -> Vec<PathBuf> {
if builder.config.dry_run {
if filename.starts_with(&host_root_dir) {
// Unless it's a proc macro used in the compiler
if crate_types.iter().any(|t| t == "proc-macro") {
- deps.push((filename.to_path_buf(), true));
+ deps.push((filename.to_path_buf(), DependencyType::Host));
}
continue;
}
// If this was output in the `deps` dir then this is a precise file
// name (hash included) so we start tracking it.
if filename.starts_with(&target_deps_dir) {
- deps.push((filename.to_path_buf(), false));
+ deps.push((filename.to_path_buf(), DependencyType::Target));
continue;
}
.collect::<Vec<_>>();
for (prefix, extension, expected_len) in toplevel {
let candidates = contents.iter().filter(|&&(_, ref filename, ref meta)| {
- filename.starts_with(&prefix[..])
- && filename[prefix.len()..].starts_with('-')
- && filename.ends_with(&extension[..])
- && meta.len() == expected_len
+ meta.len() == expected_len
+ && filename
+ .strip_prefix(&prefix[..])
+ .map(|s| s.starts_with('-') && s.ends_with(&extension[..]))
+ .unwrap_or(false)
});
let max = candidates
.max_by_key(|&&(_, _, ref metadata)| FileTime::from_last_modification_time(metadata));
let candidate = format!("{}.lib", path_to_add);
let candidate = PathBuf::from(candidate);
if candidate.exists() {
- deps.push((candidate, false));
+ deps.push((candidate, DependencyType::Target));
}
}
- deps.push((path_to_add.into(), false));
+ deps.push((path_to_add.into(), DependencyType::Target));
}
- deps.extend(additional_target_deps.into_iter().map(|d| (d, false)));
+ deps.extend(additional_target_deps);
deps.sort();
let mut new_contents = Vec::new();
- for (dep, proc_macro) in deps.iter() {
- new_contents.extend(if *proc_macro { b"h" } else { b"t" });
+ for (dep, dependency_type) in deps.iter() {
+ new_contents.extend(match *dependency_type {
+ DependencyType::Host => b"h",
+ DependencyType::Target => b"t",
+ DependencyType::TargetSelfContained => b"s",
+ });
new_contents.extend(dep.to_str().unwrap().as_bytes());
new_contents.extend(b"\0");
}
for line in stdout.lines() {
let line = t!(line);
match serde_json::from_str::<CargoMessage<'_>>(&line) {
- Ok(msg) => cb(msg),
+ Ok(msg) => {
+ if builder.config.json_output {
+ // Forward JSON to stdout.
+ println!("{}", line);
+ }
+ cb(msg)
+ }
// If this was informational, just print it out and continue
Err(_) => println!("{}", line),
}