@@ -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 : & std :: sync :: Arc < 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 : & std :: sync :: Arc < 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 : & std :: sync :: Arc < RwLock < CompilerFamilyLookupCache > > ,
94
96
cargo_output : & CargoOutput ,
95
97
out_dir : Option < & Path > ,
96
98
) -> Self {
@@ -107,6 +109,7 @@ impl Tool {
107
109
108
110
fn detect_family_inner (
109
111
path : & Path ,
112
+ args : & [ String ] ,
110
113
cargo_output : & CargoOutput ,
111
114
out_dir : Option < & Path > ,
112
115
) -> Result < ToolFamily , Error > {
@@ -158,15 +161,21 @@ impl Tool {
158
161
cargo_output. print_debug ( & stdout) ;
159
162
160
163
// 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
+ )
168
178
. is_ok ( ) ;
169
-
170
179
let clang = stdout. contains ( r#""clang""# ) ;
171
180
let gcc = stdout. contains ( r#""gcc""# ) ;
172
181
@@ -185,20 +194,26 @@ impl Tool {
185
194
}
186
195
}
187
196
}
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) {
190
205
return Ok ( * family) ;
191
206
}
192
207
193
- let family = detect_family_inner ( path, cargo_output, out_dir) ?;
208
+ let family = detect_family_inner ( path, args , cargo_output, out_dir) ?;
194
209
cached_compiler_family
195
210
. write ( )
196
211
. unwrap ( )
197
- . insert ( path . into ( ) , family) ;
212
+ . insert ( cache_key , family) ;
198
213
Ok ( family)
199
214
} ;
200
215
201
- let family = detect_family ( & path) . unwrap_or_else ( |e| {
216
+ let family = detect_family ( & path, & args ) . unwrap_or_else ( |e| {
202
217
cargo_output. print_warning ( & format_args ! (
203
218
"Compiler family detection failed due to error: {}" ,
204
219
e
@@ -208,12 +223,18 @@ impl Tool {
208
223
Some ( fname) if fname. ends_with ( "cl" ) || fname == "cl.exe" => {
209
224
ToolFamily :: Msvc { clang_cl : false }
210
225
}
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
+ }
217
238
Some ( fname) if fname. contains ( "zig" ) => ToolFamily :: Clang { zig_cc : true } ,
218
239
_ => ToolFamily :: Gnu ,
219
240
}
0 commit comments