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.

Cargo will now emit a warning if the requested target does not support
building the standard library, or if there was an issue when collecting
the necessary information via rustc
  • Loading branch information
harmou01 committed Oct 14, 2024
1 parent 82c489f commit e93004f
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 1 deletion.
52 changes: 51 additions & 1 deletion src/cargo/core/compiler/build_context/target_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::core::compiler::{BuildRunner, CompileKind, CompileMode, CompileTarget
use crate::core::{Dependency, Package, Target, TargetKind, Workspace};
use crate::util::context::{GlobalContext, StringList, TargetConfig};
use crate::util::interning::InternedString;
use crate::util::{CargoResult, Rustc};
use crate::util::{CargoResult, Rustc, VersionExt};
use anyhow::Context as _;
use cargo_platform::{Cfg, CfgExpr};
use cargo_util::{paths, ProcessBuilder};
Expand Down Expand Up @@ -43,6 +43,8 @@ pub struct TargetInfo {
crate_types: RefCell<HashMap<CrateType, Option<(String, String)>>>,
/// `cfg` information extracted from `rustc --print=cfg`.
cfg: Vec<Cfg>,
/// `supports_std` information extracted from `rustc --print=target-spec-json`
pub supports_std: Option<bool>,
/// Supported values for `-Csplit-debuginfo=` flag, queried from rustc
support_split_debuginfo: Vec<String>,
/// Path to the sysroot.
Expand All @@ -56,6 +58,16 @@ pub struct TargetInfo {
pub rustdocflags: Rc<[String]>,
}

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

#[derive(Deserialize)]
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 @@ -294,6 +306,38 @@ impl TargetInfo {
gctx.shell().warn("non-trivial mutual dependency between target-specific configuration and RUSTFLAGS")?;
}

let mut supports_std: Option<bool> = None;

// The '--print=target-spec-json' is an unstable option of rustc, therefore if
// rustc is not a 'Prerelease' build, it's safe to assume that we cannot fetch
// the target-spec-json. So don't bother trying.
if rustc.version.is_prerelease() {
let mut target_spec_process = rustc.workspace_process();
apply_env_config(gctx, &mut target_spec_process)?;
target_spec_process
.arg("--print=target-spec-json")
.arg("-Zunstable-options")
.args(&rustflags)
.env_remove("RUSTC_LOG");

if let CompileKind::Target(target) = kind {
target_spec_process
.arg("--target")
.arg(target.rustc_target());
}

let (target_spec_output, _) =
rustc.cached_output(&target_spec_process, extra_fingerprint)?;

match serde_json::from_str(&target_spec_output.as_str()) {
Result::Ok(val) => {
let target_spec: TargetSpec = val;
supports_std = target_spec.metadata.std;
}
Result::Err(_) => (),
}
}

return Ok(TargetInfo {
crate_type_process,
crate_types: RefCell::new(map),
Expand All @@ -310,6 +354,7 @@ impl TargetInfo {
)?
.into(),
cfg,
supports_std,
support_split_debuginfo,
});
}
Expand Down Expand Up @@ -1026,6 +1071,11 @@ impl<'gctx> RustcTargetData<'gctx> {
CompileKind::Target(s) => &self.target_config[&s],
}
}

/// 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 @@ -72,6 +72,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.supports_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 std_ws_manifest_path = src_path.join("Cargo.toml");
let gctx = ws.gctx();
Expand Down

0 comments on commit e93004f

Please sign in to comment.