diff options
Diffstat (limited to 'build/build-rust')
-rw-r--r-- | build/build-rust/README | 3 | ||||
-rw-r--r-- | build/build-rust/cargo-vendor-std.patch | 416 | ||||
-rw-r--r-- | build/build-rust/example.patch | 12 | ||||
-rw-r--r-- | build/build-rust/rust-vendor-std.patch | 80 |
4 files changed, 511 insertions, 0 deletions
diff --git a/build/build-rust/README b/build/build-rust/README new file mode 100644 index 0000000000..34f7af63a5 --- /dev/null +++ b/build/build-rust/README @@ -0,0 +1,3 @@ +This directory is for patches to rust toolchains, see these docs for details: + +https://firefox-source-docs.mozilla.org/build/buildsystem/toolchains.html
\ No newline at end of file diff --git a/build/build-rust/cargo-vendor-std.patch b/build/build-rust/cargo-vendor-std.patch new file mode 100644 index 0000000000..5825eed1c4 --- /dev/null +++ b/build/build-rust/cargo-vendor-std.patch @@ -0,0 +1,416 @@ +Teaches Cargo to source all std dependencies from vendored sources in the rust-src +component, making -Zbuild-std compatible with vendored builds. + +This was originally landed in https://github.com/rust-lang/cargo/pull/8834 +but was backed out for causing breakage in other situations. It works fine +for Firefox's usecase, though. + +Most of these changes just add/edit tests for the functionality. Only the +change to src/cargo/core/compiler/standard_lib.rs is important. + +diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs +index e0baebd51..547b84147 100644 +--- a/src/cargo/core/compiler/standard_lib.rs ++++ b/src/cargo/core/compiler/standard_lib.rs +@@ -11,6 +11,7 @@ use crate::ops::{self, Packages}; + use crate::util::errors::CargoResult; + use crate::Config; + use std::collections::{HashMap, HashSet}; ++use std::fs; + use std::path::PathBuf; + + use super::BuildConfig; +@@ -74,27 +75,45 @@ pub fn resolve_std<'cfg>( + } + + let src_path = detect_sysroot_src_path(target_data)?; +- let to_patch = [ +- "rustc-std-workspace-core", +- "rustc-std-workspace-alloc", +- "rustc-std-workspace-std", +- ]; +- let patches = to_patch +- .iter() +- .map(|&name| { +- let source_path = SourceId::for_path(&src_path.join("library").join(name))?; +- let dep = Dependency::parse(name, None, source_path)?; ++ ++ // Special std packages should be pulled from `library/` and should be ++ // prefixed with `rustc-std-workspace-` in certain places. ++ let libs_prefix = "library/"; ++ let special_std_prefix = "rustc-std-workspace-"; ++ let libs_path = src_path.join(libs_prefix); ++ ++ // Crates in rust-src to build. libtest is in some sense the "root" package ++ // of std, as nothing else depends on it, so it must be explicitly added. ++ let mut members = vec![format!("{}test", libs_prefix)]; ++ ++ // If rust-src contains a "vendor" directory, then patch in all the crates it contains. ++ let vendor_path = src_path.join("vendor"); ++ let vendor_dir = fs::read_dir(vendor_path)?; ++ let patches = vendor_dir ++ .into_iter() ++ .map(|entry| { ++ let entry = entry?; ++ let name = entry ++ .file_name() ++ .into_string() ++ .map_err(|_| anyhow::anyhow!("package name wasn't utf8"))?; ++ ++ // Remap the rustc-std-workspace crates to the actual rust-src libraries ++ let path = if let Some(real_name) = name.strip_prefix(special_std_prefix) { ++ // Record this crate as something to build in the workspace ++ members.push(format!("{}{}", libs_prefix, real_name)); ++ libs_path.join(&name) ++ } else { ++ entry.path() ++ }; ++ let source_path = SourceId::for_path(&path)?; ++ let dep = Dependency::parse(&name, None, source_path)?; + Ok(dep) + }) + .collect::<CargoResult<Vec<_>>>()?; ++ + let crates_io_url = crate::sources::CRATES_IO_INDEX.parse().unwrap(); + let patch = HashMap::from([(crates_io_url, patches)]); +- let members = vec![ +- String::from("library/std"), +- String::from("library/core"), +- String::from("library/alloc"), +- String::from("library/test"), +- ]; + let ws_config = crate::core::WorkspaceConfig::Root(crate::core::WorkspaceRootConfig::new( + &src_path, + &Some(members), +diff --git a/tests/testsuite/mock-std/library/test/Cargo.toml b/tests/testsuite/mock-std/library/test/Cargo.toml +index 299db7bfd..eb81bbf5e 100644 +--- a/tests/testsuite/mock-std/library/test/Cargo.toml ++++ b/tests/testsuite/mock-std/library/test/Cargo.toml +@@ -10,6 +10,7 @@ std = { path = "../std" } + panic_unwind = { path = "../panic_unwind" } + compiler_builtins = { path = "../compiler_builtins" } + registry-dep-using-std = { version = "*", features = ['mockbuild'] } ++registry-dep-only-used-by-test = { version = "*" } + + [features] + panic-unwind = [] +diff --git a/tests/testsuite/mock-std/library/test/src/lib.rs b/tests/testsuite/mock-std/library/test/src/lib.rs +index a112855f5..224b89bb2 100644 +--- a/tests/testsuite/mock-std/library/test/src/lib.rs ++++ b/tests/testsuite/mock-std/library/test/src/lib.rs +@@ -7,4 +7,5 @@ extern crate test; + pub use test::*; + + pub fn custom_api() { ++ registry_dep_only_used_by_test::wow_testing_is_so_easy(); + } +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/Cargo.toml b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/Cargo.toml +new file mode 100644 +index 000000000..31ba65a98 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/Cargo.toml +@@ -0,0 +1,9 @@ ++[package] ++name = "registry-dep-only-used-by-test" ++version = "1.0.0" ++authors = ["Alex Crichton <alex@alexcrichton.com>"] ++edition = "2018" ++ ++[dependencies] ++ ++[features] +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/src/lib.rs b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/src/lib.rs +new file mode 100644 +index 000000000..a68d2aeef +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/src/lib.rs +@@ -0,0 +1,2 @@ ++pub fn wow_testing_is_so_easy() { ++} +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/Cargo.toml b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/Cargo.toml +new file mode 100644 +index 000000000..f7e4ab232 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/Cargo.toml +@@ -0,0 +1,12 @@ ++[package] ++name = "registry-dep-using-alloc" ++version = "1.0.0" ++authors = ["Alex Crichton <alex@alexcrichton.com>"] ++edition = "2018" ++ ++[dependencies] ++rustc-std-workspace-alloc = { version = "*", optional = true } ++rustc-std-workspace-core = { version = "*", optional = true } ++ ++[features] ++mockbuild = ["rustc-std-workspace-alloc", "rustc-std-workspace-core"] +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/src/lib.rs b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/src/lib.rs +new file mode 100644 +index 000000000..b9ab30339 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/src/lib.rs +@@ -0,0 +1,9 @@ ++#[cfg(feature = "mockbuild")] ++pub fn custom_api() { ++} ++ ++#[cfg(not(feature = "mockbuild"))] ++pub fn non_sysroot_api() { ++ core::custom_api(); ++ alloc::custom_api(); ++} +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-core/Cargo.toml b/tests/testsuite/mock-std/vendor/registry-dep-using-core/Cargo.toml +new file mode 100644 +index 000000000..befb83a63 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-core/Cargo.toml +@@ -0,0 +1,11 @@ ++[package] ++name = "registry-dep-using-core" ++version = "1.0.0" ++authors = ["Alex Crichton <alex@alexcrichton.com>"] ++edition = "2018" ++ ++[dependencies] ++rustc-std-workspace-core = { version = "*", optional = true } ++ ++[features] ++mockbuild = ["rustc-std-workspace-core"] +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-core/src/lib.rs b/tests/testsuite/mock-std/vendor/registry-dep-using-core/src/lib.rs +new file mode 100644 +index 000000000..f9dbac0f4 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-core/src/lib.rs +@@ -0,0 +1,8 @@ ++#[cfg(feature = "mockbuild")] ++pub fn custom_api() { ++} ++ ++#[cfg(not(feature = "mockbuild"))] ++pub fn non_sysroot_api() { ++ core::custom_api(); ++} +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-std/Cargo.toml b/tests/testsuite/mock-std/vendor/registry-dep-using-std/Cargo.toml +new file mode 100644 +index 000000000..71ef0a42f +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-std/Cargo.toml +@@ -0,0 +1,11 @@ ++[package] ++name = "registry-dep-using-std" ++version = "1.0.0" ++authors = ["Alex Crichton <alex@alexcrichton.com>"] ++edition = "2018" ++ ++[dependencies] ++rustc-std-workspace-std = { version = "*", optional = true } ++ ++[features] ++mockbuild = ["rustc-std-workspace-std"] +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/registry-dep-using-std/src/lib.rs b/tests/testsuite/mock-std/vendor/registry-dep-using-std/src/lib.rs +new file mode 100644 +index 000000000..f3af39178 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/registry-dep-using-std/src/lib.rs +@@ -0,0 +1,8 @@ ++#[cfg(feature = "mockbuild")] ++pub fn custom_api() { ++} ++ ++#[cfg(not(feature = "mockbuild"))] ++pub fn non_sysroot_api() { ++ std::custom_api(); ++} +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/rustc-std-workspace-alloc/Cargo.toml b/tests/testsuite/mock-std/vendor/rustc-std-workspace-alloc/Cargo.toml +new file mode 100644 +index 000000000..4465a08a8 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/rustc-std-workspace-alloc/Cargo.toml +@@ -0,0 +1 @@ ++this file shouldn't be read +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/rustc-std-workspace-core/Cargo.toml b/tests/testsuite/mock-std/vendor/rustc-std-workspace-core/Cargo.toml +new file mode 100644 +index 000000000..4465a08a8 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/rustc-std-workspace-core/Cargo.toml +@@ -0,0 +1 @@ ++this file shouldn't be read +\ No newline at end of file +diff --git a/tests/testsuite/mock-std/vendor/rustc-std-workspace-std/Cargo.toml b/tests/testsuite/mock-std/vendor/rustc-std-workspace-std/Cargo.toml +new file mode 100644 +index 000000000..4465a08a8 +--- /dev/null ++++ b/tests/testsuite/mock-std/vendor/rustc-std-workspace-std/Cargo.toml +@@ -0,0 +1 @@ ++this file shouldn't be read +\ No newline at end of file +diff --git a/tests/testsuite/standard_lib.rs b/tests/testsuite/standard_lib.rs +index d3be303ea..486a9b4e0 100644 +--- a/tests/testsuite/standard_lib.rs ++++ b/tests/testsuite/standard_lib.rs +@@ -15,71 +15,18 @@ struct Setup { + } + + fn setup() -> Setup { +- // Our mock sysroot requires a few packages from crates.io, so make sure +- // they're "published" to crates.io. Also edit their code a bit to make sure +- // that they have access to our custom crates with custom apis. ++ // Register a version of one of the std dependencies that doesn't compile. ++ // This ensures that the mock-std's vendor is actually being used. + Package::new("registry-dep-using-core", "1.0.0") + .file( + "src/lib.rs", + " +- #![no_std] +- +- #[cfg(feature = \"mockbuild\")] +- pub fn custom_api() { +- } +- +- #[cfg(not(feature = \"mockbuild\"))] +- pub fn non_sysroot_api() { +- core::custom_api(); +- } ++ don't compile me bro!! + ", + ) + .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) + .feature("mockbuild", &["rustc-std-workspace-core"]) + .publish(); +- Package::new("registry-dep-using-alloc", "1.0.0") +- .file( +- "src/lib.rs", +- " +- #![no_std] +- +- extern crate alloc; +- +- #[cfg(feature = \"mockbuild\")] +- pub fn custom_api() { +- } +- +- #[cfg(not(feature = \"mockbuild\"))] +- pub fn non_sysroot_api() { +- core::custom_api(); +- alloc::custom_api(); +- } +- ", +- ) +- .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) +- .add_dep(Dependency::new("rustc-std-workspace-alloc", "*").optional(true)) +- .feature( +- "mockbuild", +- &["rustc-std-workspace-core", "rustc-std-workspace-alloc"], +- ) +- .publish(); +- Package::new("registry-dep-using-std", "1.0.0") +- .file( +- "src/lib.rs", +- " +- #[cfg(feature = \"mockbuild\")] +- pub fn custom_api() { +- } +- +- #[cfg(not(feature = \"mockbuild\"))] +- pub fn non_sysroot_api() { +- std::custom_api(); +- } +- ", +- ) +- .add_dep(Dependency::new("rustc-std-workspace-std", "*").optional(true)) +- .feature("mockbuild", &["rustc-std-workspace-std"]) +- .publish(); + + let p = ProjectBuilder::new(paths::root().join("rustc-wrapper")) + .file( +@@ -335,6 +282,81 @@ fn depend_same_as_std() { + fn test() { + let setup = setup(); + ++ // Our mock sysroot requires a few packages from crates.io, so make sure ++ // they're "published" to crates.io. Also edit their code a bit to make sure ++ // that they have access to our custom crates with custom apis. ++ Package::new("registry-dep-using-core", "1.0.0") ++ .file( ++ "src/lib.rs", ++ " ++ #![no_std] ++ ++ #[cfg(feature = \"mockbuild\")] ++ pub fn custom_api() { ++ } ++ ++ #[cfg(not(feature = \"mockbuild\"))] ++ pub fn non_sysroot_api() { ++ core::custom_api(); ++ } ++ ", ++ ) ++ .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) ++ .feature("mockbuild", &["rustc-std-workspace-core"]) ++ .publish(); ++ Package::new("registry-dep-using-alloc", "1.0.0") ++ .file( ++ "src/lib.rs", ++ " ++ #![no_std] ++ ++ extern crate alloc; ++ ++ #[cfg(feature = \"mockbuild\")] ++ pub fn custom_api() { ++ } ++ ++ #[cfg(not(feature = \"mockbuild\"))] ++ pub fn non_sysroot_api() { ++ core::custom_api(); ++ alloc::custom_api(); ++ } ++ ", ++ ) ++ .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) ++ .add_dep(Dependency::new("rustc-std-workspace-alloc", "*").optional(true)) ++ .feature( ++ "mockbuild", ++ &["rustc-std-workspace-core", "rustc-std-workspace-alloc"], ++ ) ++ .publish(); ++ Package::new("registry-dep-using-std", "1.0.0") ++ .file( ++ "src/lib.rs", ++ " ++ #[cfg(feature = \"mockbuild\")] ++ pub fn custom_api() { ++ } ++ ++ #[cfg(not(feature = \"mockbuild\"))] ++ pub fn non_sysroot_api() { ++ std::custom_api(); ++ } ++ ", ++ ) ++ .add_dep(Dependency::new("rustc-std-workspace-std", "*").optional(true)) ++ .feature("mockbuild", &["rustc-std-workspace-std"]) ++ .publish(); ++ Package::new("registry-dep-only-used-by-test", "1.0.0") ++ .file( ++ "src/lib.rs", ++ " ++ pub fn wow_testing_is_so_easy() { ++ } ++ ", ++ ) ++ .publish(); ++ + let p = project() + .file( + "src/lib.rs", diff --git a/build/build-rust/example.patch b/build/build-rust/example.patch new file mode 100644 index 0000000000..09a00bf22f --- /dev/null +++ b/build/build-rust/example.patch @@ -0,0 +1,12 @@ +diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md +index 2a4c42ea0a4..c94b24e9cb1 100644 +--- a/CONTRIBUTING.md ++++ b/CONTRIBUTING.md +@@ -1,5 +1,7 @@ + # Contributing to Rust + ++Hello this is a harmless little example patch! ++ + Thank you for your interest in contributing to Rust! + + To get started, read the [Getting Started] guide in the [rustc-dev-guide]. diff --git a/build/build-rust/rust-vendor-std.patch b/build/build-rust/rust-vendor-std.patch new file mode 100644 index 0000000000..b068f9de54 --- /dev/null +++ b/build/build-rust/rust-vendor-std.patch @@ -0,0 +1,80 @@ +Teaches Rust's build system to vendor std's dependencies into the +rust-src component. + +This was originally landed in https://github.com/rust-lang/rust/pull/78790 +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/dist.rs b/src/bootstrap/dist.rs +index 3cb0eccd324..a3b8154c024 100644 +--- a/src/bootstrap/dist.rs ++++ b/src/bootstrap/dist.rs +@@ -905,6 +905,30 @@ fn run(self, builder: &Builder<'_>) -> GeneratedTarball { + builder.copy(&builder.src.join(file), &dst_src.join(file)); + } + ++ // libtest 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 libtest 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_libtest = dst_src.join("library/test"); ++ let dst_vendor = dst_src.join("vendor"); ++ let root_lock = dst_src.join("Cargo.lock"); ++ let temp_lock = dst_libtest.join("Cargo.lock"); ++ ++ // `cargo vendor` will delete everything from the lockfile that ++ // isn't used by libtest, so we need to not use any links! ++ builder.really_copy(&root_lock, &temp_lock); ++ ++ let mut cmd = Command::new(&builder.initial_cargo); ++ cmd.arg("vendor").arg(dst_vendor).current_dir(&dst_libtest); ++ builder.info("Dist src"); ++ let _time = timeit(builder); ++ builder.run(&mut cmd); ++ ++ builder.remove(&temp_lock); ++ + tarball.generate() + } + } +diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs +index 3ed53452309..1fc0d887748 100644 +--- a/src/bootstrap/lib.rs ++++ b/src/bootstrap/lib.rs +@@ -1437,6 +1437,27 @@ 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, &format!("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 atime = FileTime::from_last_access_time(&metadata); ++ let mtime = FileTime::from_last_modification_time(&metadata); ++ t!(filetime::set_file_times(dst, atime, mtime)); ++ } ++ + /// Copies a file from `src` to `dst` + pub fn copy(&self, src: &Path, dst: &Path) { + self.copy_internal(src, dst, false); |