summaryrefslogtreecommitdiffstats
path: root/build/build-rust
diff options
context:
space:
mode:
Diffstat (limited to 'build/build-rust')
-rw-r--r--build/build-rust/README3
-rw-r--r--build/build-rust/cargo-vendor-std.patch416
-rw-r--r--build/build-rust/example.patch12
-rw-r--r--build/build-rust/rust-vendor-std.patch80
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);