From 3fe0e09fa41dc9ee53d6c2c245253d58d09867f6 Mon Sep 17 00:00:00 2001 From: Jiahao XU <30436523+NobodyXu@users.noreply.github.com> Date: Mon, 23 Dec 2024 00:35:08 +1100 Subject: [PATCH 1/4] Fix compiler family detection issue with clang-cl Fixed #1327 Signed-off-by: Jiahao XU --- src/tool.rs | 99 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 58 insertions(+), 41 deletions(-) diff --git a/src/tool.rs b/src/tool.rs index cf49b6b93..a4d8ad12b 100644 --- a/src/tool.rs +++ b/src/tool.rs @@ -105,6 +105,46 @@ impl Tool { .unwrap_or_default() } + fn guess_family_from_stdout( + stdout: &str, + path: &Path, + cargo_output: &CargoOutput, + ) -> Result { + 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, &{ + // 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(); + + let clang = stdout.contains(r#""clang""#); + let gcc = stdout.contains(r#""gcc""#); + let emscripten = stdout.contains(r#""emscripten""#); + let vxworks = stdout.contains(r#""VxWorks""#); + + match (clang, accepts_cl_style_flags, gcc, emscripten, vxworks) { + (clang_cl, true, _, false, false) => Ok(ToolFamily::Msvc { clang_cl }), + (true, _, _, _, false) | (_, _, _, true, false) => Ok(ToolFamily::Clang { + zig_cc: is_zig_cc(path, cargo_output), + }), + (false, false, true, _, false) | (_, _, _, _, true) => Ok(ToolFamily::Gnu), + (false, false, false, false, false) => { + cargo_output.print_warning(&"Compiler family detection failed since it does not define `__clang__`, `__GNUC__`, `__EMSCRIPTEN__` or `__VXWORKS__`, also does not accept cl style flag `-?`, fallback to treating it as GNU"); + Err(Error::new( + ErrorKind::ToolFamilyMacroNotFound, + "Expects macro `__clang__`, `__GNUC__` or `__EMSCRIPTEN__`, `__VXWORKS__` or accepts cl style flag `-?`, but found none", + )) + } + } + } + fn detect_family_inner( path: &Path, cargo_output: &CargoOutput, @@ -140,53 +180,30 @@ impl Tool { tmp_file.sync_data()?; drop(tmp_file); + // When expanding the file, the compiler prints a lot of information to stderr + // that it is not an error, but related to expanding itself. + // + // cc would have to disable warning here to prevent generation of too many warnings. + let mut compiler_detect_output = cargo_output.clone(); + compiler_detect_output.warnings = compiler_detect_output.debug; + let stdout = run_output( Command::new(path).arg("-E").arg(tmp.path()), path, - // When expanding the file, the compiler prints a lot of information to stderr - // that it is not an error, but related to expanding itself. - // - // cc would have to disable warning here to prevent generation of too many warnings. - &{ - let mut cargo_output = cargo_output.clone(); - cargo_output.warnings = cargo_output.debug; - cargo_output - }, + &compiler_detect_output, )?; let stdout = String::from_utf8_lossy(&stdout); - 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, &{ - // 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(); - - let clang = stdout.contains(r#""clang""#); - let gcc = stdout.contains(r#""gcc""#); - let emscripten = stdout.contains(r#""emscripten""#); - let vxworks = stdout.contains(r#""VxWorks""#); - - match (clang, accepts_cl_style_flags, gcc, emscripten, vxworks) { - (clang_cl, true, _, false, false) => Ok(ToolFamily::Msvc { clang_cl }), - (true, _, _, _, false) | (_, _, _, true, false) => Ok(ToolFamily::Clang { - zig_cc: is_zig_cc(path, cargo_output), - }), - (false, false, true, _, false) | (_, _, _, _, true) => Ok(ToolFamily::Gnu), - (false, false, false, false, false) => { - cargo_output.print_warning(&"Compiler family detection failed since it does not define `__clang__`, `__GNUC__`, `__EMSCRIPTEN__` or `__VXWORKS__`, also does not accept cl style flag `-?`, fallback to treating it as GNU"); - Err(Error::new( - ErrorKind::ToolFamilyMacroNotFound, - "Expects macro `__clang__`, `__GNUC__` or `__EMSCRIPTEN__`, `__VXWORKS__` or accepts cl style flag `-?`, but found none", - )) - } + if stdout.contains("-Wslash-u-filename") { + let stdout = run_output( + Command::new(path).arg("-E").arg("--").arg(tmp.path()), + path, + &compiler_detect_output, + )?; + let stdout = String::from_utf8_lossy(&stdout); + guess_family_from_stdout(&stdout, path, cargo_output) + } else { + guess_family_from_stdout(&stdout, path, cargo_output) } } let detect_family = |path: &Path| -> Result { From 2e917e7cc84fe914d404afacf4d982dfb87ea2c8 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jan 2025 00:56:30 +1100 Subject: [PATCH 2/4] Use `--` delimiter for any clang-like compiler to disambiguous path from arguments. Signed-off-by: Jiahao XU --- src/lib.rs | 8 +++++++- src/tool.rs | 8 ++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 4a706817f..c5d42f7ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -725,6 +725,10 @@ impl Build { }, ); + if compiler.supports_path_delimiter() { + cmd.arg("--"); + } + cmd.arg(&src); // On MSVC skip the CRT by setting the entry point to `main`. @@ -1795,7 +1799,8 @@ impl Build { if is_asm { cmd.args(self.asm_flags.iter().map(std::ops::Deref::deref)); } - if compiler.family == (ToolFamily::Msvc { clang_cl: true }) && !is_assembler_msvc { + + if compiler.supports_path_delimiter() && !is_assembler_msvc { // #513: For `clang-cl`, separate flags/options from the input file. // When cross-compiling macOS -> Windows, this avoids interpreting // common `/Users/...` paths as the `/U` flag and triggering @@ -1803,6 +1808,7 @@ impl Build { cmd.arg("--"); } cmd.arg(&obj.src); + if cfg!(target_os = "macos") { self.fix_env_for_apple_os(&mut cmd)?; } diff --git a/src/tool.rs b/src/tool.rs index a4d8ad12b..d831884dc 100644 --- a/src/tool.rs +++ b/src/tool.rs @@ -420,6 +420,14 @@ impl Tool { pub fn is_like_msvc(&self) -> bool { matches!(self.family, ToolFamily::Msvc { .. }) } + + /// Supports using `--` delimiter to separate arguments and path to source files. + pub(crate) fn supports_path_delimiter(&self) -> bool { + matches!( + self.family, + ToolFamily::Clang { .. } | ToolFamily::Msvc { clang_cl: true } + ) + } } /// Represents the family of tools this tool belongs to. From 216180364e80023eb825b13e13b368a8f58a5b40 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jan 2025 01:11:25 +1100 Subject: [PATCH 3/4] Fix gnu_no_dash_dash Signed-off-by: Jiahao XU --- tests/test.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/test.rs b/tests/test.rs index b88a81904..84d3e005f 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -405,6 +405,8 @@ fn gnu_static() { } #[test] +// on macOS, cc/gcc is link to apple clang +#[cfg_attr(target_os = "macos", ignore)] fn gnu_no_dash_dash() { let test = Test::gnu(); test.gcc().file("foo.c").compile("foo"); From 5d5956de03c143eba21d3187101bef0b40bbbc76 Mon Sep 17 00:00:00 2001 From: Jiahao XU Date: Tue, 7 Jan 2025 01:14:11 +1100 Subject: [PATCH 4/4] Do not use `--` for cuda Signed-off-by: Jiahao XU --- src/tool.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tool.rs b/src/tool.rs index d831884dc..ad6060608 100644 --- a/src/tool.rs +++ b/src/tool.rs @@ -426,7 +426,7 @@ impl Tool { matches!( self.family, ToolFamily::Clang { .. } | ToolFamily::Msvc { clang_cl: true } - ) + ) && !self.cuda } }