Skip to content

Commit bbc61bd

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 bbc61bd

File tree

2 files changed

+91
-30
lines changed

2 files changed

+91
-30
lines changed

src/lib.rs

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -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,13 +1510,10 @@ 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-
1531-
if compiler.is_like_msvc() {
1513+
// MSVC doesn't support stdin compilation, so use file-based approach for it
1514+
// For GCC/Clang, use stdin to support language-selection flags like -xassembler-with-cpp
1515+
// See: https://github.com/rust-lang/cc-rs/issues/359
1516+
let is_supported = if compiler.is_like_msvc() {
15321517
// On MSVC we need to make sure the LIB directory is included
15331518
// so the CRT can be found.
15341519
for (key, value) in &tool.env {
@@ -1537,10 +1522,61 @@ impl Build {
15371522
break;
15381523
}
15391524
}
1540-
}
15411525

1542-
let output = cmd.current_dir(out_dir).output()?;
1543-
let is_supported = output.status.success() && output.stderr.is_empty();
1526+
// Use file-based compilation for MSVC
1527+
let src = if self.cuda {
1528+
assert!(self.cpp);
1529+
out_dir.join("flag_check.cu")
1530+
} else if self.cpp {
1531+
out_dir.join("flag_check.cpp")
1532+
} else {
1533+
out_dir.join("flag_check.c")
1534+
};
1535+
1536+
if !src.exists() {
1537+
let mut f = fs::File::create(&src)?;
1538+
write!(f, "int main(void) {{ return 0; }}")?;
1539+
}
1540+
1541+
if compiler.supports_path_delimiter() {
1542+
cmd.arg("--");
1543+
}
1544+
cmd.arg(&src);
1545+
1546+
let output = cmd.current_dir(&out_dir).output()?;
1547+
output.status.success() && output.stderr.is_empty()
1548+
} else {
1549+
// Use stdin compilation for GCC/Clang
1550+
let flag_str = flag.to_string_lossy();
1551+
let is_language_flag = flag_str.starts_with("-x");
1552+
1553+
if !is_language_flag {
1554+
// For non-language-selection flags, explicitly specify the language
1555+
// to ensure proper validation (e.g., -std=c++11 should fail for C code)
1556+
if self.cpp {
1557+
cmd.arg("-xc++");
1558+
} else if self.cuda {
1559+
cmd.arg("-xcuda");
1560+
} else {
1561+
cmd.arg("-xc");
1562+
}
1563+
}
1564+
// For language-selection flags (like -xassembler-with-cpp), don't specify
1565+
// a language - let the flag itself determine it
1566+
1567+
cmd.arg("-");
1568+
1569+
let mut child = cmd
1570+
.stdin(std::process::Stdio::piped())
1571+
.current_dir(&out_dir)
1572+
.spawn()?;
1573+
1574+
// Close stdin immediately (empty input is sufficient for flag validation)
1575+
drop(child.stdin.take());
1576+
1577+
let output = child.wait_with_output()?;
1578+
output.status.success() && output.stderr.is_empty()
1579+
};
15441580

15451581
self.build_cache
15461582
.known_flag_support_status_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)