Skip to content

Commit

Permalink
fix(build-std): determining root crates by target spec std:bool
Browse files Browse the repository at this point in the history
In rust-lang#14183 Cargo start erroring out if the `metadata.std`
field in a target spet 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 no change the behavior of `-Zbuild-std` with explict
crates set. For example `-Zbuild-std=std` will force to build `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
  • Loading branch information
weihanglo committed Dec 5, 2024
1 parent 1249d09 commit ef2a6ed
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 29 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
81 changes: 58 additions & 23 deletions src/cargo/core/compiler/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,31 +116,65 @@ pub fn generate_std_roots(
profiles: &Profiles,
target_data: &RustcTargetData<'_>,
) -> CargoResult<HashMap<CompileKind, Vec<Unit>>> {
let std_ids = std_crates(crates, Some(units))
.iter()
.map(|crate_name| std_resolve.query(crate_name))
.collect::<CargoResult<Vec<PackageId>>>()?;
// Convert PackageId to Package.
let std_pkgs = package_set.get_many(std_ids)?;
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));
let std_pkgs = if maybe_std.is_empty() {
None
} else {
let pkg_ids = std_crates(crates, Some(units))
.iter()
.map(|crate_name| std_resolve.query(crate_name))
.collect::<CargoResult<Vec<PackageId>>>()?;
Some(package_set.get_many(pkg_ids)?)
};
let core_pkgs = if core_only.is_empty() {
None
} else {
let crates = if crates.is_empty() {
&["core".to_string()]
} else {
crates
};
let pkg_ids = std_crates(crates, Some(units))
.iter()
.map(|crate_name| std_resolve.query(crate_name))
.collect::<CargoResult<Vec<PackageId>>>()?;
Some(package_set.get_many(pkg_ids)?)
};

// Generate a map of Units for each kind requested.
let mut ret = HashMap::new();
gather_roots(
&mut ret,
&std_pkgs,
std_features,
kinds,
interner,
profiles,
target_data,
);
if let Some(pkgs) = std_pkgs {
gather_roots(
&mut ret,
&pkgs,
std_features,
&maybe_std,
interner,
profiles,
target_data,
);
}
if let Some(pkgs) = core_pkgs {
gather_roots(
&mut ret,
&pkgs,
std_features,
&core_only,
interner,
profiles,
target_data,
);
}
Ok(ret)
}

fn gather_roots(
ret: &mut HashMap<CompileKind, Vec<Unit>>,
pkgs: &[&Package],
std_features: &ResolvedFeatures,
kinds: &[CompileKind],
kinds: &[&CompileKind],
interner: &UnitInterner,
profiles: &Profiles,
target_data: &RustcTargetData<'_>,
Expand All @@ -157,25 +191,26 @@ fn gather_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,
Expand Down
72 changes: 66 additions & 6 deletions tests/testsuite/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,12 +425,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();
}

Expand Down

0 comments on commit ef2a6ed

Please sign in to comment.