@@ -249,6 +249,12 @@ use tool::ToolFamily;
249249
250250mod target_info;
251251
252+ #[ derive( Debug , Eq , PartialEq , Hash ) ]
253+ struct CompilerFlag {
254+ compiler : Box < Path > ,
255+ flag : Box < str > ,
256+ }
257+
252258/// A builder for compilation of a native library.
253259///
254260/// A `Build` is the main type of the `cc` crate and is used to control all the
@@ -261,7 +267,7 @@ pub struct Build {
261267 objects : Vec < Arc < Path > > ,
262268 flags : Vec < Arc < str > > ,
263269 flags_supported : Vec < Arc < str > > ,
264- known_flag_support_status : Arc < Mutex < HashMap < String , bool > > > ,
270+ known_flag_support_status_cache : Arc < Mutex < HashMap < CompilerFlag , bool > > > ,
265271 ar_flags : Vec < Arc < str > > ,
266272 asm_flags : Vec < Arc < str > > ,
267273 no_default_flags : bool ,
@@ -382,7 +388,7 @@ impl Build {
382388 objects : Vec :: new ( ) ,
383389 flags : Vec :: new ( ) ,
384390 flags_supported : Vec :: new ( ) ,
385- known_flag_support_status : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
391+ known_flag_support_status_cache : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
386392 ar_flags : Vec :: new ( ) ,
387393 asm_flags : Vec :: new ( ) ,
388394 no_default_flags : false ,
@@ -592,29 +598,42 @@ impl Build {
592598 /// `known_flag_support` field. If `is_flag_supported(flag)`
593599 /// is called again, the result will be read from the hash table.
594600 pub fn is_flag_supported ( & self , flag : & str ) -> Result < bool , Error > {
595- let mut known_status = self . known_flag_support_status . lock ( ) . unwrap ( ) ;
596- if let Some ( is_supported) = known_status. get ( flag) . cloned ( ) {
601+ let target = self . get_target ( ) ?;
602+
603+ let mut compiler = {
604+ let mut cfg = Build :: new ( ) ;
605+ cfg. flag ( flag)
606+ . cargo_metadata ( self . cargo_output . metadata )
607+ . target ( & target)
608+ . opt_level ( 0 )
609+ . host ( & self . get_host ( ) ?)
610+ . debug ( false )
611+ . cpp ( self . cpp )
612+ . cuda ( self . cuda ) ;
613+ if let Some ( ref c) = self . compiler {
614+ cfg. compiler ( c. clone ( ) ) ;
615+ }
616+ cfg. try_get_compiler ( ) ?
617+ } ;
618+
619+ let compiler_flag = CompilerFlag {
620+ compiler : compiler. path . clone ( ) . into ( ) ,
621+ flag : flag. into ( ) ,
622+ } ;
623+
624+ if let Some ( is_supported) = self
625+ . known_flag_support_status_cache
626+ . lock ( )
627+ . unwrap ( )
628+ . get ( & compiler_flag)
629+ . cloned ( )
630+ {
597631 return Ok ( is_supported) ;
598632 }
599633
600634 let out_dir = self . get_out_dir ( ) ?;
601635 let src = self . ensure_check_file ( ) ?;
602636 let obj = out_dir. join ( "flag_check" ) ;
603- let target = self . get_target ( ) ?;
604- let host = self . get_host ( ) ?;
605- let mut cfg = Build :: new ( ) ;
606- cfg. flag ( flag)
607- . cargo_metadata ( self . cargo_output . metadata )
608- . target ( & target)
609- . opt_level ( 0 )
610- . host ( & host)
611- . debug ( false )
612- . cpp ( self . cpp )
613- . cuda ( self . cuda ) ;
614- if let Some ( ref c) = self . compiler {
615- cfg. compiler ( c. clone ( ) ) ;
616- }
617- let mut compiler = cfg. try_get_compiler ( ) ?;
618637
619638 // Clang uses stderr for verbose output, which yields a false positive
620639 // result if the CFLAGS/CXXFLAGS include -v to aid in debugging.
@@ -650,7 +669,11 @@ impl Build {
650669 let output = cmd. output ( ) ?;
651670 let is_supported = output. status . success ( ) && output. stderr . is_empty ( ) ;
652671
653- known_status. insert ( flag. to_owned ( ) , is_supported) ;
672+ self . known_flag_support_status_cache
673+ . lock ( )
674+ . unwrap ( )
675+ . insert ( compiler_flag, is_supported) ;
676+
654677 Ok ( is_supported)
655678 }
656679
0 commit comments