@@ -250,6 +250,12 @@ use tool::ToolFamily;
250
250
mod target_info;
251
251
mod tempfile;
252
252
253
+ #[ derive( Debug , Eq , PartialEq , Hash ) ]
254
+ struct CompilerFlag {
255
+ compiler : Box < Path > ,
256
+ flag : Box < str > ,
257
+ }
258
+
253
259
/// A builder for compilation of a native library.
254
260
///
255
261
/// A `Build` is the main type of the `cc` crate and is used to control all the
@@ -262,7 +268,7 @@ pub struct Build {
262
268
objects : Vec < Arc < Path > > ,
263
269
flags : Vec < Arc < str > > ,
264
270
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 > > > ,
266
272
ar_flags : Vec < Arc < str > > ,
267
273
asm_flags : Vec < Arc < str > > ,
268
274
no_default_flags : bool ,
@@ -385,7 +391,7 @@ impl Build {
385
391
objects : Vec :: new ( ) ,
386
392
flags : Vec :: new ( ) ,
387
393
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 ( ) ) ) ,
389
395
ar_flags : Vec :: new ( ) ,
390
396
asm_flags : Vec :: new ( ) ,
391
397
no_default_flags : false ,
@@ -595,29 +601,42 @@ impl Build {
595
601
/// `known_flag_support` field. If `is_flag_supported(flag)`
596
602
/// is called again, the result will be read from the hash table.
597
603
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
+ {
600
634
return Ok ( is_supported) ;
601
635
}
602
636
603
637
let out_dir = self . get_out_dir ( ) ?;
604
638
let src = self . ensure_check_file ( ) ?;
605
639
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 ( ) ?;
621
640
622
641
// Clang uses stderr for verbose output, which yields a false positive
623
642
// result if the CFLAGS/CXXFLAGS include -v to aid in debugging.
@@ -653,7 +672,11 @@ impl Build {
653
672
let output = cmd. output ( ) ?;
654
673
let is_supported = output. status . success ( ) && output. stderr . is_empty ( ) ;
655
674
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
+
657
680
Ok ( is_supported)
658
681
}
659
682
0 commit comments