Skip to content

Commit 3a4a86d

Browse files
Include wrapper args. in stdout family heuristics to restore classifying clang --driver-mode=cl as Msvc { clang_cl: true } (#1378)
1 parent 65b4d9a commit 3a4a86d

File tree

3 files changed

+50
-36
lines changed

3 files changed

+50
-36
lines changed

src/lib.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ use command_helpers::*;
254254

255255
mod tool;
256256
pub use tool::Tool;
257-
use tool::ToolFamily;
257+
use tool::{CompilerFamilyLookupCache, ToolFamily};
258258

259259
mod tempfile;
260260

@@ -277,7 +277,7 @@ struct BuildCache {
277277
env_cache: RwLock<HashMap<Box<str>, Env>>,
278278
apple_sdk_root_cache: RwLock<HashMap<Box<str>, Arc<OsStr>>>,
279279
apple_versions_cache: RwLock<HashMap<Box<str>, Arc<str>>>,
280-
cached_compiler_family: RwLock<HashMap<Box<Path>, ToolFamily>>,
280+
cached_compiler_family: RwLock<CompilerFamilyLookupCache>,
281281
known_flag_support_status_cache: RwLock<HashMap<CompilerFlag, bool>>,
282282
target_info_parser: target::TargetInfoParser,
283283
}
@@ -2739,19 +2739,13 @@ impl Build {
27392739
let tool_opt: Option<Tool> = self
27402740
.env_tool(env)
27412741
.map(|(tool, wrapper, args)| {
2742-
// find the driver mode, if any
2743-
const DRIVER_MODE: &str = "--driver-mode=";
2744-
let driver_mode = args
2745-
.iter()
2746-
.find(|a| a.starts_with(DRIVER_MODE))
2747-
.map(|a| &a[DRIVER_MODE.len()..]);
27482742
// Chop off leading/trailing whitespace to work around
27492743
// semi-buggy build scripts which are shared in
27502744
// makefiles/configure scripts (where spaces are far more
27512745
// lenient)
2752-
let mut t = Tool::with_clang_driver(
2746+
let mut t = Tool::with_args(
27532747
tool,
2754-
driver_mode,
2748+
args.clone(),
27552749
&self.build_cache.cached_compiler_family,
27562750
&self.cargo_output,
27572751
out_dir,
@@ -2871,7 +2865,7 @@ impl Build {
28712865
};
28722866
let mut nvcc_tool = Tool::with_features(
28732867
nvcc,
2874-
None,
2868+
vec![],
28752869
self.cuda,
28762870
&self.build_cache.cached_compiler_family,
28772871
&self.cargo_output,

src/tool.rs

+44-25
Original file line numberDiff line numberDiff line change
@@ -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 {
4042
impl 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
}

tests/rustflags.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#[cfg(not(windows))]
12
use crate::support::Test;
23
mod support;
34

0 commit comments

Comments
 (0)