Teaches Rust's build system to vendor `std`'s dependencies into the `rust-src` component. This was originally landed in , but was backed out for causing some breakage for distro maintainers who need to build Rust itself in a vendored/offline context. It doesn't actually fetch anything interesting from Crates.io, just the magic fake `std`/`core` crates that exist to make the build work right. Those crates *are* vendored but their contents are ignored in favour of the actual stdlib. For Firefox's purposes, these patches still work fine, and are necessary to make `-Zbuild-std` work in a vendored environment. diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 58f86aa996d..ef8c1584011 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -941,6 +941,35 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball { builder.copy_link(&builder.src.join(file), &dst_src.join(file)); } + // libsysroot includes std and everything else, so vendoring it + // creates exactly what's needed for `cargo -Zbuild-std` or any + // other analysis of the stdlib's source. Cargo also needs help + // finding the lock, so we copy it to libsysroot temporarily. + // + // Note that this requires std to only have one version of each + // crate. e.g. two versions of getopts won't be patchable. + let dst_libsysroot = dst_src.join("library/sysroot"); + let dst_vendor = dst_src.join("vendor"); + let root_lock = dst_src.join("Cargo.lock"); + let temp_lock = dst_libsysroot.join("Cargo.lock"); + + // `cargo vendor` will delete everything from the lockfile that + // isn't used by libsysroot, so we need to not use any links! + builder.really_copy(&root_lock, &temp_lock); + + let mut cmd = command(&builder.initial_cargo); + cmd.arg("vendor").arg(dst_vendor).current_dir(&dst_libsysroot); + cmd.env("RUSTC_BOOTSTRAP", "1"); + builder.info("Dist src"); + let _time = timeit(builder); + builder.run( + &mut cmd, + crate::utils::exec::OutputMode::Print, + crate::utils::exec::OutputMode::Print, + ); + + builder.remove(&temp_lock); + tarball.generate() } } diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 453fb39327d..af579af9eca 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -1732,6 +1732,30 @@ fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, DependencyType)> { paths } + /// Copies a file from `src` to `dst` and doesn't use links, so + /// that the copy can be modified without affecting the original. + pub fn really_copy(&self, src: &Path, dst: &Path) { + if self.config.dry_run() { + return; + } + self.verbose_than(1, || println!("Copy {:?} to {:?}", src, dst)); + if src == dst { + return; + } + let _ = fs::remove_file(dst); + let metadata = t!(src.symlink_metadata()); + if let Err(e) = fs::copy(src, dst) { + panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e) + } + t!(fs::set_permissions(dst, metadata.permissions())); + let file_times = fs::FileTimes::new() + .set_accessed(t!(metadata.accessed())) + .set_modified(t!(metadata.modified())); + + let dst_file = t!(fs::File::open(dst)); + t!(dst_file.set_times(file_times)); + } + /// Links a file from `src` to `dst`. /// Attempts to use hard links if possible, falling back to copying. /// You can neither rely on this being a copy nor it being a link,