Source code
Revision control
Copy as Markdown
Other Tools
Teaches Cargo to source all std dependencies from vendored sources in the rust-src
component, making -Zbuild-std compatible with vendored builds.
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",