Skip to content

Commit a60fb6c

Browse files
committed
Check build target supports std when building with -Zbuild-std=std
Running cargo with "-Zbuild-std=std" should check whether the build target supports building the standard library. This information can be obtained from rustc with the target-spec-json "--print" option. When 'std' is false for the build target, cargo should not attempt to build the standard library. This avoids the "use of unstable library" errors, as this check is performed before Cargo starts trying to build restricted_std code.
1 parent a0b2803 commit a60fb6c

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

src/cargo/core/compiler/build_context/target_info.rs

+51
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ pub struct TargetInfo {
4444
crate_types: RefCell<HashMap<CrateType, Option<(String, String)>>>,
4545
/// `cfg` information extracted from `rustc --print=cfg`.
4646
cfg: Vec<Cfg>,
47+
/// `target_spec` information extracted from `rustc --print=target-spec-json`
48+
pub target_spec: TargetSpec,
4749
/// Supported values for `-Csplit-debuginfo=` flag, queried from rustc
4850
support_split_debuginfo: Vec<String>,
4951
/// Path to the sysroot.
@@ -62,6 +64,16 @@ pub struct TargetInfo {
6264
pub support_check_cfg: bool,
6365
}
6466

67+
#[derive(Deserialize, Clone)]
68+
pub struct Metadata {
69+
pub std: Option<bool>,
70+
}
71+
72+
#[derive(Deserialize, Clone)]
73+
pub struct TargetSpec {
74+
pub metadata: Metadata,
75+
}
76+
6577
/// Kind of each file generated by a Unit, part of `FileType`.
6678
#[derive(Clone, PartialEq, Eq, Debug)]
6779
pub enum FileFlavor {
@@ -175,9 +187,11 @@ impl TargetInfo {
175187
let mut process = rustc.workspace_process();
176188
apply_env_config(gctx, &mut process)?;
177189
process
190+
.env("RUSTC_BOOTSTRAP", &"1".to_string())
178191
.arg("-")
179192
.arg("--crate-name")
180193
.arg("___")
194+
.arg("-Zunstable-options")
181195
.arg("--print=file-names")
182196
.args(&rustflags)
183197
.env_remove("RUSTC_LOG");
@@ -215,6 +229,7 @@ impl TargetInfo {
215229
process.arg("--print=sysroot");
216230
process.arg("--print=split-debuginfo");
217231
process.arg("--print=crate-name"); // `___` as a delimiter.
232+
process.arg("--print=target-spec-json");
218233
process.arg("--print=cfg");
219234

220235
let (output, error) = rustc
@@ -266,6 +281,36 @@ impl TargetInfo {
266281
res
267282
};
268283

284+
let target_spec_json = {
285+
let mut res: String = String::new();
286+
loop {
287+
match lines.next() {
288+
Some(line) if line == "}" => {
289+
res.push_str("}");
290+
break;
291+
}
292+
Some(line) => res.push_str(line.into()),
293+
None => {
294+
return error_missing_print_output(
295+
"target-spec-json",
296+
&process,
297+
&output,
298+
&error,
299+
)
300+
}
301+
}
302+
}
303+
res
304+
};
305+
306+
let target_spec: TargetSpec = serde_json::from_str(&target_spec_json.as_str())
307+
.with_context(|| {
308+
format!(
309+
"failed to parse target spec from `rustc --print=target-spec-json`, got:\n{}",
310+
output
311+
)
312+
})?;
313+
269314
let cfg = lines
270315
.map(|line| Ok(Cfg::from_str(line)?))
271316
.filter(TargetInfo::not_user_specific_cfg)
@@ -322,6 +367,7 @@ impl TargetInfo {
322367
Flags::Rustdoc,
323368
)?,
324369
cfg,
370+
target_spec,
325371
support_split_debuginfo,
326372
support_check_cfg,
327373
});
@@ -1026,6 +1072,11 @@ impl<'gctx> RustcTargetData<'gctx> {
10261072
pub fn script_override(&self, lib_name: &str, kind: CompileKind) -> Option<&BuildOutput> {
10271073
self.target_config(kind).links_overrides.get(lib_name)
10281074
}
1075+
1076+
/// Gets the target info hashmap from the target data.
1077+
pub fn target_info(&self) -> &HashMap<CompileTarget, TargetInfo> {
1078+
&self.target_info
1079+
}
10291080
}
10301081

10311082
/// Structure used to deal with Rustdoc fingerprinting

src/cargo/core/compiler/standard_lib.rs

+12
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ pub fn resolve_std<'gctx>(
7373
.warn("-Zbuild-std does not currently fully support --build-plan")?;
7474
}
7575

76+
// check that targets support building std
77+
if crates.contains(&"std".to_string()) {
78+
for (target, target_info) in target_data.target_info() {
79+
if target_info.target_spec.metadata.std == Some(false) {
80+
return Err(anyhow::Error::msg(format!(
81+
"building std is not supported on this target: {:?}",
82+
target.short_name()
83+
)));
84+
}
85+
}
86+
}
87+
7688
let src_path = detect_sysroot_src_path(target_data)?;
7789
let to_patch = [
7890
"rustc-std-workspace-core",

0 commit comments

Comments
 (0)