From c77edbf715be316e95d0ead82378ad83e4ceba54 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 4 Dec 2024 15:47:59 -0500 Subject: [PATCH 1/6] refactor: rename parse_feature fn --- src/cargo/core/features.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 55eae5f4795..2f415c5a971 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -1148,7 +1148,8 @@ impl CliUnstable { } } - fn parse_features(value: Option<&str>) -> Vec { + /// Parse a comma-separated list + fn parse_list(value: Option<&str>) -> Vec { match value { None => Vec::new(), Some("") => Vec::new(), @@ -1197,7 +1198,7 @@ impl CliUnstable { match k { // Permanently unstable features // Sorted alphabetically: - "allow-features" => self.allow_features = Some(parse_features(v).into_iter().collect()), + "allow-features" => self.allow_features = Some(parse_list(v).into_iter().collect()), "print-im-a-teapot" => self.print_im_a_teapot = parse_bool(k, v)?, // Stabilized features @@ -1216,7 +1217,7 @@ impl CliUnstable { // until we feel confident to remove entirely. // // See rust-lang/cargo#11168 - let feats = parse_features(v); + let feats = parse_list(v); let stab_is_not_empty = feats.iter().any(|feat| { matches!( feat.as_str(), @@ -1259,7 +1260,7 @@ impl CliUnstable { "build-std" => { self.build_std = Some(crate::core::compiler::standard_lib::parse_unstable_flag(v)) } - "build-std-features" => self.build_std_features = Some(parse_features(v)), + "build-std-features" => self.build_std_features = Some(parse_list(v)), "cargo-lints" => self.cargo_lints = parse_empty(k, v)?, "codegen-backend" => self.codegen_backend = parse_empty(k, v)?, "config-include" => self.config_include = parse_empty(k, v)?, From e18b64ff80c7f43758c6330beebfbb0e78da5584 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 3 Dec 2024 23:57:43 -0500 Subject: [PATCH 2/6] refactor(build-std): skip consulting std_crate The only functionality of `standard_lib::std_crates` is adding `test` to the requested crate list. `resolve_std` already unconditionally adds `sysroot` to the list, which always includes `test` in dependency graph. Therefore calling `std_crates` is redundant. --- src/cargo/ops/cargo_fetch.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/cargo/ops/cargo_fetch.rs b/src/cargo/ops/cargo_fetch.rs index 37b56438cd6..589bbf47812 100644 --- a/src/cargo/ops/cargo_fetch.rs +++ b/src/cargo/ops/cargo_fetch.rs @@ -64,8 +64,7 @@ pub fn fetch<'a>( } // If -Zbuild-std was passed, download dependencies for the standard library. - // We don't know ahead of time what jobs we'll be running, so tell `std_crates` that. - if let Some(crates) = standard_lib::std_crates(gctx, None) { + if let Some(crates) = gctx.cli_unstable().build_std.as_ref() { let (std_package_set, _, _) = standard_lib::resolve_std(ws, &mut data, &build_config, &crates)?; packages.add_set(std_package_set); From 30d11ce1d9f06907d1e707c4fe379ebf57305a5e Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 5 Dec 2024 00:13:57 -0500 Subject: [PATCH 3/6] refactor(build-std): defer std crates to build Instead of altering the original `-Zbuild-std` arg value, this defers the timing of detereming which crate to build to when Cargo generates std root units. --- src/cargo/core/compiler/standard_lib.rs | 63 ++++++++++--------------- src/cargo/core/features.rs | 18 +------ src/cargo/ops/cargo_compile/mod.rs | 3 +- 3 files changed, 29 insertions(+), 55 deletions(-) diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs index 441d970715d..3ca1c6c7a8d 100644 --- a/src/cargo/core/compiler/standard_lib.rs +++ b/src/cargo/core/compiler/standard_lib.rs @@ -9,54 +9,40 @@ use crate::core::resolver::HasDevUnits; use crate::core::{PackageId, PackageSet, Resolve, Workspace}; use crate::ops::{self, Packages}; use crate::util::errors::CargoResult; -use crate::GlobalContext; + use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use super::BuildConfig; -/// Parse the `-Zbuild-std` flag. -pub fn parse_unstable_flag(value: Option<&str>) -> Vec { +fn std_crates<'a>(crates: &'a [String], units: Option<&[Unit]>) -> HashSet<&'a str> { + let mut crates = HashSet::from_iter(crates.iter().map(|s| s.as_str())); // This is a temporary hack until there is a more principled way to // declare dependencies in Cargo.toml. - let value = value.unwrap_or("std"); - let mut crates: HashSet<&str> = value.split(',').collect(); + if crates.is_empty() { + crates.insert("std"); + } if crates.contains("std") { crates.insert("core"); crates.insert("alloc"); crates.insert("proc_macro"); crates.insert("panic_unwind"); crates.insert("compiler_builtins"); - } else if crates.contains("core") { - crates.insert("compiler_builtins"); - } - crates.into_iter().map(|s| s.to_string()).collect() -} - -pub(crate) fn std_crates(gctx: &GlobalContext, units: Option<&[Unit]>) -> Option> { - let crates = gctx.cli_unstable().build_std.as_ref()?.clone(); - - // Only build libtest if it looks like it is needed. - let mut crates = crates.clone(); - // If we know what units we're building, we can filter for libtest depending on the jobs. - if let Some(units) = units { - if units - .iter() - .any(|unit| unit.mode.is_rustc_test() && unit.target.harness()) - { - // Only build libtest when libstd is built (libtest depends on libstd) - if crates.iter().any(|c| c == "std") && !crates.iter().any(|c| c == "test") { - crates.push("test".to_string()); + // Only build libtest if it looks like it is needed (libtest depends on libstd) + // If we know what units we're building, we can filter for libtest depending on the jobs. + if let Some(units) = units { + if units + .iter() + .any(|unit| unit.mode.is_rustc_test() && unit.target.harness()) + { + crates.insert("test"); } } - } else { - // We don't know what jobs are going to be run, so download libtest just in case. - if !crates.iter().any(|c| c == "test") { - crates.push("test".to_string()) - } + } else if crates.contains("core") { + crates.insert("compiler_builtins"); } - Some(crates) + crates } /// Resolve the standard library dependencies. @@ -66,6 +52,8 @@ pub fn resolve_std<'gctx>( build_config: &BuildConfig, crates: &[String], ) -> CargoResult<(PackageSet<'gctx>, Resolve, ResolvedFeatures)> { + let crates = std_crates(crates, None); + if build_config.build_plan { ws.gctx() .shell() @@ -73,7 +61,7 @@ pub fn resolve_std<'gctx>( } // check that targets support building std - if crates.contains(&"std".to_string()) { + if crates.contains("std") { let unsupported_targets = target_data.get_unsupported_std_targets(); if !unsupported_targets.is_empty() { anyhow::bail!( @@ -95,7 +83,7 @@ pub fn resolve_std<'gctx>( std_ws.set_require_optional_deps(false); // `sysroot` is not in the default set because it is optional, but it needs // to be part of the resolve in case we do need it or `libtest`. - let mut spec_pkgs = Vec::from(crates); + let mut spec_pkgs: Vec = crates.iter().map(|s| s.to_string()).collect(); spec_pkgs.push("sysroot".to_string()); let spec = Packages::Packages(spec_pkgs); let specs = spec.to_package_id_specs(&std_ws)?; @@ -128,11 +116,13 @@ pub fn resolve_std<'gctx>( )) } -/// Generate a list of root `Unit`s for the standard library. +/// Generates a map of root units for the standard library for each kind requested. /// -/// The given slice of crate names is the root set. +/// * `crates` is the arg value from `-Zbuild-std`. +/// * `units` is the root units of the build. pub fn generate_std_roots( crates: &[String], + units: &[Unit], std_resolve: &Resolve, std_features: &ResolvedFeatures, kinds: &[CompileKind], @@ -141,8 +131,7 @@ pub fn generate_std_roots( profiles: &Profiles, target_data: &RustcTargetData<'_>, ) -> CargoResult>> { - // Generate the root Units for the standard library. - let std_ids = crates + let std_ids = std_crates(crates, Some(units)) .iter() .map(|crate_name| std_resolve.query(crate_name)) .collect::>>()?; diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 2f415c5a971..4e17898d6e0 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -759,7 +759,6 @@ unstable_cli_options!( avoid_dev_deps: bool = ("Avoid installing dev-dependencies if possible"), binary_dep_depinfo: bool = ("Track changes to dependency artifacts"), bindeps: bool = ("Allow Cargo packages to depend on bin, cdylib, and staticlib crates, and use the artifacts built by those crates"), - #[serde(deserialize_with = "deserialize_build_std")] build_std: Option> = ("Enable Cargo to compile the standard library itself as part of a crate graph compilation"), build_std_features: Option> = ("Configure features enabled for the standard library itself when building the standard library"), cargo_lints: bool = ("Enable the `[lints.cargo]` table"), @@ -873,19 +872,6 @@ const STABILIZED_LINTS: &str = "The `[lints]` table is now always available."; const STABILIZED_CHECK_CFG: &str = "Compile-time checking of conditional (a.k.a. `-Zcheck-cfg`) is now always enabled."; -fn deserialize_build_std<'de, D>(deserializer: D) -> Result>, D::Error> -where - D: serde::Deserializer<'de>, -{ - let Some(crates) = >>::deserialize(deserializer)? else { - return Ok(None); - }; - let v = crates.join(","); - Ok(Some( - crate::core::compiler::standard_lib::parse_unstable_flag(Some(&v)), - )) -} - #[derive(Debug, Copy, Clone, Default, Deserialize, Ord, PartialOrd, Eq, PartialEq)] #[serde(default)] pub struct GitFeatures { @@ -1257,9 +1243,7 @@ impl CliUnstable { "avoid-dev-deps" => self.avoid_dev_deps = parse_empty(k, v)?, "binary-dep-depinfo" => self.binary_dep_depinfo = parse_empty(k, v)?, "bindeps" => self.bindeps = parse_empty(k, v)?, - "build-std" => { - self.build_std = Some(crate::core::compiler::standard_lib::parse_unstable_flag(v)) - } + "build-std" => self.build_std = Some(parse_list(v)), "build-std-features" => self.build_std_features = Some(parse_list(v)), "cargo-lints" => self.cargo_lints = parse_empty(k, v)?, "codegen-backend" => self.codegen_backend = parse_empty(k, v)?, diff --git a/src/cargo/ops/cargo_compile/mod.rs b/src/cargo/ops/cargo_compile/mod.rs index d03e529be74..c1bc93800f4 100644 --- a/src/cargo/ops/cargo_compile/mod.rs +++ b/src/cargo/ops/cargo_compile/mod.rs @@ -398,10 +398,11 @@ pub fn create_bcx<'a, 'gctx>( Vec::new() }; - let std_roots = if let Some(crates) = standard_lib::std_crates(gctx, Some(&units)) { + let std_roots = if let Some(crates) = gctx.cli_unstable().build_std.as_ref() { let (std_resolve, std_features) = std_resolve_features.as_ref().unwrap(); standard_lib::generate_std_roots( &crates, + &units, std_resolve, std_features, &explicit_host_kinds, From 125e873dffc4b68b263c5decd88750ec10fd441e Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Wed, 4 Dec 2024 15:35:22 -0500 Subject: [PATCH 4/6] refactor(build-std): sysroot has everything we need for `Resolve` sysroot depends on `std`, `proc_macro`, and `test` [1], which includes everything we need from the default set of crates. Passing `sysroot` alone as spec should produce the same resolution. [1]: https://github.com/rust-lang/rust/blob/acabb5248231987ae1f0c215208d1005a5db402d/library/sysroot/Cargo.toml#L7-L11 --- src/cargo/core/compiler/standard_lib.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs index 3ca1c6c7a8d..377d5337f48 100644 --- a/src/cargo/core/compiler/standard_lib.rs +++ b/src/cargo/core/compiler/standard_lib.rs @@ -81,12 +81,10 @@ pub fn resolve_std<'gctx>( // `[dev-dependencies]`. No need for us to generate a `Resolve` which has // those included because we'll never use them anyway. std_ws.set_require_optional_deps(false); - // `sysroot` is not in the default set because it is optional, but it needs - // to be part of the resolve in case we do need it or `libtest`. - let mut spec_pkgs: Vec = crates.iter().map(|s| s.to_string()).collect(); - spec_pkgs.push("sysroot".to_string()); - let spec = Packages::Packages(spec_pkgs); - let specs = spec.to_package_id_specs(&std_ws)?; + // `sysroot` + the default feature set below should give us a good default + // Resolve, which includes `libtest` as well. + let specs = Packages::Packages(vec!["sysroot".into()]); + let specs = specs.to_package_id_specs(&std_ws)?; let features = match &gctx.cli_unstable().build_std_features { Some(list) => list.clone(), None => vec![ From 1cd370c2a2ddf341e5caba974f22a4711a8b0a51 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 5 Dec 2024 14:17:14 -0500 Subject: [PATCH 5/6] fix(build-std): remove std unsupported check Will let `std:bool` to determine necessary deps for `-Zbuild-std`, instead of erroring out. --- src/cargo/core/compiler/standard_lib.rs | 30 ++++++----------------- src/cargo/ops/cargo_compile/mod.rs | 4 ++-- src/cargo/ops/cargo_fetch.rs | 5 ++-- tests/testsuite/standard_lib.rs | 32 +++++++++++++++++++++---- 4 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs index 377d5337f48..013506a3810 100644 --- a/src/cargo/core/compiler/standard_lib.rs +++ b/src/cargo/core/compiler/standard_lib.rs @@ -15,7 +15,7 @@ use std::path::PathBuf; use super::BuildConfig; -fn std_crates<'a>(crates: &'a [String], units: Option<&[Unit]>) -> HashSet<&'a str> { +fn std_crates<'a>(crates: &'a [String], units: &[Unit]) -> HashSet<&'a str> { let mut crates = HashSet::from_iter(crates.iter().map(|s| s.as_str())); // This is a temporary hack until there is a more principled way to // declare dependencies in Cargo.toml. @@ -30,13 +30,11 @@ fn std_crates<'a>(crates: &'a [String], units: Option<&[Unit]>) -> HashSet<&'a s crates.insert("compiler_builtins"); // Only build libtest if it looks like it is needed (libtest depends on libstd) // If we know what units we're building, we can filter for libtest depending on the jobs. - if let Some(units) = units { - if units - .iter() - .any(|unit| unit.mode.is_rustc_test() && unit.target.harness()) - { - crates.insert("test"); - } + if units + .iter() + .any(|unit| unit.mode.is_rustc_test() && unit.target.harness()) + { + crates.insert("test"); } } else if crates.contains("core") { crates.insert("compiler_builtins"); @@ -50,27 +48,13 @@ pub fn resolve_std<'gctx>( ws: &Workspace<'gctx>, target_data: &mut RustcTargetData<'gctx>, build_config: &BuildConfig, - crates: &[String], ) -> CargoResult<(PackageSet<'gctx>, Resolve, ResolvedFeatures)> { - let crates = std_crates(crates, None); - if build_config.build_plan { ws.gctx() .shell() .warn("-Zbuild-std does not currently fully support --build-plan")?; } - // check that targets support building std - if crates.contains("std") { - let unsupported_targets = target_data.get_unsupported_std_targets(); - if !unsupported_targets.is_empty() { - anyhow::bail!( - "building std is not supported on the following targets: {}", - unsupported_targets.join(", ") - ) - } - } - let src_path = detect_sysroot_src_path(target_data)?; let std_ws_manifest_path = src_path.join("Cargo.toml"); let gctx = ws.gctx(); @@ -129,7 +113,7 @@ pub fn generate_std_roots( profiles: &Profiles, target_data: &RustcTargetData<'_>, ) -> CargoResult>> { - let std_ids = std_crates(crates, Some(units)) + let std_ids = std_crates(crates, units) .iter() .map(|crate_name| std_resolve.query(crate_name)) .collect::>>()?; diff --git a/src/cargo/ops/cargo_compile/mod.rs b/src/cargo/ops/cargo_compile/mod.rs index c1bc93800f4..4e011e7ec5a 100644 --- a/src/cargo/ops/cargo_compile/mod.rs +++ b/src/cargo/ops/cargo_compile/mod.rs @@ -289,9 +289,9 @@ pub fn create_bcx<'a, 'gctx>( resolved_features, } = resolve; - let std_resolve_features = if let Some(crates) = &gctx.cli_unstable().build_std { + let std_resolve_features = if gctx.cli_unstable().build_std.is_some() { let (std_package_set, std_resolve, std_features) = - standard_lib::resolve_std(ws, &mut target_data, &build_config, crates)?; + standard_lib::resolve_std(ws, &mut target_data, &build_config)?; pkg_set.add_set(std_package_set); Some((std_resolve, std_features)) } else { diff --git a/src/cargo/ops/cargo_fetch.rs b/src/cargo/ops/cargo_fetch.rs index 589bbf47812..b1e596f6485 100644 --- a/src/cargo/ops/cargo_fetch.rs +++ b/src/cargo/ops/cargo_fetch.rs @@ -64,9 +64,8 @@ pub fn fetch<'a>( } // If -Zbuild-std was passed, download dependencies for the standard library. - if let Some(crates) = gctx.cli_unstable().build_std.as_ref() { - let (std_package_set, _, _) = - standard_lib::resolve_std(ws, &mut data, &build_config, &crates)?; + if gctx.cli_unstable().build_std.is_some() { + let (std_package_set, _, _) = standard_lib::resolve_std(ws, &mut data, &build_config)?; packages.add_set(std_package_set); } diff --git a/tests/testsuite/standard_lib.rs b/tests/testsuite/standard_lib.rs index 214df036561..75237b16974 100644 --- a/tests/testsuite/standard_lib.rs +++ b/tests/testsuite/standard_lib.rs @@ -389,8 +389,29 @@ fn check_core() { .run(); } -#[cargo_test(build_std_mock)] -fn test_std_on_unsupported_target() { +#[cargo_test(build_std_mock, requires = "rustup")] +fn build_std_with_no_arg_for_core_only_target() { + let has_rustup_aarch64_unknown_none = std::process::Command::new("rustup") + .args(["target", "list", "--installed"]) + .output() + .ok() + .map(|output| { + String::from_utf8(output.stdout) + .map(|stdout| stdout.contains("aarch64-unknown-none")) + .unwrap_or_default() + }) + .unwrap_or_default(); + if !has_rustup_aarch64_unknown_none { + let msg = + "to run this test, run `rustup target add aarch64-unknown-none --toolchain nightly`"; + if cargo_util::is_ci() { + panic!("{msg}"); + } else { + eprintln!("{msg}"); + } + return; + } + let setup = setup(); let p = project() @@ -405,13 +426,14 @@ fn test_std_on_unsupported_target() { ) .build(); - p.cargo("build") + p.cargo("build -v") .arg("--target=aarch64-unknown-none") - .arg("--target=x86_64-unknown-none") .build_std(&setup) .with_status(101) .with_stderr_data(str![[r#" -[ERROR] building std is not supported on the following targets: [..] +... +error[E0463]: can't find crate for `std` +... "#]]) .run(); } From feb398a4423387adeb682d0aaa329d0ef769df4e Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 5 Dec 2024 15:27:06 -0500 Subject: [PATCH 6/6] fix(build-std): determine root crates by target spec `std:bool` In rust-lang/cargo#14183 Cargo starts bailing out if the `metadata.std` field in a target spec JSON is set to `false`. This is problematic because std for some targets are actually buildable even they've declared as std-unsupported. This patch removes the hard error, and instead determines the required root crates by the `metadata.std` field. That is to say, if a target is explicitly declared as `std: false`, `-Zbuild-std` will build `core` and `compiler-builtins` only, no `std` will be built. This patch doesn't change the behavior of `-Zbuild-std` with explicit crates set. For example `-Zbuild-std=std` will force building `std`. See Zulip discussion: https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/help.20debugging.20a.20docs.2Ers.20issue.20with.20a.20new.20cargo.20error --- .github/workflows/main.yml | 2 + src/cargo/core/compiler/standard_lib.rs | 67 ++++++++++++++++++----- tests/testsuite/standard_lib.rs | 72 ++++++++++++++++++++++--- 3 files changed, 121 insertions(+), 20 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7657db7b865..9b7fa428136 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -161,6 +161,8 @@ jobs: - run: rustup update --no-self-update stable - run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }} - run: rustup target add ${{ matrix.other }} + - run: rustup target add aarch64-unknown-none # need this for build-std mock tests + if: startsWith(matrix.rust, 'nightly') - run: rustup component add rustc-dev llvm-tools-preview rust-docs if: startsWith(matrix.rust, 'nightly') - run: sudo apt update -y && sudo apt install lldb gcc-multilib libsecret-1-0 libsecret-1-dev -y diff --git a/src/cargo/core/compiler/standard_lib.rs b/src/cargo/core/compiler/standard_lib.rs index 013506a3810..5e9fe6af494 100644 --- a/src/cargo/core/compiler/standard_lib.rs +++ b/src/cargo/core/compiler/standard_lib.rs @@ -15,12 +15,12 @@ use std::path::PathBuf; use super::BuildConfig; -fn std_crates<'a>(crates: &'a [String], units: &[Unit]) -> HashSet<&'a str> { +fn std_crates<'a>(crates: &'a [String], default: &'static str, units: &[Unit]) -> HashSet<&'a str> { let mut crates = HashSet::from_iter(crates.iter().map(|s| s.as_str())); // This is a temporary hack until there is a more principled way to // declare dependencies in Cargo.toml. if crates.is_empty() { - crates.insert("std"); + crates.insert(default); } if crates.contains("std") { crates.insert("core"); @@ -113,14 +113,52 @@ pub fn generate_std_roots( profiles: &Profiles, target_data: &RustcTargetData<'_>, ) -> CargoResult>> { - let std_ids = std_crates(crates, units) + // Generate a map of Units for each kind requested. + let mut ret = HashMap::new(); + let (core_only, maybe_std): (Vec<&CompileKind>, Vec<_>) = kinds.iter().partition(|kind| + // Only include targets that explicitly don't support std + target_data.info(**kind).supports_std == Some(false)); + for (default_crate, kinds) in [("core", core_only), ("std", maybe_std)] { + if kinds.is_empty() { + continue; + } + generate_roots( + &mut ret, + default_crate, + crates, + units, + std_resolve, + std_features, + &kinds, + package_set, + interner, + profiles, + target_data, + )?; + } + + Ok(ret) +} + +fn generate_roots( + ret: &mut HashMap>, + default: &'static str, + crates: &[String], + units: &[Unit], + std_resolve: &Resolve, + std_features: &ResolvedFeatures, + kinds: &[&CompileKind], + package_set: &PackageSet<'_>, + interner: &UnitInterner, + profiles: &Profiles, + target_data: &RustcTargetData<'_>, +) -> CargoResult<()> { + let std_ids = std_crates(crates, default, units) .iter() .map(|crate_name| std_resolve.query(crate_name)) .collect::>>()?; - // Convert PackageId to Package. let std_pkgs = package_set.get_many(std_ids)?; - // Generate a map of Units for each kind requested. - let mut ret = HashMap::new(); + for pkg in std_pkgs { let lib = pkg .targets() @@ -133,25 +171,26 @@ pub fn generate_std_roots( let mode = CompileMode::Build; let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev); for kind in kinds { - let list = ret.entry(*kind).or_insert_with(Vec::new); - let unit_for = UnitFor::new_normal(*kind); + let kind = **kind; + let list = ret.entry(kind).or_insert_with(Vec::new); + let unit_for = UnitFor::new_normal(kind); let profile = profiles.get_profile( pkg.package_id(), /*is_member*/ false, /*is_local*/ false, unit_for, - *kind, + kind, ); list.push(interner.intern( pkg, lib, profile, - *kind, + kind, mode, features.clone(), - target_data.info(*kind).rustflags.clone(), - target_data.info(*kind).rustdocflags.clone(), - target_data.target_config(*kind).links_overrides.clone(), + target_data.info(kind).rustflags.clone(), + target_data.info(kind).rustdocflags.clone(), + target_data.target_config(kind).links_overrides.clone(), /*is_std*/ true, /*dep_hash*/ 0, IsArtifact::No, @@ -159,7 +198,7 @@ pub fn generate_std_roots( )); } } - Ok(ret) + Ok(()) } fn detect_sysroot_src_path(target_data: &RustcTargetData<'_>) -> CargoResult { diff --git a/tests/testsuite/standard_lib.rs b/tests/testsuite/standard_lib.rs index 75237b16974..16645c17bce 100644 --- a/tests/testsuite/standard_lib.rs +++ b/tests/testsuite/standard_lib.rs @@ -429,12 +429,72 @@ fn build_std_with_no_arg_for_core_only_target() { p.cargo("build -v") .arg("--target=aarch64-unknown-none") .build_std(&setup) - .with_status(101) - .with_stderr_data(str![[r#" -... -error[E0463]: can't find crate for `std` -... -"#]]) + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[DOWNLOADING] crates ... +[DOWNLOADED] registry-dep-using-std v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] registry-dep-using-core v1.0.0 (registry `dummy-registry`) +[DOWNLOADED] registry-dep-using-alloc v1.0.0 (registry `dummy-registry`) +[COMPILING] compiler_builtins v0.1.0 ([..]/library/compiler_builtins) +[COMPILING] core v0.1.0 ([..]/library/core) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[RUNNING] `[..] rustc --crate-name compiler_builtins [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..] rustc --crate-name core [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..] rustc --crate-name foo [..]--target aarch64-unknown-none[..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) + .run(); + + p.cargo("clean").run(); + + // Also work for a mix of std and core-only targets, + // though not sure how common it is... + // + // Note that we don't download std dependencies for the second call + // because `-Zbuild-std` downloads them all also when building for core only. + p.cargo("build -v") + .arg("--target=aarch64-unknown-none") + .target_host() + .build_std(&setup) + .with_stderr_data( + str![[r#" +[UPDATING] `dummy-registry` index +[COMPILING] core v0.1.0 ([..]/library/core) +[COMPILING] dep_test v0.1.0 ([..]/dep_test) +[COMPILING] compiler_builtins v0.1.0 ([..]/library/compiler_builtins) +[COMPILING] proc_macro v0.1.0 ([..]/library/proc_macro) +[COMPILING] panic_unwind v0.1.0 ([..]/library/panic_unwind) +[COMPILING] rustc-std-workspace-core v1.9.0 ([..]/library/rustc-std-workspace-core) +[COMPILING] foo v0.0.1 ([ROOT]/foo) +[COMPILING] registry-dep-using-core v1.0.0 +[COMPILING] alloc v0.1.0 ([..]/library/alloc) +[COMPILING] rustc-std-workspace-alloc v1.9.0 ([..]/library/rustc-std-workspace-alloc) +[COMPILING] registry-dep-using-alloc v1.0.0 +[COMPILING] std v0.1.0 ([..]/library/std) +[RUNNING] `[..]rustc --crate-name compiler_builtins [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..]rustc --crate-name core [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..]rustc --crate-name foo [..]--target aarch64-unknown-none[..]` +[RUNNING] `[..]rustc --crate-name core [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name dep_test [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name proc_macro [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name panic_unwind [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name compiler_builtins [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name rustc_std_workspace_core [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name registry_dep_using_core [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name alloc [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name rustc_std_workspace_alloc [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name registry_dep_using_alloc [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name std [..]--target [HOST_TARGET][..]` +[RUNNING] `[..]rustc --crate-name foo [..]--target [HOST_TARGET][..]` +[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s + +"#]] + .unordered(), + ) .run(); }