@@ -16,6 +16,8 @@ use crate::{
16
16
Error , ErrorKind , OutputKind ,
17
17
} ;
18
18
19
+ pub ( crate ) type CompilerFamilyLookupCache = HashMap < Box < [ Box < OsStr > ] > , ToolFamily > ;
20
+
19
21
/// Configuration used to represent an invocation of a C compiler.
20
22
///
21
23
/// This can be used to figure out what compiler is in use, what the arguments
@@ -40,30 +42,30 @@ pub struct Tool {
40
42
impl Tool {
41
43
pub ( crate ) fn new (
42
44
path : PathBuf ,
43
- cached_compiler_family : & RwLock < HashMap < Box < Path > , ToolFamily > > ,
45
+ cached_compiler_family : & RwLock < CompilerFamilyLookupCache > ,
44
46
cargo_output : & CargoOutput ,
45
47
out_dir : Option < & Path > ,
46
48
) -> Self {
47
49
Self :: with_features (
48
50
path,
49
- None ,
51
+ vec ! [ ] ,
50
52
false ,
51
53
cached_compiler_family,
52
54
cargo_output,
53
55
out_dir,
54
56
)
55
57
}
56
58
57
- pub ( crate ) fn with_clang_driver (
59
+ pub ( crate ) fn with_args (
58
60
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 > ,
61
63
cargo_output : & CargoOutput ,
62
64
out_dir : Option < & Path > ,
63
65
) -> Self {
64
66
Self :: with_features (
65
67
path,
66
- clang_driver ,
68
+ args ,
67
69
false ,
68
70
cached_compiler_family,
69
71
cargo_output,
@@ -88,9 +90,9 @@ impl Tool {
88
90
89
91
pub ( crate ) fn with_features (
90
92
path : PathBuf ,
91
- clang_driver : Option < & str > ,
93
+ args : Vec < String > ,
92
94
cuda : bool ,
93
- cached_compiler_family : & RwLock < HashMap < Box < Path > , ToolFamily > > ,
95
+ cached_compiler_family : & RwLock < CompilerFamilyLookupCache > ,
94
96
cargo_output : & CargoOutput ,
95
97
out_dir : Option < & Path > ,
96
98
) -> Self {
@@ -114,21 +116,25 @@ impl Tool {
114
116
fn guess_family_from_stdout (
115
117
stdout : & str ,
116
118
path : & Path ,
119
+ args : & [ String ] ,
117
120
cargo_output : & CargoOutput ,
118
121
) -> Result < ToolFamily , Error > {
119
122
cargo_output. print_debug ( & stdout) ;
120
123
121
124
// https://gitlab.kitware.com/cmake/cmake/-/blob/69a2eeb9dff5b60f2f1e5b425002a0fd45b7cadb/Modules/CMakeDetermineCompilerId.cmake#L267-271
122
125
// 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
+ & {
125
130
// the errors are not errors!
126
131
let mut cargo_output = cargo_output. clone ( ) ;
127
132
cargo_output. warnings = cargo_output. debug ;
128
133
cargo_output. output = OutputKind :: Discard ;
129
134
cargo_output
130
- } )
131
- . is_ok ( ) ;
135
+ } ,
136
+ )
137
+ . is_ok ( ) ;
132
138
133
139
let clang = stdout. contains ( r#""clang""# ) ;
134
140
let gcc = stdout. contains ( r#""gcc""# ) ;
@@ -153,6 +159,7 @@ impl Tool {
153
159
154
160
fn detect_family_inner (
155
161
path : & Path ,
162
+ args : & [ String ] ,
156
163
cargo_output : & CargoOutput ,
157
164
out_dir : Option < & Path > ,
158
165
) -> Result < ToolFamily , Error > {
@@ -207,25 +214,31 @@ impl Tool {
207
214
& compiler_detect_output,
208
215
) ?;
209
216
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)
211
218
} else {
212
- guess_family_from_stdout ( & stdout, path, cargo_output)
219
+ guess_family_from_stdout ( & stdout, path, args , cargo_output)
213
220
}
214
221
}
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) {
217
230
return Ok ( * family) ;
218
231
}
219
232
220
- let family = detect_family_inner ( path, cargo_output, out_dir) ?;
233
+ let family = detect_family_inner ( path, args , cargo_output, out_dir) ?;
221
234
cached_compiler_family
222
235
. write ( )
223
236
. unwrap ( )
224
- . insert ( path . into ( ) , family) ;
237
+ . insert ( cache_key , family) ;
225
238
Ok ( family)
226
239
} ;
227
240
228
- let family = detect_family ( & path) . unwrap_or_else ( |e| {
241
+ let family = detect_family ( & path, & args ) . unwrap_or_else ( |e| {
229
242
cargo_output. print_warning ( & format_args ! (
230
243
"Compiler family detection failed due to error: {}" ,
231
244
e
@@ -235,12 +248,18 @@ impl Tool {
235
248
Some ( fname) if fname. ends_with ( "cl" ) || fname == "cl.exe" => {
236
249
ToolFamily :: Msvc { clang_cl : false }
237
250
}
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
+ }
244
263
Some ( fname) if fname. contains ( "zig" ) => ToolFamily :: Clang { zig_cc : true } ,
245
264
_ => ToolFamily :: Gnu ,
246
265
}
0 commit comments