@@ -250,6 +250,12 @@ use tool::ToolFamily;
250250mod target_info;
251251mod tempfile;
252252
253+ #[ derive( Debug , Eq , PartialEq , Hash ) ]
254+ struct CompilerFlag {
255+ compiler : Box < Path > ,
256+ flag : Box < str > ,
257+ }
258+
253259/// A builder for compilation of a native library.
254260///
255261/// A `Build` is the main type of the `cc` crate and is used to control all the
@@ -262,7 +268,7 @@ pub struct Build {
262268 objects : Vec < Arc < Path > > ,
263269 flags : Vec < Arc < str > > ,
264270 flags_supported : Vec < Arc < str > > ,
265- known_flag_support_status : Arc < Mutex < HashMap < String , bool > > > ,
271+ known_flag_support_status_cache : Arc < Mutex < HashMap < CompilerFlag , bool > > > ,
266272 ar_flags : Vec < Arc < str > > ,
267273 asm_flags : Vec < Arc < str > > ,
268274 no_default_flags : bool ,
@@ -385,7 +391,7 @@ impl Build {
385391 objects : Vec :: new ( ) ,
386392 flags : Vec :: new ( ) ,
387393 flags_supported : Vec :: new ( ) ,
388- known_flag_support_status : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
394+ known_flag_support_status_cache : Arc :: new ( Mutex :: new ( HashMap :: new ( ) ) ) ,
389395 ar_flags : Vec :: new ( ) ,
390396 asm_flags : Vec :: new ( ) ,
391397 no_default_flags : false ,
@@ -595,29 +601,42 @@ impl Build {
595601 /// `known_flag_support` field. If `is_flag_supported(flag)`
596602 /// is called again, the result will be read from the hash table.
597603 pub fn is_flag_supported ( & self , flag : & str ) -> Result < bool , Error > {
598- let mut known_status = self . known_flag_support_status . lock ( ) . unwrap ( ) ;
599- if let Some ( is_supported) = known_status. get ( flag) . cloned ( ) {
604+ let target = self . get_target ( ) ?;
605+
606+ let mut compiler = {
607+ let mut cfg = Build :: new ( ) ;
608+ cfg. flag ( flag)
609+ . cargo_metadata ( self . cargo_output . metadata )
610+ . target ( & target)
611+ . opt_level ( 0 )
612+ . host ( & self . get_host ( ) ?)
613+ . debug ( false )
614+ . cpp ( self . cpp )
615+ . cuda ( self . cuda ) ;
616+ if let Some ( ref c) = self . compiler {
617+ cfg. compiler ( c. clone ( ) ) ;
618+ }
619+ cfg. try_get_compiler ( ) ?
620+ } ;
621+
622+ let compiler_flag = CompilerFlag {
623+ compiler : compiler. path . clone ( ) . into ( ) ,
624+ flag : flag. into ( ) ,
625+ } ;
626+
627+ if let Some ( is_supported) = self
628+ . known_flag_support_status_cache
629+ . lock ( )
630+ . unwrap ( )
631+ . get ( & compiler_flag)
632+ . cloned ( )
633+ {
600634 return Ok ( is_supported) ;
601635 }
602636
603637 let out_dir = self . get_out_dir ( ) ?;
604638 let src = self . ensure_check_file ( ) ?;
605639 let obj = out_dir. join ( "flag_check" ) ;
606- let target = self . get_target ( ) ?;
607- let host = self . get_host ( ) ?;
608- let mut cfg = Build :: new ( ) ;
609- cfg. flag ( flag)
610- . cargo_metadata ( self . cargo_output . metadata )
611- . target ( & target)
612- . opt_level ( 0 )
613- . host ( & host)
614- . debug ( false )
615- . cpp ( self . cpp )
616- . cuda ( self . cuda ) ;
617- if let Some ( ref c) = self . compiler {
618- cfg. compiler ( c. clone ( ) ) ;
619- }
620- let mut compiler = cfg. try_get_compiler ( ) ?;
621640
622641 // Clang uses stderr for verbose output, which yields a false positive
623642 // result if the CFLAGS/CXXFLAGS include -v to aid in debugging.
@@ -653,7 +672,11 @@ impl Build {
653672 let output = cmd. output ( ) ?;
654673 let is_supported = output. status . success ( ) && output. stderr . is_empty ( ) ;
655674
656- known_status. insert ( flag. to_owned ( ) , is_supported) ;
675+ self . known_flag_support_status_cache
676+ . lock ( )
677+ . unwrap ( )
678+ . insert ( compiler_flag, is_supported) ;
679+
657680 Ok ( is_supported)
658681 }
659682
0 commit comments