33mod cargo_workspace;
44mod project_json;
55mod sysroot;
6+ mod cfg_flag;
67
78use std:: {
89 fs:: { self , read_dir, ReadDir } ,
910 io,
10- process:: { Command , Output } ,
11+ process:: Command ,
1112} ;
1213
1314use anyhow:: { bail, Context , Result } ;
1415use paths:: { AbsPath , AbsPathBuf } ;
1516use ra_cfg:: CfgOptions ;
1617use ra_db:: { CrateGraph , CrateId , CrateName , Edition , Env , FileId } ;
1718use rustc_hash:: { FxHashMap , FxHashSet } ;
18- use stdx:: split_delim;
19+
20+ use crate :: cfg_flag:: CfgFlag ;
1921
2022pub use crate :: {
2123 cargo_workspace:: { CargoConfig , CargoWorkspace , Package , Target , TargetKind } ,
2224 project_json:: { ProjectJson , ProjectJsonData } ,
2325 sysroot:: Sysroot ,
2426} ;
27+
2528pub use ra_proc_macro:: ProcMacroClient ;
2629
2730#[ derive( Debug , Clone , Eq , PartialEq ) ]
@@ -250,7 +253,7 @@ impl ProjectWorkspace {
250253 let mut crate_graph = CrateGraph :: default ( ) ;
251254 match self {
252255 ProjectWorkspace :: Json { project } => {
253- let mut target_cfg_map = FxHashMap :: < Option < & str > , CfgOptions > :: default ( ) ;
256+ let mut cfg_cache : FxHashMap < Option < & str > , Vec < CfgFlag > > = FxHashMap :: default ( ) ;
254257 let crates: FxHashMap < _ , _ > = project
255258 . crates
256259 . iter ( )
@@ -266,11 +269,12 @@ impl ProjectWorkspace {
266269 . map ( |it| proc_macro_client. by_dylib_path ( & it) ) ;
267270
268271 let target = krate. target . as_deref ( ) . or ( target) ;
269- let target_cfgs = target_cfg_map
270- . entry ( target. clone ( ) )
271- . or_insert_with ( || get_rustc_cfg_options ( target. as_deref ( ) ) ) ;
272- let mut cfg_options = krate. cfg . clone ( ) ;
273- cfg_options. append ( target_cfgs) ;
272+ let target_cfgs = cfg_cache
273+ . entry ( target)
274+ . or_insert_with ( || get_rustc_cfg_options ( target) ) ;
275+
276+ let mut cfg_options = CfgOptions :: default ( ) ;
277+ cfg_options. extend ( target_cfgs. iter ( ) . chain ( krate. cfg . iter ( ) ) . cloned ( ) ) ;
274278
275279 // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env
276280 Some ( (
@@ -307,7 +311,8 @@ impl ProjectWorkspace {
307311 }
308312 }
309313 ProjectWorkspace :: Cargo { cargo, sysroot } => {
310- let mut cfg_options = get_rustc_cfg_options ( target) ;
314+ let mut cfg_options = CfgOptions :: default ( ) ;
315+ cfg_options. extend ( get_rustc_cfg_options ( target) ) ;
311316
312317 let sysroot_crates: FxHashMap < _ , _ > = sysroot
313318 . crates ( )
@@ -354,6 +359,7 @@ impl ProjectWorkspace {
354359
355360 // Add test cfg for non-sysroot crates
356361 cfg_options. insert_atom ( "test" . into ( ) ) ;
362+ cfg_options. insert_atom ( "debug_assertions" . into ( ) ) ;
357363
358364 // Next, create crates for each package, target pair
359365 for pkg in cargo. packages ( ) {
@@ -367,15 +373,7 @@ impl ProjectWorkspace {
367373 for feature in cargo[ pkg] . features . iter ( ) {
368374 opts. insert_key_value ( "feature" . into ( ) , feature. into ( ) ) ;
369375 }
370- for cfg in cargo[ pkg] . cfgs . iter ( ) {
371- match cfg. find ( '=' ) {
372- Some ( split) => opts. insert_key_value (
373- cfg[ ..split] . into ( ) ,
374- cfg[ split + 1 ..] . trim_matches ( '"' ) . into ( ) ,
375- ) ,
376- None => opts. insert_atom ( cfg. into ( ) ) ,
377- } ;
378- }
376+ opts. extend ( cargo[ pkg] . cfgs . iter ( ) . cloned ( ) ) ;
379377 opts
380378 } ;
381379 let mut env = Env :: default ( ) ;
@@ -503,51 +501,35 @@ impl ProjectWorkspace {
503501 }
504502}
505503
506- fn get_rustc_cfg_options ( target : Option < & str > ) -> CfgOptions {
507- let mut cfg_options = CfgOptions :: default ( ) ;
504+ fn get_rustc_cfg_options ( target : Option < & str > ) -> Vec < CfgFlag > {
505+ let mut res = Vec :: new ( ) ;
508506
509507 // Some nightly-only cfgs, which are required for stdlib
510- {
511- cfg_options. insert_atom ( "target_thread_local" . into ( ) ) ;
512- for & target_has_atomic in [ "8" , "16" , "32" , "64" , "cas" , "ptr" ] . iter ( ) {
513- cfg_options. insert_key_value ( "target_has_atomic" . into ( ) , target_has_atomic. into ( ) ) ;
514- cfg_options
515- . insert_key_value ( "target_has_atomic_load_store" . into ( ) , target_has_atomic. into ( ) ) ;
508+ res. push ( CfgFlag :: Atom ( "target_thread_local" . into ( ) ) ) ;
509+ for & ty in [ "8" , "16" , "32" , "64" , "cas" , "ptr" ] . iter ( ) {
510+ for & key in [ "target_has_atomic" , "target_has_atomic_load_store" ] . iter ( ) {
511+ res. push ( CfgFlag :: KeyValue { key : key. to_string ( ) , value : ty. into ( ) } ) ;
516512 }
517513 }
518514
519- let rustc_cfgs = || -> Result < String > {
520- // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here.
515+ let rustc_cfgs = {
521516 let mut cmd = Command :: new ( ra_toolchain:: rustc ( ) ) ;
522517 cmd. args ( & [ "--print" , "cfg" , "-O" ] ) ;
523518 if let Some ( target) = target {
524519 cmd. args ( & [ "--target" , target] ) ;
525520 }
526- let output = output ( cmd) ?;
527- Ok ( String :: from_utf8 ( output. stdout ) ?)
528- } ( ) ;
521+ utf8_stdout ( cmd)
522+ } ;
529523
530524 match rustc_cfgs {
531- Ok ( rustc_cfgs) => {
532- for line in rustc_cfgs. lines ( ) {
533- match split_delim ( line, '=' ) {
534- None => cfg_options. insert_atom ( line. into ( ) ) ,
535- Some ( ( key, value) ) => {
536- let value = value. trim_matches ( '"' ) ;
537- cfg_options. insert_key_value ( key. into ( ) , value. into ( ) ) ;
538- }
539- }
540- }
541- }
525+ Ok ( rustc_cfgs) => res. extend ( rustc_cfgs. lines ( ) . map ( |it| it. parse ( ) . unwrap ( ) ) ) ,
542526 Err ( e) => log:: error!( "failed to get rustc cfgs: {:#}" , e) ,
543527 }
544528
545- cfg_options. insert_atom ( "debug_assertions" . into ( ) ) ;
546-
547- cfg_options
529+ res
548530}
549531
550- fn output ( mut cmd : Command ) -> Result < Output > {
532+ fn utf8_stdout ( mut cmd : Command ) -> Result < String > {
551533 let output = cmd. output ( ) . with_context ( || format ! ( "{:?} failed" , cmd) ) ?;
552534 if !output. status . success ( ) {
553535 match String :: from_utf8 ( output. stderr ) {
@@ -557,5 +539,6 @@ fn output(mut cmd: Command) -> Result<Output> {
557539 _ => bail ! ( "{:?} failed, {}" , cmd, output. status) ,
558540 }
559541 }
560- Ok ( output)
542+ let stdout = String :: from_utf8 ( output. stdout ) ?;
543+ Ok ( stdout)
561544}
0 commit comments