Skip to content

Commit

Permalink
Check build target supports std when building with -Zbuild-std=std
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
harmou01 committed Jul 3, 2024
1 parent a0b2803 commit a60fb6c
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 0 deletions.
51 changes: 51 additions & 0 deletions src/cargo/core/compiler/build_context/target_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ pub struct TargetInfo {
crate_types: RefCell<HashMap<CrateType, Option<(String, String)>>>,
/// `cfg` information extracted from `rustc --print=cfg`.
cfg: Vec<Cfg>,
/// `target_spec` information extracted from `rustc --print=target-spec-json`
pub target_spec: TargetSpec,
/// Supported values for `-Csplit-debuginfo=` flag, queried from rustc
support_split_debuginfo: Vec<String>,
/// Path to the sysroot.
Expand All @@ -62,6 +64,16 @@ pub struct TargetInfo {
pub support_check_cfg: bool,
}

#[derive(Deserialize, Clone)]
pub struct Metadata {
pub std: Option<bool>,
}

#[derive(Deserialize, Clone)]
pub struct TargetSpec {
pub metadata: Metadata,
}

/// Kind of each file generated by a Unit, part of `FileType`.
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum FileFlavor {
Expand Down Expand Up @@ -175,9 +187,11 @@ impl TargetInfo {
let mut process = rustc.workspace_process();
apply_env_config(gctx, &mut process)?;
process
.env("RUSTC_BOOTSTRAP", &"1".to_string())
.arg("-")
.arg("--crate-name")
.arg("___")
.arg("-Zunstable-options")
.arg("--print=file-names")
.args(&rustflags)
.env_remove("RUSTC_LOG");
Expand Down Expand Up @@ -215,6 +229,7 @@ impl TargetInfo {
process.arg("--print=sysroot");
process.arg("--print=split-debuginfo");
process.arg("--print=crate-name"); // `___` as a delimiter.
process.arg("--print=target-spec-json");
process.arg("--print=cfg");

let (output, error) = rustc
Expand Down Expand Up @@ -266,6 +281,36 @@ impl TargetInfo {
res
};

let target_spec_json = {
let mut res: String = String::new();
loop {
match lines.next() {
Some(line) if line == "}" => {
res.push_str("}");
break;
}
Some(line) => res.push_str(line.into()),
None => {
return error_missing_print_output(
"target-spec-json",
&process,
&output,
&error,
)
}
}
}
res
};

let target_spec: TargetSpec = serde_json::from_str(&target_spec_json.as_str())
.with_context(|| {
format!(
"failed to parse target spec from `rustc --print=target-spec-json`, got:\n{}",
output
)
})?;

let cfg = lines
.map(|line| Ok(Cfg::from_str(line)?))
.filter(TargetInfo::not_user_specific_cfg)
Expand Down Expand Up @@ -322,6 +367,7 @@ impl TargetInfo {
Flags::Rustdoc,
)?,
cfg,
target_spec,
support_split_debuginfo,
support_check_cfg,
});
Expand Down Expand Up @@ -1026,6 +1072,11 @@ impl<'gctx> RustcTargetData<'gctx> {
pub fn script_override(&self, lib_name: &str, kind: CompileKind) -> Option<&BuildOutput> {
self.target_config(kind).links_overrides.get(lib_name)
}

/// Gets the target info hashmap from the target data.
pub fn target_info(&self) -> &HashMap<CompileTarget, TargetInfo> {
&self.target_info
}
}

/// Structure used to deal with Rustdoc fingerprinting
Expand Down
12 changes: 12 additions & 0 deletions src/cargo/core/compiler/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,18 @@ pub fn resolve_std<'gctx>(
.warn("-Zbuild-std does not currently fully support --build-plan")?;
}

// check that targets support building std
if crates.contains(&"std".to_string()) {
for (target, target_info) in target_data.target_info() {
if target_info.target_spec.metadata.std == Some(false) {
return Err(anyhow::Error::msg(format!(
"building std is not supported on this target: {:?}",
target.short_name()
)));
}
}
}

let src_path = detect_sysroot_src_path(target_data)?;
let to_patch = [
"rustc-std-workspace-core",
Expand Down

0 comments on commit a60fb6c

Please sign in to comment.