@@ -16,6 +16,8 @@ use crate::{
1616 Error , ErrorKind , OutputKind ,
1717} ;
1818
19+ pub ( crate ) type CompilerFamilyLookupCache = HashMap < Box < [ Box < OsStr > ] > , ToolFamily > ;
20+
1921/// Configuration used to represent an invocation of a C compiler.
2022///
2123/// This can be used to figure out what compiler is in use, what the arguments
@@ -40,30 +42,30 @@ pub struct Tool {
4042impl Tool {
4143 pub ( crate ) fn new (
4244 path : PathBuf ,
43- cached_compiler_family : & RwLock < HashMap < Box < Path > , ToolFamily > > ,
45+ cached_compiler_family : & std :: sync :: Arc < RwLock < CompilerFamilyLookupCache > > ,
4446 cargo_output : & CargoOutput ,
4547 out_dir : Option < & Path > ,
4648 ) -> Self {
4749 Self :: with_features (
4850 path,
49- None ,
51+ vec ! [ ] ,
5052 false ,
5153 cached_compiler_family,
5254 cargo_output,
5355 out_dir,
5456 )
5557 }
5658
57- pub ( crate ) fn with_clang_driver (
59+ pub ( crate ) fn with_args (
5860 path : PathBuf ,
59- clang_driver : Option < & str > ,
60- cached_compiler_family : & RwLock < HashMap < Box < Path > , ToolFamily > > ,
61+ args : Vec < String > ,
62+ cached_compiler_family : & std :: sync :: Arc < RwLock < CompilerFamilyLookupCache > > ,
6163 cargo_output : & CargoOutput ,
6264 out_dir : Option < & Path > ,
6365 ) -> Self {
6466 Self :: with_features (
6567 path,
66- clang_driver ,
68+ args ,
6769 false ,
6870 cached_compiler_family,
6971 cargo_output,
@@ -88,9 +90,9 @@ impl Tool {
8890
8991 pub ( crate ) fn with_features (
9092 path : PathBuf ,
91- clang_driver : Option < & str > ,
93+ args : Vec < String > ,
9294 cuda : bool ,
93- cached_compiler_family : & RwLock < HashMap < Box < Path > , ToolFamily > > ,
95+ cached_compiler_family : & std :: sync :: Arc < RwLock < CompilerFamilyLookupCache > > ,
9496 cargo_output : & CargoOutput ,
9597 out_dir : Option < & Path > ,
9698 ) -> Self {
@@ -107,6 +109,7 @@ impl Tool {
107109
108110 fn detect_family_inner (
109111 path : & Path ,
112+ args : & [ String ] ,
110113 cargo_output : & CargoOutput ,
111114 out_dir : Option < & Path > ,
112115 ) -> Result < ToolFamily , Error > {
@@ -158,15 +161,21 @@ impl Tool {
158161 cargo_output. print_debug ( & stdout) ;
159162
160163 // https://gitlab.kitware.com/cmake/cmake/-/blob/69a2eeb9dff5b60f2f1e5b425002a0fd45b7cadb/Modules/CMakeDetermineCompilerId.cmake#L267-271
161- let accepts_cl_style_flags = run ( Command :: new ( path) . arg ( "-?" ) , path, & {
162- // the errors are not errors!
163- let mut cargo_output = cargo_output. clone ( ) ;
164- cargo_output. warnings = cargo_output. debug ;
165- cargo_output. output = OutputKind :: Discard ;
166- cargo_output
167- } )
164+ let accepts_cl_style_flags = run (
165+ Command :: new ( path)
166+ . args ( args)
167+ . arg ( "-?" )
168+ . stdin ( std:: process:: Stdio :: null ( ) ) ,
169+ path,
170+ & {
171+ // the errors are not errors!
172+ let mut cargo_output = cargo_output. clone ( ) ;
173+ cargo_output. warnings = cargo_output. debug ;
174+ cargo_output. output = OutputKind :: Discard ;
175+ cargo_output
176+ } ,
177+ )
168178 . is_ok ( ) ;
169-
170179 let clang = stdout. contains ( r#""clang""# ) ;
171180 let gcc = stdout. contains ( r#""gcc""# ) ;
172181
@@ -185,20 +194,26 @@ impl Tool {
185194 }
186195 }
187196 }
188- let detect_family = |path : & Path | -> Result < ToolFamily , Error > {
189- if let Some ( family) = cached_compiler_family. read ( ) . unwrap ( ) . get ( path) {
197+ let detect_family = |path : & Path , args : & [ String ] | -> Result < ToolFamily , Error > {
198+ let cache_key = [ path. as_os_str ( ) ]
199+ . iter ( )
200+ . cloned ( )
201+ . chain ( args. iter ( ) . map ( OsStr :: new) )
202+ . map ( Into :: into)
203+ . collect ( ) ;
204+ if let Some ( family) = cached_compiler_family. read ( ) . unwrap ( ) . get ( & cache_key) {
190205 return Ok ( * family) ;
191206 }
192207
193- let family = detect_family_inner ( path, cargo_output, out_dir) ?;
208+ let family = detect_family_inner ( path, args , cargo_output, out_dir) ?;
194209 cached_compiler_family
195210 . write ( )
196211 . unwrap ( )
197- . insert ( path . into ( ) , family) ;
212+ . insert ( cache_key , family) ;
198213 Ok ( family)
199214 } ;
200215
201- let family = detect_family ( & path) . unwrap_or_else ( |e| {
216+ let family = detect_family ( & path, & args ) . unwrap_or_else ( |e| {
202217 cargo_output. print_warning ( & format_args ! (
203218 "Compiler family detection failed due to error: {}" ,
204219 e
@@ -208,12 +223,18 @@ impl Tool {
208223 Some ( fname) if fname. ends_with ( "cl" ) || fname == "cl.exe" => {
209224 ToolFamily :: Msvc { clang_cl : false }
210225 }
211- Some ( fname) if fname. contains ( "clang" ) => match clang_driver {
212- Some ( "cl" ) => ToolFamily :: Msvc { clang_cl : true } ,
213- _ => ToolFamily :: Clang {
214- zig_cc : is_zig_cc ( & path, cargo_output) ,
215- } ,
216- } ,
226+ Some ( fname) if fname. contains ( "clang" ) => {
227+ let is_clang_cl = args
228+ . iter ( )
229+ . any ( |a| a. strip_prefix ( "--driver-mode=" ) == Some ( "cl" ) ) ;
230+ if is_clang_cl {
231+ ToolFamily :: Msvc { clang_cl : true }
232+ } else {
233+ ToolFamily :: Clang {
234+ zig_cc : is_zig_cc ( & path, cargo_output) ,
235+ }
236+ }
237+ }
217238 Some ( fname) if fname. contains ( "zig" ) => ToolFamily :: Clang { zig_cc : true } ,
218239 _ => ToolFamily :: Gnu ,
219240 }
0 commit comments