@@ -14,7 +14,7 @@ use crate::util::context::{GlobalContext, StringList, TargetConfig};
1414use crate :: util:: interning:: InternedString ;
1515use crate :: util:: { CargoResult , Rustc } ;
1616use anyhow:: Context as _;
17- use cargo_platform:: { Cfg , CfgExpr } ;
17+ use cargo_platform:: { Cfg , CfgExpr , CheckCfg } ;
1818use cargo_util:: { ProcessBuilder , paths} ;
1919use serde:: { Deserialize , Serialize } ;
2020use std:: cell:: RefCell ;
@@ -43,6 +43,8 @@ pub struct TargetInfo {
4343 crate_types : RefCell < HashMap < CrateType , Option < ( String , String ) > > > ,
4444 /// `cfg` information extracted from `rustc --print=cfg`.
4545 cfg : Vec < Cfg > ,
46+ /// `check-cfg` informations extracted from `rustc --print=check-cfg`.
47+ check_cfg : Option < CheckCfg > ,
4648 /// `supports_std` information extracted from `rustc --print=target-spec-json`
4749 pub supports_std : Option < bool > ,
4850 /// Supported values for `-Csplit-debuginfo=` flag, queried from rustc
@@ -208,6 +210,14 @@ impl TargetInfo {
208210 process. arg ( "--print=crate-name" ) ; // `___` as a delimiter.
209211 process. arg ( "--print=cfg" ) ;
210212
213+ if gctx. cli_unstable ( ) . check_target_cfgs {
214+ process. arg ( "--print=crate-name" ) ; // `___` as a delimiter.
215+ process. arg ( "--print=check-cfg" ) ;
216+
217+ process. arg ( "--check-cfg=cfg()" ) ; // otherwise `--print=check-cfg` won't output
218+ process. arg ( "-Zunstable-options" ) ; // required by `--print=check-cfg`
219+ }
220+
211221 // parse_crate_type() relies on "unsupported/unknown crate type" error message,
212222 // so make warnings always emitted as warnings.
213223 process. arg ( "-Wwarnings" ) ;
@@ -261,16 +271,42 @@ impl TargetInfo {
261271 res
262272 } ;
263273
264- let cfg = lines
265- . map ( |line| Ok ( Cfg :: from_str ( line) ?) )
266- . filter ( TargetInfo :: not_user_specific_cfg)
267- . collect :: < CargoResult < Vec < _ > > > ( )
268- . with_context ( || {
269- format ! (
270- "failed to parse the cfg from `rustc --print=cfg`, got:\n {}" ,
271- output
272- )
273- } ) ?;
274+ let cfg = {
275+ let mut res = Vec :: new ( ) ;
276+ for line in & mut lines {
277+ // HACK: abuse `--print=crate-name` to use `___` as a delimiter.
278+ if line == "___" {
279+ break ;
280+ }
281+
282+ let cfg = Cfg :: from_str ( line) . with_context ( || {
283+ format ! (
284+ "failed to parse the cfg from `rustc --print=cfg`, got:\n {}" ,
285+ output
286+ )
287+ } ) ?;
288+ if TargetInfo :: not_user_specific_cfg ( & cfg) {
289+ res. push ( cfg) ;
290+ }
291+ }
292+ res
293+ } ;
294+
295+ let check_cfg = if gctx. cli_unstable ( ) . check_target_cfgs {
296+ let mut check_cfg = CheckCfg :: default ( ) ;
297+ check_cfg. exhaustive = true ;
298+
299+ for line in lines {
300+ check_cfg
301+ . parse_print_check_cfg_line ( line)
302+ . with_context ( || {
303+ format ! ( "unable to parse a line from `--print=check-cfg`" )
304+ } ) ?;
305+ }
306+ Some ( check_cfg)
307+ } else {
308+ None
309+ } ;
274310
275311 // recalculate `rustflags` from above now that we have `cfg`
276312 // information
@@ -356,14 +392,15 @@ impl TargetInfo {
356392 ) ?
357393 . into ( ) ,
358394 cfg,
395+ check_cfg,
359396 supports_std,
360397 support_split_debuginfo,
361398 } ) ;
362399 }
363400 }
364401
365- fn not_user_specific_cfg ( cfg : & CargoResult < Cfg > ) -> bool {
366- if let Ok ( Cfg :: Name ( cfg_name) ) = cfg {
402+ fn not_user_specific_cfg ( cfg : & Cfg ) -> bool {
403+ if let Cfg :: Name ( cfg_name) = cfg {
367404 // This should also include "debug_assertions", but it causes
368405 // regressions. Maybe some day in the distant future it can be
369406 // added (and possibly change the warning to an error).
@@ -379,6 +416,11 @@ impl TargetInfo {
379416 & self . cfg
380417 }
381418
419+ /// The [`CheckCfg`] settings.
420+ pub fn check_cfg ( & self ) -> & Option < CheckCfg > {
421+ & self . check_cfg
422+ }
423+
382424 /// Returns the list of file types generated by the given crate type.
383425 ///
384426 /// Returns `None` if the target does not support the given crate type.
0 commit comments