Skip to content

Commit f25bf82

Browse files
committed
fix(build-std): determine root crates by target spec std:bool
In #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
1 parent d1e38ce commit f25bf82

File tree

3 files changed

+126
-27
lines changed

3 files changed

+126
-27
lines changed

.github/workflows/main.yml

+2
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ jobs:
161161
- run: rustup update --no-self-update stable
162162
- run: rustup update --no-self-update ${{ matrix.rust }} && rustup default ${{ matrix.rust }}
163163
- run: rustup target add ${{ matrix.other }}
164+
- run: rustup target add aarch64-unknown-none # need this for build-std mock tests
165+
if: startsWith(matrix.rust, 'nightly')
164166
- run: rustup component add rustc-dev llvm-tools-preview rust-docs
165167
if: startsWith(matrix.rust, 'nightly')
166168
- run: sudo apt update -y && sudo apt install lldb gcc-multilib libsecret-1-0 libsecret-1-dev -y

src/cargo/core/compiler/standard_lib.rs

+58-21
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ use std::path::PathBuf;
1515

1616
use super::BuildConfig;
1717

18-
fn std_crates<'a>(crates: &'a [String], units: Option<&[Unit]>) -> HashSet<&'a str> {
18+
fn std_crates<'a>(crates: &'a [String], default: &'static str, units: &[Unit]) -> HashSet<&'a str> {
1919
let mut crates = HashSet::from_iter(crates.iter().map(|s| s.as_str()));
2020
// This is a temporary hack until there is a more principled way to
2121
// declare dependencies in Cargo.toml.
2222
if crates.is_empty() {
23-
crates.insert("std");
23+
crates.insert(default);
2424
}
2525
if crates.contains("std") {
2626
crates.insert("core");
@@ -30,13 +30,11 @@ fn std_crates<'a>(crates: &'a [String], units: Option<&[Unit]>) -> HashSet<&'a s
3030
crates.insert("compiler_builtins");
3131
// Only build libtest if it looks like it is needed (libtest depends on libstd)
3232
// If we know what units we're building, we can filter for libtest depending on the jobs.
33-
if let Some(units) = units {
34-
if units
35-
.iter()
36-
.any(|unit| unit.mode.is_rustc_test() && unit.target.harness())
37-
{
38-
crates.insert("test");
39-
}
33+
if units
34+
.iter()
35+
.any(|unit| unit.mode.is_rustc_test() && unit.target.harness())
36+
{
37+
crates.insert("test");
4038
}
4139
} else if crates.contains("core") {
4240
crates.insert("compiler_builtins");
@@ -115,14 +113,52 @@ pub fn generate_std_roots(
115113
profiles: &Profiles,
116114
target_data: &RustcTargetData<'_>,
117115
) -> CargoResult<HashMap<CompileKind, Vec<Unit>>> {
118-
let std_ids = std_crates(crates, Some(units))
116+
// Generate a map of Units for each kind requested.
117+
let mut ret = HashMap::new();
118+
let (core_only, maybe_std): (Vec<&CompileKind>, Vec<_>) = kinds.iter().partition(|kind|
119+
// Only include targets that explicitly don't support std
120+
target_data.info(**kind).supports_std == Some(false));
121+
for (default_crate, kinds) in [("core", core_only), ("std", maybe_std)] {
122+
if kinds.is_empty() {
123+
continue;
124+
}
125+
generate_roots(
126+
&mut ret,
127+
default_crate,
128+
crates,
129+
units,
130+
std_resolve,
131+
std_features,
132+
&kinds,
133+
package_set,
134+
interner,
135+
profiles,
136+
target_data,
137+
)?;
138+
}
139+
140+
Ok(ret)
141+
}
142+
143+
fn generate_roots(
144+
ret: &mut HashMap<CompileKind, Vec<Unit>>,
145+
default: &'static str,
146+
crates: &[String],
147+
units: &[Unit],
148+
std_resolve: &Resolve,
149+
std_features: &ResolvedFeatures,
150+
kinds: &[&CompileKind],
151+
package_set: &PackageSet<'_>,
152+
interner: &UnitInterner,
153+
profiles: &Profiles,
154+
target_data: &RustcTargetData<'_>,
155+
) -> CargoResult<()> {
156+
let std_ids = std_crates(crates, default, units)
119157
.iter()
120158
.map(|crate_name| std_resolve.query(crate_name))
121159
.collect::<CargoResult<Vec<PackageId>>>()?;
122-
// Convert PackageId to Package.
123160
let std_pkgs = package_set.get_many(std_ids)?;
124-
// Generate a map of Units for each kind requested.
125-
let mut ret = HashMap::new();
161+
126162
for pkg in std_pkgs {
127163
let lib = pkg
128164
.targets()
@@ -135,33 +171,34 @@ pub fn generate_std_roots(
135171
let mode = CompileMode::Build;
136172
let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);
137173
for kind in kinds {
138-
let list = ret.entry(*kind).or_insert_with(Vec::new);
139-
let unit_for = UnitFor::new_normal(*kind);
174+
let kind = **kind;
175+
let list = ret.entry(kind).or_insert_with(Vec::new);
176+
let unit_for = UnitFor::new_normal(kind);
140177
let profile = profiles.get_profile(
141178
pkg.package_id(),
142179
/*is_member*/ false,
143180
/*is_local*/ false,
144181
unit_for,
145-
*kind,
182+
kind,
146183
);
147184
list.push(interner.intern(
148185
pkg,
149186
lib,
150187
profile,
151-
*kind,
188+
kind,
152189
mode,
153190
features.clone(),
154-
target_data.info(*kind).rustflags.clone(),
155-
target_data.info(*kind).rustdocflags.clone(),
156-
target_data.target_config(*kind).links_overrides.clone(),
191+
target_data.info(kind).rustflags.clone(),
192+
target_data.info(kind).rustdocflags.clone(),
193+
target_data.target_config(kind).links_overrides.clone(),
157194
/*is_std*/ true,
158195
/*dep_hash*/ 0,
159196
IsArtifact::No,
160197
None,
161198
));
162199
}
163200
}
164-
Ok(ret)
201+
Ok(())
165202
}
166203

167204
fn detect_sysroot_src_path(target_data: &RustcTargetData<'_>) -> CargoResult<PathBuf> {

tests/testsuite/standard_lib.rs

+66-6
Original file line numberDiff line numberDiff line change
@@ -429,12 +429,72 @@ fn build_std_with_no_arg_for_core_only_target() {
429429
p.cargo("build -v")
430430
.arg("--target=aarch64-unknown-none")
431431
.build_std(&setup)
432-
.with_status(101)
433-
.with_stderr_data(str![[r#"
434-
...
435-
error[E0463]: can't find crate for `std`
436-
...
437-
"#]])
432+
.with_stderr_data(
433+
str![[r#"
434+
[UPDATING] `dummy-registry` index
435+
[DOWNLOADING] crates ...
436+
[DOWNLOADED] registry-dep-using-std v1.0.0 (registry `dummy-registry`)
437+
[DOWNLOADED] registry-dep-using-core v1.0.0 (registry `dummy-registry`)
438+
[DOWNLOADED] registry-dep-using-alloc v1.0.0 (registry `dummy-registry`)
439+
[COMPILING] compiler_builtins v0.1.0 ([..]/library/compiler_builtins)
440+
[COMPILING] core v0.1.0 ([..]/library/core)
441+
[COMPILING] foo v0.0.1 ([ROOT]/foo)
442+
[RUNNING] `[..] rustc --crate-name compiler_builtins [..]--target aarch64-unknown-none[..]`
443+
[RUNNING] `[..] rustc --crate-name core [..]--target aarch64-unknown-none[..]`
444+
[RUNNING] `[..] rustc --crate-name foo [..]--target aarch64-unknown-none[..]`
445+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
446+
447+
"#]]
448+
.unordered(),
449+
)
450+
.run();
451+
452+
p.cargo("clean").run();
453+
454+
// Also work for a mix of std and core-only targets,
455+
// though not sure how common it is...
456+
//
457+
// Note that we don't download std dependencies for the second call
458+
// because `-Zbuild-std` downloads them all also when building for core only.
459+
p.cargo("build -v")
460+
.arg("--target=aarch64-unknown-none")
461+
.target_host()
462+
.build_std(&setup)
463+
.with_stderr_data(
464+
str![[r#"
465+
[UPDATING] `dummy-registry` index
466+
[COMPILING] core v0.1.0 ([..]/library/core)
467+
[COMPILING] dep_test v0.1.0 ([..]/dep_test)
468+
[COMPILING] compiler_builtins v0.1.0 ([..]/library/compiler_builtins)
469+
[COMPILING] proc_macro v0.1.0 ([..]/library/proc_macro)
470+
[COMPILING] panic_unwind v0.1.0 ([..]/library/panic_unwind)
471+
[COMPILING] rustc-std-workspace-core v1.9.0 ([..]/library/rustc-std-workspace-core)
472+
[COMPILING] foo v0.0.1 ([ROOT]/foo)
473+
[COMPILING] registry-dep-using-core v1.0.0
474+
[COMPILING] alloc v0.1.0 ([..]/library/alloc)
475+
[COMPILING] rustc-std-workspace-alloc v1.9.0 ([..]/library/rustc-std-workspace-alloc)
476+
[COMPILING] registry-dep-using-alloc v1.0.0
477+
[COMPILING] std v0.1.0 ([..]/library/std)
478+
[RUNNING] `[..]rustc --crate-name compiler_builtins [..]--target aarch64-unknown-none[..]`
479+
[RUNNING] `[..]rustc --crate-name core [..]--target aarch64-unknown-none[..]`
480+
[RUNNING] `[..]rustc --crate-name foo [..]--target aarch64-unknown-none[..]`
481+
[RUNNING] `[..]rustc --crate-name core [..]--target [HOST_TARGET][..]`
482+
[RUNNING] `[..]rustc --crate-name dep_test [..]--target [HOST_TARGET][..]`
483+
[RUNNING] `[..]rustc --crate-name proc_macro [..]--target [HOST_TARGET][..]`
484+
[RUNNING] `[..]rustc --crate-name panic_unwind [..]--target [HOST_TARGET][..]`
485+
[RUNNING] `[..]rustc --crate-name compiler_builtins [..]--target [HOST_TARGET][..]`
486+
[RUNNING] `[..]rustc --crate-name rustc_std_workspace_core [..]--target [HOST_TARGET][..]`
487+
[RUNNING] `[..]rustc --crate-name registry_dep_using_core [..]--target [HOST_TARGET][..]`
488+
[RUNNING] `[..]rustc --crate-name alloc [..]--target [HOST_TARGET][..]`
489+
[RUNNING] `[..]rustc --crate-name rustc_std_workspace_alloc [..]--target [HOST_TARGET][..]`
490+
[RUNNING] `[..]rustc --crate-name registry_dep_using_alloc [..]--target [HOST_TARGET][..]`
491+
[RUNNING] `[..]rustc --crate-name std [..]--target [HOST_TARGET][..]`
492+
[RUNNING] `[..]rustc --crate-name foo [..]--target [HOST_TARGET][..]`
493+
[FINISHED] `dev` profile [unoptimized + debuginfo] target(s) in [ELAPSED]s
494+
495+
"#]]
496+
.unordered(),
497+
)
438498
.run();
439499
}
440500

0 commit comments

Comments
 (0)