@@ -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
0 commit comments