1Teaches Cargo to source all std dependencies from vendored sources in the rust-src 2component, making -Zbuild-std compatible with vendored builds. 3 4This was originally landed in https://github.com/rust-lang/cargo/pull/8834 5but was backed out for causing breakage in other situations. It works fine 6for Firefox's usecase, though. 7 8Most of these changes just add/edit tests for the functionality. Only the 9change to src/cargo/core/compiler/standard_lib.rs is important. 10 11diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs 12index 0b14df805..7bc5151a4 100644 13--- a/src/cargo/core/compiler/standard_lib.rs 14+++ b/src/cargo/core/compiler/standard_lib.rs 15@@ -10,6 +10,7 @@ use crate::ops::{self, Packages}; 16 use crate::util::errors::CargoResult; 17 use std::collections::{HashMap, HashSet}; 18 use std::env; 19+use std::fs; 20 use std::path::PathBuf; 21 22 /// Parse the `-Zbuild-std` flag. 23@@ -38,28 +39,46 @@ pub fn resolve_std<'cfg>( 24 crates: &[String], 25 ) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> { 26 let src_path = detect_sysroot_src_path(target_data)?; 27- let to_patch = [ 28- "rustc-std-workspace-core", 29- "rustc-std-workspace-alloc", 30- "rustc-std-workspace-std", 31- ]; 32- let patches = to_patch 33- .iter() 34- .map(|&name| { 35- let source_path = SourceId::for_path(&src_path.join("library").join(name))?; 36- let dep = Dependency::parse_no_deprecated(name, None, source_path)?; 37+ 38+ // Special std packages should be pulled from `library/` and should be 39+ // prefixed with `rustc-std-workspace-` in certain places. 40+ let libs_prefix = "library/"; 41+ let special_std_prefix = "rustc-std-workspace-"; 42+ let libs_path = src_path.join(libs_prefix); 43+ 44+ // Crates in rust-src to build. libtest is in some sense the "root" package 45+ // of std, as nothing else depends on it, so it must be explicitly added. 46+ let mut members = vec![format!("{}test", libs_prefix)]; 47+ 48+ // If rust-src contains a "vendor" directory, then patch in all the crates it contains. 49+ let vendor_path = src_path.join("vendor"); 50+ let vendor_dir = fs::read_dir(vendor_path)?; 51+ let patches = vendor_dir 52+ .into_iter() 53+ .map(|entry| { 54+ let entry = entry?; 55+ let name = entry 56+ .file_name() 57+ .into_string() 58+ .map_err(|_| anyhow::anyhow!("package name wasn't utf8"))?; 59+ 60+ // Remap the rustc-std-workspace crates to the actual rust-src libraries 61+ let path = if let Some(real_name) = name.strip_prefix(special_std_prefix) { 62+ // Record this crate as something to build in the workspace 63+ members.push(format!("{}{}", libs_prefix, real_name)); 64+ libs_path.join(&name) 65+ } else { 66+ entry.path() 67+ }; 68+ let source_path = SourceId::for_path(&path)?; 69+ let dep = Dependency::parse_no_deprecated(&name, None, source_path)?; 70 Ok(dep) 71 }) 72 .collect::<CargoResult<Vec<_>>>()?; 73+ 74 let crates_io_url = crate::sources::CRATES_IO_INDEX.parse().unwrap(); 75 let mut patch = HashMap::new(); 76 patch.insert(crates_io_url, patches); 77- let members = vec![ 78- String::from("library/std"), 79- String::from("library/core"), 80- String::from("library/alloc"), 81- String::from("library/test"), 82- ]; 83 let ws_config = crate::core::WorkspaceConfig::Root(crate::core::WorkspaceRootConfig::new( 84 &src_path, 85 &Some(members), 86diff --git a/tests/testsuite/mock-std/library/test/Cargo.toml b/tests/testsuite/mock-std/library/test/Cargo.toml 87index 299db7bfd..eb81bbf5e 100644 88--- a/tests/testsuite/mock-std/library/test/Cargo.toml 89+++ b/tests/testsuite/mock-std/library/test/Cargo.toml 90@@ -10,6 +10,7 @@ std = { path = "../std" } 91 panic_unwind = { path = "../panic_unwind" } 92 compiler_builtins = { path = "../compiler_builtins" } 93 registry-dep-using-std = { version = "*", features = ['mockbuild'] } 94+registry-dep-only-used-by-test = { version = "*" } 95 96 [features] 97 panic-unwind = [] 98diff --git a/tests/testsuite/mock-std/library/test/src/lib.rs b/tests/testsuite/mock-std/library/test/src/lib.rs 99index a112855f5..224b89bb2 100644 100--- a/tests/testsuite/mock-std/library/test/src/lib.rs 101+++ b/tests/testsuite/mock-std/library/test/src/lib.rs 102@@ -7,4 +7,5 @@ extern crate test; 103 pub use test::*; 104 105 pub fn custom_api() { 106+ registry_dep_only_used_by_test::wow_testing_is_so_easy(); 107 } 108diff --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 109new file mode 100644 110index 000000000..31ba65a98 111--- /dev/null 112+++ b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/Cargo.toml 113@@ -0,0 +1,9 @@ 114+[package] 115+name = "registry-dep-only-used-by-test" 116+version = "1.0.0" 117+authors = ["Alex Crichton <alex@alexcrichton.com>"] 118+edition = "2018" 119+ 120+[dependencies] 121+ 122+[features] 123diff --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 124new file mode 100644 125index 000000000..a68d2aeef 126--- /dev/null 127+++ b/tests/testsuite/mock-std/vendor/registry-dep-only-used-by-test/src/lib.rs 128@@ -0,0 +1,2 @@ 129+pub fn wow_testing_is_so_easy() { 130+} 131\ No newline at end of file 132diff --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 133new file mode 100644 134index 000000000..f7e4ab232 135--- /dev/null 136+++ b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/Cargo.toml 137@@ -0,0 +1,12 @@ 138+[package] 139+name = "registry-dep-using-alloc" 140+version = "1.0.0" 141+authors = ["Alex Crichton <alex@alexcrichton.com>"] 142+edition = "2018" 143+ 144+[dependencies] 145+rustc-std-workspace-alloc = { version = "*", optional = true } 146+rustc-std-workspace-core = { version = "*", optional = true } 147+ 148+[features] 149+mockbuild = ["rustc-std-workspace-alloc", "rustc-std-workspace-core"] 150\ No newline at end of file 151diff --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 152new file mode 100644 153index 000000000..b9ab30339 154--- /dev/null 155+++ b/tests/testsuite/mock-std/vendor/registry-dep-using-alloc/src/lib.rs 156@@ -0,0 +1,9 @@ 157+#[cfg(feature = "mockbuild")] 158+pub fn custom_api() { 159+} 160+ 161+#[cfg(not(feature = "mockbuild"))] 162+pub fn non_sysroot_api() { 163+ core::custom_api(); 164+ alloc::custom_api(); 165+} 166\ No newline at end of file 167diff --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 168new file mode 100644 169index 000000000..befb83a63 170--- /dev/null 171+++ b/tests/testsuite/mock-std/vendor/registry-dep-using-core/Cargo.toml 172@@ -0,0 +1,11 @@ 173+[package] 174+name = "registry-dep-using-core" 175+version = "1.0.0" 176+authors = ["Alex Crichton <alex@alexcrichton.com>"] 177+edition = "2018" 178+ 179+[dependencies] 180+rustc-std-workspace-core = { version = "*", optional = true } 181+ 182+[features] 183+mockbuild = ["rustc-std-workspace-core"] 184\ No newline at end of file 185diff --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 186new file mode 100644 187index 000000000..f9dbac0f4 188--- /dev/null 189+++ b/tests/testsuite/mock-std/vendor/registry-dep-using-core/src/lib.rs 190@@ -0,0 +1,8 @@ 191+#[cfg(feature = "mockbuild")] 192+pub fn custom_api() { 193+} 194+ 195+#[cfg(not(feature = "mockbuild"))] 196+pub fn non_sysroot_api() { 197+ core::custom_api(); 198+} 199\ No newline at end of file 200diff --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 201new file mode 100644 202index 000000000..71ef0a42f 203--- /dev/null 204+++ b/tests/testsuite/mock-std/vendor/registry-dep-using-std/Cargo.toml 205@@ -0,0 +1,11 @@ 206+[package] 207+name = "registry-dep-using-std" 208+version = "1.0.0" 209+authors = ["Alex Crichton <alex@alexcrichton.com>"] 210+edition = "2018" 211+ 212+[dependencies] 213+rustc-std-workspace-std = { version = "*", optional = true } 214+ 215+[features] 216+mockbuild = ["rustc-std-workspace-std"] 217\ No newline at end of file 218diff --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 219new file mode 100644 220index 000000000..f3af39178 221--- /dev/null 222+++ b/tests/testsuite/mock-std/vendor/registry-dep-using-std/src/lib.rs 223@@ -0,0 +1,8 @@ 224+#[cfg(feature = "mockbuild")] 225+pub fn custom_api() { 226+} 227+ 228+#[cfg(not(feature = "mockbuild"))] 229+pub fn non_sysroot_api() { 230+ std::custom_api(); 231+} 232\ No newline at end of file 233diff --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 234new file mode 100644 235index 000000000..4465a08a8 236--- /dev/null 237+++ b/tests/testsuite/mock-std/vendor/rustc-std-workspace-alloc/Cargo.toml 238@@ -0,0 +1 @@ 239+this file shouldn't be read 240\ No newline at end of file 241diff --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 242new file mode 100644 243index 000000000..4465a08a8 244--- /dev/null 245+++ b/tests/testsuite/mock-std/vendor/rustc-std-workspace-core/Cargo.toml 246@@ -0,0 +1 @@ 247+this file shouldn't be read 248\ No newline at end of file 249diff --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 250new file mode 100644 251index 000000000..4465a08a8 252--- /dev/null 253+++ b/tests/testsuite/mock-std/vendor/rustc-std-workspace-std/Cargo.toml 254@@ -0,0 +1 @@ 255+this file shouldn't be read 256\ No newline at end of file 257diff --git a/tests/testsuite/standard_lib.rs b/tests/testsuite/standard_lib.rs 258index b0d42b38d..3bbc49db7 100644 259--- a/tests/testsuite/standard_lib.rs 260+++ b/tests/testsuite/standard_lib.rs 261@@ -27,71 +27,18 @@ fn setup() -> Option<Setup> { 262 return None; 263 } 264 265- // Our mock sysroot requires a few packages from crates.io, so make sure 266- // they're "published" to crates.io. Also edit their code a bit to make sure 267- // that they have access to our custom crates with custom apis. 268+ // Register a version of one of the std dependencies that doesn't compile. 269+ // This ensures that the mock-std's vendor is actually being used. 270 Package::new("registry-dep-using-core", "1.0.0") 271 .file( 272 "src/lib.rs", 273 " 274- #![no_std] 275- 276- #[cfg(feature = \"mockbuild\")] 277- pub fn custom_api() { 278- } 279- 280- #[cfg(not(feature = \"mockbuild\"))] 281- pub fn non_sysroot_api() { 282- core::custom_api(); 283- } 284+ don't compile me bro!! 285 ", 286 ) 287 .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) 288 .feature("mockbuild", &["rustc-std-workspace-core"]) 289 .publish(); 290- Package::new("registry-dep-using-alloc", "1.0.0") 291- .file( 292- "src/lib.rs", 293- " 294- #![no_std] 295- 296- extern crate alloc; 297- 298- #[cfg(feature = \"mockbuild\")] 299- pub fn custom_api() { 300- } 301- 302- #[cfg(not(feature = \"mockbuild\"))] 303- pub fn non_sysroot_api() { 304- core::custom_api(); 305- alloc::custom_api(); 306- } 307- ", 308- ) 309- .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) 310- .add_dep(Dependency::new("rustc-std-workspace-alloc", "*").optional(true)) 311- .feature( 312- "mockbuild", 313- &["rustc-std-workspace-core", "rustc-std-workspace-alloc"], 314- ) 315- .publish(); 316- Package::new("registry-dep-using-std", "1.0.0") 317- .file( 318- "src/lib.rs", 319- " 320- #[cfg(feature = \"mockbuild\")] 321- pub fn custom_api() { 322- } 323- 324- #[cfg(not(feature = \"mockbuild\"))] 325- pub fn non_sysroot_api() { 326- std::custom_api(); 327- } 328- ", 329- ) 330- .add_dep(Dependency::new("rustc-std-workspace-std", "*").optional(true)) 331- .feature("mockbuild", &["rustc-std-workspace-std"]) 332- .publish(); 333 334 let p = ProjectBuilder::new(paths::root().join("rustc-wrapper")) 335 .file( 336@@ -327,6 +274,81 @@ fn depend_same_as_std() { 337 None => return, 338 }; 339 340+ // Our mock sysroot requires a few packages from crates.io, so make sure 341+ // they're "published" to crates.io. Also edit their code a bit to make sure 342+ // that they have access to our custom crates with custom apis. 343+ Package::new("registry-dep-using-core", "1.0.0") 344+ .file( 345+ "src/lib.rs", 346+ " 347+ #![no_std] 348+ 349+ #[cfg(feature = \"mockbuild\")] 350+ pub fn custom_api() { 351+ } 352+ 353+ #[cfg(not(feature = \"mockbuild\"))] 354+ pub fn non_sysroot_api() { 355+ core::custom_api(); 356+ } 357+ ", 358+ ) 359+ .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) 360+ .feature("mockbuild", &["rustc-std-workspace-core"]) 361+ .publish(); 362+ Package::new("registry-dep-using-alloc", "1.0.0") 363+ .file( 364+ "src/lib.rs", 365+ " 366+ #![no_std] 367+ 368+ extern crate alloc; 369+ 370+ #[cfg(feature = \"mockbuild\")] 371+ pub fn custom_api() { 372+ } 373+ 374+ #[cfg(not(feature = \"mockbuild\"))] 375+ pub fn non_sysroot_api() { 376+ core::custom_api(); 377+ alloc::custom_api(); 378+ } 379+ ", 380+ ) 381+ .add_dep(Dependency::new("rustc-std-workspace-core", "*").optional(true)) 382+ .add_dep(Dependency::new("rustc-std-workspace-alloc", "*").optional(true)) 383+ .feature( 384+ "mockbuild", 385+ &["rustc-std-workspace-core", "rustc-std-workspace-alloc"], 386+ ) 387+ .publish(); 388+ Package::new("registry-dep-using-std", "1.0.0") 389+ .file( 390+ "src/lib.rs", 391+ " 392+ #[cfg(feature = \"mockbuild\")] 393+ pub fn custom_api() { 394+ } 395+ 396+ #[cfg(not(feature = \"mockbuild\"))] 397+ pub fn non_sysroot_api() { 398+ std::custom_api(); 399+ } 400+ ", 401+ ) 402+ .add_dep(Dependency::new("rustc-std-workspace-std", "*").optional(true)) 403+ .feature("mockbuild", &["rustc-std-workspace-std"]) 404+ .publish(); 405+ Package::new("registry-dep-only-used-by-test", "1.0.0") 406+ .file( 407+ "src/lib.rs", 408+ " 409+ pub fn wow_testing_is_so_easy() { 410+ } 411+ ", 412+ ) 413+ .publish(); 414+ 415 let p = project() 416 .file( 417 "src/lib.rs", 418