diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index 5e6f3e9e6cc0f..82be4e3361eb6 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -79,7 +79,6 @@ fn main() { cmd.args(&args) .arg("--cfg") .arg(format!("stage{}", stage)) - .arg("--cfg").arg("rustbuild") .env(bootstrap::util::dylib_path_var(), env::join_paths(&dylib_path).unwrap()); @@ -95,6 +94,13 @@ fn main() { cmd.arg("-Cprefer-dynamic"); } + // Pass the `rustbuild` feature flag to crates which rustbuild is + // building. See the comment in bootstrap/lib.rs where this env var is + // set for more details. + if env::var_os("RUSTBUILD_UNSTABLE").is_some() { + cmd.arg("--cfg").arg("rustbuild"); + } + // Help the libc crate compile by assisting it in finding the MUSL // native libraries. if let Some(s) = env::var_os("MUSL_ROOT") { diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 2d2be531e628c..fbee0cb0563aa 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -180,7 +180,7 @@ struct Crate { /// /// These entries currently correspond to the various output directories of the /// build system, with each mod generating output in a different directory. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq, Eq)] pub enum Mode { /// This cargo is going to build the standard library, placing output in the /// "stageN-std" directory. @@ -491,7 +491,7 @@ impl Build { // For other crates, however, we know that we've already got a standard // library up and running, so we can use the normal compiler to compile // build scripts in that situation. - if let Mode::Libstd = mode { + if mode == Mode::Libstd { cargo.env("RUSTC_SNAPSHOT", &self.rustc) .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_snapshot_libdir()); } else { @@ -499,6 +499,27 @@ impl Build { .env("RUSTC_SNAPSHOT_LIBDIR", self.rustc_libdir(compiler)); } + // There are two invariants we try must maintain: + // * stable crates cannot depend on unstable crates (general Rust rule), + // * crates that end up in the sysroot must be unstable (rustbuild rule). + // + // In order to do enforce the latter, we pass the env var + // `RUSTBUILD_UNSTABLE` down the line for any crates which will end up + // in the sysroot. We read this in bootstrap/bin/rustc.rs and if it is + // set, then we pass the `rustbuild` feature to rustc when building the + // the crate. + // + // In turn, crates that can be used here should recognise the `rustbuild` + // feature and opt-in to `rustc_private`. + // + // We can't always pass `rustbuild` because crates which are outside of + // the comipiler, libs, and tests are stable and we don't want to make + // their deps unstable (since this would break the first invariant + // above). + if mode != Mode::Tool { + cargo.env("RUSTBUILD_UNSTABLE", "1"); + } + // Ignore incremental modes except for stage0, since we're // not guaranteeing correctness acros builds if the compiler // is changing under your feet.`