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
432 lines
16 KiB
Diff
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",
|