Files
tubestation/build/build-rust/cargo-vendor-std-1.79.patch
Mike Hommey fc12f1e821 Bug 1901125 - Properly handle the presence of multiple crates of the same name. r=firefox-build-system-reviewers,sergesanspaille
When building cargo sets up the patches for the vendored dependencies of
libstd, when several of those dependencies are different versions of the
same crate, only one of the corresponding patches work because the
package name, derived from the directory name, doesn't match.

Instead, we always take the package name from Cargo.toml.

While we're here, we add the missing resources on the rust-dev tasks.

Differential Revision: https://phabricator.services.mozilla.com/D213380
2024-06-12 08:27:26 +00:00

432 lines
16 KiB
Diff

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 3e387bddd..41be56056 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::GlobalContext;
use std::collections::{HashMap, HashSet};
+use std::fs;
use std::path::PathBuf;
use std::rc::Rc;
@@ -67,34 +68,54 @@ pub fn resolve_std<'gctx>(
build_config: &BuildConfig,
crates: &[String],
) -> CargoResult<(PackageSet<'gctx>, Resolve, ResolvedFeatures)> {
+ let gctx = ws.gctx();
if build_config.build_plan {
- ws.gctx()
+ gctx
.shell()
.warn("-Zbuild-std does not currently fully support --build-plan")?;
}
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. libsysroot 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!("{}sysroot", 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 package = crate::sources::PathSource::new(&path, source_path, gctx).root_package()?;
+ let dep = Dependency::parse(package.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/sysroot"),
- ];
let ws_config = crate::core::WorkspaceConfig::Root(crate::core::WorkspaceRootConfig::new(
&src_path,
&Some(members),
@@ -115,7 +136,6 @@ pub fn resolve_std<'gctx>(
None,
);
- let gctx = ws.gctx();
// This is a delicate hack. In order for features to resolve correctly,
// the resolver needs to run a specific "current" member of the workspace.
// Thus, in order to set the features for `std`, we need to set `sysroot`
diff --git a/tests/testsuite/mock-std/library/test/Cargo.toml b/tests/testsuite/mock-std/library/test/Cargo.toml
index b9f51eda7..fed5f3973 100644
--- a/tests/testsuite/mock-std/library/test/Cargo.toml
+++ b/tests/testsuite/mock-std/library/test/Cargo.toml
@@ -9,3 +9,4 @@ 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 = "*" }
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",