diff --git a/src/lib.rs b/src/lib.rs index 4a706817..c5d42f7e 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 cf49b6b9..ad606060 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 { @@ -403,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 } + ) && !self.cuda + } } /// Represents the family of tools this tool belongs to. diff --git a/tests/test.rs b/tests/test.rs index b88a8190..84d3e005 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");