@@ -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 : & 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 : & 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 : & RwLock < CompilerFamilyLookupCache > ,
9496 cargo_output : & CargoOutput ,
9597 out_dir : Option < & Path > ,
9698 ) -> Self {
@@ -114,21 +116,25 @@ impl Tool {
114116 fn guess_family_from_stdout (
115117 stdout : & str ,
116118 path : & Path ,
119+ args : & [ String ] ,
117120 cargo_output : & CargoOutput ,
118121 ) -> Result < ToolFamily , Error > {
119122 cargo_output. print_debug ( & stdout) ;
120123
121124 // https://gitlab.kitware.com/cmake/cmake/-/blob/69a2eeb9dff5b60f2f1e5b425002a0fd45b7cadb/Modules/CMakeDetermineCompilerId.cmake#L267-271
122125 // stdin is set to null to ensure that the help output is never paginated.
123- let accepts_cl_style_flags =
124- run ( Command :: new ( path) . arg ( "-?" ) . stdin ( Stdio :: null ( ) ) , path, & {
126+ let accepts_cl_style_flags = run (
127+ Command :: new ( path) . args ( args) . arg ( "-?" ) . stdin ( Stdio :: null ( ) ) ,
128+ path,
129+ & {
125130 // the errors are not errors!
126131 let mut cargo_output = cargo_output. clone ( ) ;
127132 cargo_output. warnings = cargo_output. debug ;
128133 cargo_output. output = OutputKind :: Discard ;
129134 cargo_output
130- } )
131- . is_ok ( ) ;
135+ } ,
136+ )
137+ . is_ok ( ) ;
132138
133139 let clang = stdout. contains ( r#""clang""# ) ;
134140 let gcc = stdout. contains ( r#""gcc""# ) ;
@@ -153,6 +159,7 @@ impl Tool {
153159
154160 fn detect_family_inner (
155161 path : & Path ,
162+ args : & [ String ] ,
156163 cargo_output : & CargoOutput ,
157164 out_dir : Option < & Path > ,
158165 ) -> Result < ToolFamily , Error > {
@@ -207,25 +214,31 @@ impl Tool {
207214 & compiler_detect_output,
208215 ) ?;
209216 let stdout = String :: from_utf8_lossy ( & stdout) ;
210- guess_family_from_stdout ( & stdout, path, cargo_output)
217+ guess_family_from_stdout ( & stdout, path, args , cargo_output)
211218 } else {
212- guess_family_from_stdout ( & stdout, path, cargo_output)
219+ guess_family_from_stdout ( & stdout, path, args , cargo_output)
213220 }
214221 }
215- let detect_family = |path : & Path | -> Result < ToolFamily , Error > {
216- if let Some ( family) = cached_compiler_family. read ( ) . unwrap ( ) . get ( path) {
222+ let detect_family = |path : & Path , args : & [ String ] | -> Result < ToolFamily , Error > {
223+ let cache_key = [ path. as_os_str ( ) ]
224+ . iter ( )
225+ . cloned ( )
226+ . chain ( args. iter ( ) . map ( OsStr :: new) )
227+ . map ( Into :: into)
228+ . collect ( ) ;
229+ if let Some ( family) = cached_compiler_family. read ( ) . unwrap ( ) . get ( & cache_key) {
217230 return Ok ( * family) ;
218231 }
219232
220- let family = detect_family_inner ( path, cargo_output, out_dir) ?;
233+ let family = detect_family_inner ( path, args , cargo_output, out_dir) ?;
221234 cached_compiler_family
222235 . write ( )
223236 . unwrap ( )
224- . insert ( path . into ( ) , family) ;
237+ . insert ( cache_key , family) ;
225238 Ok ( family)
226239 } ;
227240
228- let family = detect_family ( & path) . unwrap_or_else ( |e| {
241+ let family = detect_family ( & path, & args ) . unwrap_or_else ( |e| {
229242 cargo_output. print_warning ( & format_args ! (
230243 "Compiler family detection failed due to error: {}" ,
231244 e
@@ -235,12 +248,18 @@ impl Tool {
235248 Some ( fname) if fname. ends_with ( "cl" ) || fname == "cl.exe" => {
236249 ToolFamily :: Msvc { clang_cl : false }
237250 }
238- Some ( fname) if fname. contains ( "clang" ) => match clang_driver {
239- Some ( "cl" ) => ToolFamily :: Msvc { clang_cl : true } ,
240- _ => ToolFamily :: Clang {
241- zig_cc : is_zig_cc ( & path, cargo_output) ,
242- } ,
243- } ,
251+ Some ( fname) if fname. contains ( "clang" ) => {
252+ let is_clang_cl = args
253+ . iter ( )
254+ . any ( |a| a. strip_prefix ( "--driver-mode=" ) == Some ( "cl" ) ) ;
255+ if is_clang_cl {
256+ ToolFamily :: Msvc { clang_cl : true }
257+ } else {
258+ ToolFamily :: Clang {
259+ zig_cc : is_zig_cc ( & path, cargo_output) ,
260+ }
261+ }
262+ }
244263 Some ( fname) if fname. contains ( "zig" ) => ToolFamily :: Clang { zig_cc : true } ,
245264 _ => ToolFamily :: Gnu ,
246265 }
0 commit comments