Skip to content

Commit 8662ab4

Browse files
committed
Auto merge of #8834 - Gankra:rust-src-vendor, r=ehuss
Check if rust-src contains a vendor dir, and patch it in This is the cargo side of rust-lang/wg-cargo-std-aware#23 Note that this design naively assumes there is only one version of each package. It does not robustly verify this, and will presumably just cryptically fail to resolve dependencies. See rust-lang/rust#78790 for the other half of this change.
2 parents af212d5 + 85b5b18 commit 8662ab4

File tree

15 files changed

+192
-74
lines changed

15 files changed

+192
-74
lines changed

src/cargo/core/compiler/standard_lib.rs

+39-18
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ use crate::core::resolver::features::{FeaturesFor, ResolvedFeatures};
77
use crate::core::resolver::{HasDevUnits, ResolveOpts};
88
use crate::core::{Dependency, PackageId, PackageSet, Resolve, SourceId, Workspace};
99
use crate::ops::{self, Packages};
10-
use crate::util::errors::CargoResult;
10+
use crate::util::errors::{CargoResult, CargoResultExt};
1111
use std::collections::{HashMap, HashSet};
1212
use std::env;
13+
use std::fs;
1314
use std::path::PathBuf;
1415

1516
/// Parse the `-Zbuild-std` flag.
@@ -38,28 +39,48 @@ pub fn resolve_std<'cfg>(
3839
crates: &[String],
3940
) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> {
4041
let src_path = detect_sysroot_src_path(target_data)?;
41-
let to_patch = [
42-
"rustc-std-workspace-core",
43-
"rustc-std-workspace-alloc",
44-
"rustc-std-workspace-std",
45-
];
46-
let patches = to_patch
47-
.iter()
48-
.map(|&name| {
49-
let source_path = SourceId::for_path(&src_path.join("library").join(name))?;
50-
let dep = Dependency::parse_no_deprecated(name, None, source_path)?;
42+
43+
// Special std packages should be pulled from `library/` and should be
44+
// prefixed with `rustc-std-workspace-` in certain places.
45+
let libs_prefix = "library/";
46+
let special_std_prefix = "rustc-std-workspace-";
47+
let libs_path = src_path.join(libs_prefix);
48+
49+
// Crates in rust-src to build. libtest is in some sense the "root" package
50+
// of std, as nothing else depends on it, so it must be explicitly added.
51+
let mut members = vec![format!("{}test", libs_prefix)];
52+
53+
// If rust-src contains a "vendor" directory, then patch in all the crates it contains.
54+
let vendor_path = src_path.join("vendor");
55+
let vendor_dir = fs::read_dir(&vendor_path)
56+
.chain_err(|| format!("could not read vendor path {}", vendor_path.display()))?;
57+
let patches = vendor_dir
58+
.into_iter()
59+
.map(|entry| {
60+
let entry = entry?;
61+
let name = entry
62+
.file_name()
63+
.into_string()
64+
.map_err(|_| anyhow::anyhow!("package name wasn't utf8"))?;
65+
66+
// Remap the rustc-std-workspace crates to the actual rust-src libraries
67+
let path = if let Some(real_name) = name.strip_prefix(special_std_prefix) {
68+
// Record this crate as something to build in the workspace
69+
members.push(format!("{}{}", libs_prefix, real_name));
70+
libs_path.join(&name)
71+
} else {
72+
entry.path()
73+
};
74+
let source_path = SourceId::for_path(&path)?;
75+
let dep = Dependency::parse_no_deprecated(&name, None, source_path)?;
5176
Ok(dep)
5277
})
53-
.collect::<CargoResult<Vec<_>>>()?;
78+
.collect::<CargoResult<Vec<_>>>()
79+
.chain_err(|| "failed to generate vendor patches")?;
80+
5481
let crates_io_url = crate::sources::CRATES_IO_INDEX.parse().unwrap();
5582
let mut patch = HashMap::new();
5683
patch.insert(crates_io_url, patches);
57-
let members = vec![
58-
String::from("library/std"),
59-
String::from("library/core"),
60-
String::from("library/alloc"),
61-
String::from("library/test"),
62-
];
6384
let ws_config = crate::core::WorkspaceConfig::Root(crate::core::WorkspaceRootConfig::new(
6485
&src_path,
6586
&Some(members),

tests/testsuite/mock-std/library/test/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ std = { path = "../std" }
1010
panic_unwind = { path = "../panic_unwind" }
1111
compiler_builtins = { path = "../compiler_builtins" }
1212
registry-dep-using-std = { version = "*", features = ['mockbuild'] }
13+
registry-dep-only-used-by-test = { version = "*" }
1314

1415
[features]
1516
panic-unwind = []

tests/testsuite/mock-std/library/test/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ extern crate test;
77
pub use test::*;
88

99
pub fn custom_api() {
10+
registry_dep_only_used_by_test::wow_testing_is_so_easy();
1011
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "registry-dep-only-used-by-test"
3+
version = "1.0.0"
4+
authors = ["Alex Crichton <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
9+
[features]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pub fn wow_testing_is_so_easy() {
2+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "registry-dep-using-alloc"
3+
version = "1.0.0"
4+
authors = ["Alex Crichton <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
rustc-std-workspace-alloc = { version = "*", optional = true }
9+
rustc-std-workspace-core = { version = "*", optional = true }
10+
11+
[features]
12+
mockbuild = ["rustc-std-workspace-alloc", "rustc-std-workspace-core"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#[cfg(feature = "mockbuild")]
2+
pub fn custom_api() {
3+
}
4+
5+
#[cfg(not(feature = "mockbuild"))]
6+
pub fn non_sysroot_api() {
7+
core::custom_api();
8+
alloc::custom_api();
9+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "registry-dep-using-core"
3+
version = "1.0.0"
4+
authors = ["Alex Crichton <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
rustc-std-workspace-core = { version = "*", optional = true }
9+
10+
[features]
11+
mockbuild = ["rustc-std-workspace-core"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#[cfg(feature = "mockbuild")]
2+
pub fn custom_api() {
3+
}
4+
5+
#[cfg(not(feature = "mockbuild"))]
6+
pub fn non_sysroot_api() {
7+
core::custom_api();
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "registry-dep-using-std"
3+
version = "1.0.0"
4+
authors = ["Alex Crichton <[email protected]>"]
5+
edition = "2018"
6+
7+
[dependencies]
8+
rustc-std-workspace-std = { version = "*", optional = true }
9+
10+
[features]
11+
mockbuild = ["rustc-std-workspace-std"]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#[cfg(feature = "mockbuild")]
2+
pub fn custom_api() {
3+
}
4+
5+
#[cfg(not(feature = "mockbuild"))]
6+
pub fn non_sysroot_api() {
7+
std::custom_api();
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
this file shouldn't be read
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
this file shouldn't be read
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
this file shouldn't be read

tests/testsuite/standard_lib.rs

+78-56
Original file line numberDiff line numberDiff line change
@@ -27,71 +27,18 @@ fn setup() -> Option<Setup> {
2727
return None;
2828
}
2929

30-
// Our mock sysroot requires a few packages from crates.io, so make sure
31-
// they're "published" to crates.io. Also edit their code a bit to make sure
32-
// that they have access to our custom crates with custom apis.
30+
// Register a version of one of the std dependencies that doesn't compile.
31+
// This ensures that the mock-std's vendor is actually being used.
3332
Package::new("registry-dep-using-core", "1.0.0")
3433
.file(
3534
"src/lib.rs",
3635
"
37-
#![no_std]
38-
39-
#[cfg(feature = \"mockbuild\")]
40-
pub fn custom_api() {
41-
}
42-
43-
#[cfg(not(feature = \"mockbuild\"))]
44-
pub fn non_sysroot_api() {
45-
core::custom_api();
46-
}
36+
don't compile me bro!!
4737
",
4838
)
4939
.add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true))
5040
.feature("mockbuild", &["rustc-std-workspace-core"])
5141
.publish();
52-
Package::new("registry-dep-using-alloc", "1.0.0")
53-
.file(
54-
"src/lib.rs",
55-
"
56-
#![no_std]
57-
58-
extern crate alloc;
59-
60-
#[cfg(feature = \"mockbuild\")]
61-
pub fn custom_api() {
62-
}
63-
64-
#[cfg(not(feature = \"mockbuild\"))]
65-
pub fn non_sysroot_api() {
66-
core::custom_api();
67-
alloc::custom_api();
68-
}
69-
",
70-
)
71-
.add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true))
72-
.add_dep(Dependency::new("rustc-std-workspace-alloc", "*").optional(true))
73-
.feature(
74-
"mockbuild",
75-
&["rustc-std-workspace-core", "rustc-std-workspace-alloc"],
76-
)
77-
.publish();
78-
Package::new("registry-dep-using-std", "1.0.0")
79-
.file(
80-
"src/lib.rs",
81-
"
82-
#[cfg(feature = \"mockbuild\")]
83-
pub fn custom_api() {
84-
}
85-
86-
#[cfg(not(feature = \"mockbuild\"))]
87-
pub fn non_sysroot_api() {
88-
std::custom_api();
89-
}
90-
",
91-
)
92-
.add_dep(Dependency::new("rustc-std-workspace-std", "*").optional(true))
93-
.feature("mockbuild", &["rustc-std-workspace-std"])
94-
.publish();
9542

9643
let p = ProjectBuilder::new(paths::root().join("rustc-wrapper"))
9744
.file(
@@ -335,6 +282,81 @@ fn depend_same_as_std() {
335282
None => return,
336283
};
337284

285+
// Our mock sysroot requires a few packages from crates.io, so make sure
286+
// they're "published" to crates.io. Also edit their code a bit to make sure
287+
// that they have access to our custom crates with custom apis.
288+
Package::new("registry-dep-using-core", "1.0.0")
289+
.file(
290+
"src/lib.rs",
291+
"
292+
#![no_std]
293+
294+
#[cfg(feature = \"mockbuild\")]
295+
pub fn custom_api() {
296+
}
297+
298+
#[cfg(not(feature = \"mockbuild\"))]
299+
pub fn non_sysroot_api() {
300+
core::custom_api();
301+
}
302+
",
303+
)
304+
.add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true))
305+
.feature("mockbuild", &["rustc-std-workspace-core"])
306+
.publish();
307+
Package::new("registry-dep-using-alloc", "1.0.0")
308+
.file(
309+
"src/lib.rs",
310+
"
311+
#![no_std]
312+
313+
extern crate alloc;
314+
315+
#[cfg(feature = \"mockbuild\")]
316+
pub fn custom_api() {
317+
}
318+
319+
#[cfg(not(feature = \"mockbuild\"))]
320+
pub fn non_sysroot_api() {
321+
core::custom_api();
322+
alloc::custom_api();
323+
}
324+
",
325+
)
326+
.add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true))
327+
.add_dep(Dependency::new("rustc-std-workspace-alloc", "*").optional(true))
328+
.feature(
329+
"mockbuild",
330+
&["rustc-std-workspace-core", "rustc-std-workspace-alloc"],
331+
)
332+
.publish();
333+
Package::new("registry-dep-using-std", "1.0.0")
334+
.file(
335+
"src/lib.rs",
336+
"
337+
#[cfg(feature = \"mockbuild\")]
338+
pub fn custom_api() {
339+
}
340+
341+
#[cfg(not(feature = \"mockbuild\"))]
342+
pub fn non_sysroot_api() {
343+
std::custom_api();
344+
}
345+
",
346+
)
347+
.add_dep(Dependency::new("rustc-std-workspace-std", "*").optional(true))
348+
.feature("mockbuild", &["rustc-std-workspace-std"])
349+
.publish();
350+
Package::new("registry-dep-only-used-by-test", "1.0.0")
351+
.file(
352+
"src/lib.rs",
353+
"
354+
pub fn wow_testing_is_so_easy() {
355+
}
356+
",
357+
)
358+
.publish();
359+
338360
let p = project()
339361
.file(
340362
"src/lib.rs",

0 commit comments

Comments
 (0)