Skip to content

Commit da402eb

Browse files
committed
Fix #359: Support language-selection flags in is_flag_supported()
Changed flag validation from file-based to stdin-based compilation to support language-selection flags like -xassembler-with-cpp. This also improves flag validation by ensuring invalid flags are properly rejected. - Use stdin compilation with explicit language for most flags - For -x flags, let the flag determine the language - Add -Werror=unknown-warning-option for clang to reject invalid -W flags - Remove unused ensure_check_file() method - Add regression test for assembly flags
1 parent 9ec00e4 commit da402eb

File tree

3 files changed

+69
-28
lines changed

3 files changed

+69
-28
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Fixed
11+
12+
- Fix `is_flag_supported` to work with assembly-specific flags by using stdin compilation instead of file-based compilation ([#359](https://github.com/rust-lang/cc-rs/issues/359))
13+
1014
## [1.2.49](https://github.com/rust-lang/cc-rs/compare/cc-v1.2.48...cc-v1.2.49) - 2025-12-06
1115

1216
### Other

src/lib.rs

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ use std::env;
246246
use std::ffi::{OsStr, OsString};
247247
use std::fmt::{self, Display};
248248
use std::fs;
249-
use std::io::{self, Write};
249+
use std::io;
250250
use std::path::{Component, Path, PathBuf};
251251
use std::process::{Command, Stdio};
252252
use std::sync::{
@@ -1425,25 +1425,6 @@ impl Build {
14251425
)
14261426
}
14271427

1428-
fn ensure_check_file(&self) -> Result<PathBuf, Error> {
1429-
let out_dir = self.get_out_dir()?;
1430-
let src = if self.cuda {
1431-
assert!(self.cpp);
1432-
out_dir.join("flag_check.cu")
1433-
} else if self.cpp {
1434-
out_dir.join("flag_check.cpp")
1435-
} else {
1436-
out_dir.join("flag_check.c")
1437-
};
1438-
1439-
if !src.exists() {
1440-
let mut f = fs::File::create(&src)?;
1441-
write!(f, "int main(void) {{ return 0; }}")?;
1442-
}
1443-
1444-
Ok(src)
1445-
}
1446-
14471428
fn is_flag_supported_inner(
14481429
&self,
14491430
flag: &OsStr,
@@ -1467,7 +1448,6 @@ impl Build {
14671448
}
14681449

14691450
let out_dir = self.get_out_dir()?;
1470-
let src = self.ensure_check_file()?;
14711451
let obj = out_dir.join("flag_check");
14721452

14731453
let mut compiler = {
@@ -1499,6 +1479,14 @@ impl Build {
14991479
// Avoid reporting that the arg is unsupported just because the
15001480
// compiler complains that it wasn't used.
15011481
compiler.push_cc_arg("-Wno-unused-command-line-argument".into());
1482+
// Turn unknown warning options into errors so invalid -W flags are properly rejected
1483+
compiler.push_cc_arg("-Werror=unknown-warning-option".into());
1484+
}
1485+
1486+
if compiler.is_like_gnu() || compiler.is_like_clang() {
1487+
// Turn warnings into errors to ensure invalid flags are rejected
1488+
// (e.g., -std=c++11 for C code, invalid warning flags)
1489+
compiler.push_cc_arg("-Werror".into());
15021490
}
15031491

15041492
let mut cmd = compiler.to_command();
@@ -1522,12 +1510,6 @@ impl Build {
15221510
// https://github.com/rust-lang/cc-rs/issues/1423
15231511
cmd.arg("-c");
15241512

1525-
if compiler.supports_path_delimiter() {
1526-
cmd.arg("--");
1527-
}
1528-
1529-
cmd.arg(&src);
1530-
15311513
if compiler.is_like_msvc() {
15321514
// On MSVC we need to make sure the LIB directory is included
15331515
// so the CRT can be found.
@@ -1539,7 +1521,37 @@ impl Build {
15391521
}
15401522
}
15411523

1542-
let output = cmd.current_dir(out_dir).output()?;
1524+
// Use stdin compilation for all flag tests to avoid issues with
1525+
// language-specific flags like -xassembler-with-cpp.
1526+
// See: https://github.com/rust-lang/cc-rs/issues/359
1527+
let flag_str = flag.to_str().unwrap_or("");
1528+
let is_language_flag = flag_str.starts_with("-x");
1529+
1530+
if !is_language_flag {
1531+
// For non-language-selection flags, explicitly specify the language
1532+
// to ensure proper validation (e.g., -std=c++11 should fail for C code)
1533+
if self.cpp {
1534+
cmd.arg("-xc++");
1535+
} else if self.cuda {
1536+
cmd.arg("-xcuda");
1537+
} else {
1538+
cmd.arg("-xc");
1539+
}
1540+
}
1541+
// For language-selection flags (like -xassembler-with-cpp), don't specify
1542+
// a language - let the flag itself determine it
1543+
1544+
cmd.arg("-");
1545+
1546+
let mut child = cmd
1547+
.stdin(std::process::Stdio::piped())
1548+
.current_dir(&out_dir)
1549+
.spawn()?;
1550+
1551+
// Close stdin immediately (empty input is sufficient for flag validation)
1552+
drop(child.stdin.take());
1553+
1554+
let output = child.wait_with_output()?;
15431555
let is_supported = output.status.success() && output.stderr.is_empty();
15441556

15451557
self.build_cache

tests/test.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,31 @@ fn gnu_flag_if_supported_cpp() {
417417
test.cmd(0).must_have("-std=c++11");
418418
}
419419

420+
// Regression test for issue #359: is_flag_supported should work with
421+
// language-specific flags (e.g., assembly flags) by using stdin compilation
422+
// instead of file-based compilation to avoid file extension issues.
423+
#[cfg(not(windows))]
424+
#[test]
425+
fn is_flag_supported_assembly_flags() {
426+
let test = Test::gnu();
427+
428+
// Test that assembly-specific flags are correctly detected as supported
429+
let build = test.gcc();
430+
let result = build.is_flag_supported("-xassembler-with-cpp");
431+
assert!(
432+
result.is_ok() && result.unwrap(),
433+
"Assembly flag -xassembler-with-cpp should be supported"
434+
);
435+
436+
// Test that normal C flags still work
437+
let build = test.gcc();
438+
let result = build.is_flag_supported("-Wall");
439+
assert!(
440+
result.is_ok() && result.unwrap(),
441+
"C flag -Wall should be supported"
442+
);
443+
}
444+
420445
#[test]
421446
fn gnu_static() {
422447
reset_env();

0 commit comments

Comments
 (0)