diff --git a/src/cargo/core/compiler/build_context/target_info.rs b/src/cargo/core/compiler/build_context/target_info.rs index 042d4de26c6..33e0461ca36 100644 --- a/src/cargo/core/compiler/build_context/target_info.rs +++ b/src/cargo/core/compiler/build_context/target_info.rs @@ -14,7 +14,7 @@ use crate::util::context::{GlobalContext, StringList, TargetConfig}; use crate::util::interning::InternedString; use crate::util::{CargoResult, Rustc}; use anyhow::Context as _; -use cargo_platform::{Cfg, CfgExpr}; +use cargo_platform::{Cfg, CfgExpr, CheckCfg}; use cargo_util::{paths, ProcessBuilder}; use serde::{Deserialize, Serialize}; use std::cell::RefCell; @@ -43,6 +43,8 @@ pub struct TargetInfo { crate_types: RefCell>>, /// `cfg` information extracted from `rustc --print=cfg`. cfg: Vec, + /// `CheckCfg` informations extracted from `rustc --print=check-cfg`. + check_cfg: Option, /// Supported values for `-Csplit-debuginfo=` flag, queried from rustc support_split_debuginfo: Vec, /// Path to the sysroot. @@ -204,6 +206,14 @@ impl TargetInfo { process.arg("--print=crate-name"); // `___` as a delimiter. process.arg("--print=cfg"); + if gctx.cli_unstable().check_target_cfgs { + process.arg("--print=crate-name"); // `___` as a delimiter. + process.arg("--print=check-cfg"); + + process.arg("--check-cfg=cfg()"); // otherwise `--print=check-cfg` won't output + process.arg("-Zunstable-options"); // required by `--print=check-cfg` + } + let (output, error) = rustc .cached_output(&process, extra_fingerprint) .with_context(|| { @@ -256,6 +266,11 @@ impl TargetInfo { let cfg = { let mut res = Vec::new(); for line in &mut lines { + // HACK: abuse `--print=crate-name` to use `___` as a delimiter. + if line == "___" { + break; + } + let cfg = Cfg::from_str(line).with_context(|| { format!( "failed to parse the cfg from `rustc --print=cfg`, got:\n{}", @@ -269,6 +284,22 @@ impl TargetInfo { res }; + let check_cfg = if gctx.cli_unstable().check_target_cfgs { + let mut check_cfg = CheckCfg::default(); + check_cfg.exhaustive = true; + + for line in lines { + check_cfg + .parse_print_check_cfg_line(line) + .with_context(|| { + format!("unable to parse a line from `--print=check-cfg`") + })?; + } + Some(check_cfg) + } else { + None + }; + // recalculate `rustflags` from above now that we have `cfg` // information let new_flags = extra_args( @@ -315,6 +346,7 @@ impl TargetInfo { )? .into(), cfg, + check_cfg, support_split_debuginfo, }); } @@ -337,6 +369,11 @@ impl TargetInfo { &self.cfg } + /// The [`CheckCfg`] settings. + pub fn check_cfg(&self) -> &Option { + &self.check_cfg + } + /// Returns the list of file types generated by the given crate type. /// /// Returns `None` if the target does not support the given crate type.