Skip to content

Commit

Permalink
fix: include wrapper args. in stdout family heuristics
Browse files Browse the repository at this point in the history
This can be particularly significant for compilers that can dynamically
change what options they accept based on arguments, like `clang
--driver-mode=cl`.
  • Loading branch information
ErichDonGubler committed Jan 31, 2025
1 parent 50a3f70 commit c5c1a91
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 12 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

- Include compiler wrapper arguments (i.e., `CC=compiler arg1 arg2`) in the classification of compilers' tool family. This fixes cases like `clang --driver-mode=cl` being incorrectly detected as needing `clang`-like arguments, rather than `cl`-like arguments. [#????](https://github.com/rust-lang/cc-rs/????).

## [1.2.10](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.9...cc-v1.2.10) - 2025-01-17

### Other
Expand Down
33 changes: 21 additions & 12 deletions src/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::{
Error, ErrorKind, OutputKind,
};

pub(crate) type CompilerFamilyLookupCache = HashMap<Box<Path>, ToolFamily>;
pub(crate) type CompilerFamilyLookupCache = HashMap<(Box<Path>, Vec<String>), ToolFamily>;

/// Configuration used to represent an invocation of a C compiler.
///
Expand Down Expand Up @@ -116,21 +116,25 @@ impl Tool {
fn guess_family_from_stdout(
stdout: &str,
path: &Path,
args: &[String],
cargo_output: &CargoOutput,
) -> Result<ToolFamily, Error> {
cargo_output.print_debug(&stdout);

// https://gitlab.kitware.com/cmake/cmake/-/blob/69a2eeb9dff5b60f2f1e5b425002a0fd45b7cadb/Modules/CMakeDetermineCompilerId.cmake#L267-271
// stdin is set to null to ensure that the help output is never paginated.
let accepts_cl_style_flags =
run(Command::new(path).arg("-?").stdin(Stdio::null()), path, &{
let accepts_cl_style_flags = run(
Command::new(path).args(args).arg("-?").stdin(Stdio::null()),
path,
&{
// the errors are not errors!
let mut cargo_output = cargo_output.clone();
cargo_output.warnings = cargo_output.debug;
cargo_output.output = OutputKind::Discard;
cargo_output
})
.is_ok();
},
)
.is_ok();

let clang = stdout.contains(r#""clang""#);
let gcc = stdout.contains(r#""gcc""#);
Expand All @@ -155,6 +159,7 @@ impl Tool {

fn detect_family_inner(
path: &Path,
args: &[String],
cargo_output: &CargoOutput,
out_dir: Option<&Path>,
) -> Result<ToolFamily, Error> {
Expand Down Expand Up @@ -209,25 +214,29 @@ impl Tool {
&compiler_detect_output,
)?;
let stdout = String::from_utf8_lossy(&stdout);
guess_family_from_stdout(&stdout, path, cargo_output)
guess_family_from_stdout(&stdout, path, args, cargo_output)
} else {
guess_family_from_stdout(&stdout, path, cargo_output)
guess_family_from_stdout(&stdout, path, args, cargo_output)
}
}
let detect_family = |path: &Path| -> Result<ToolFamily, Error> {
if let Some(family) = cached_compiler_family.read().unwrap().get(path) {
let detect_family = |path: &Path, args: &[String]| -> Result<ToolFamily, Error> {
let cache_key = (Box::from(path), args.to_vec());
if let Some(family) = cached_compiler_family.read().unwrap().get(&cache_key) {
return Ok(*family);
}

let family = detect_family_inner(path, cargo_output, out_dir)?;
let family = {
let (path, args) = &cache_key;
detect_family_inner(path, args, cargo_output, out_dir)?
};
cached_compiler_family
.write()
.unwrap()
.insert(path.into(), family);
.insert(cache_key, family);
Ok(family)
};

let family = detect_family(&path).unwrap_or_else(|e| {
let family = detect_family(&path, &args).unwrap_or_else(|e| {
cargo_output.print_warning(&format_args!(
"Compiler family detection failed due to error: {}",
e
Expand Down

0 comments on commit c5c1a91

Please sign in to comment.