Skip to content

Commit 8a45e2b

Browse files
Stop passing an invalid target to llvm-mingw's cross-compilation wrappers (#1495)
The cross-compilation toolchains distributed by the `llvm-mingw` project for building code for the `*-pc-windows-gnullvm` targets have a wrapper script in place of their `clang` binaries that calls them with a specific target, much like it has been the case with the Android NDK. When `cc-rs` sets a explicit `--target` flag, the wrapper script breaks down, and is no longer able to use the proper linker and libraries. To improve on this situation and make it possible to cross-compile Rust projects that depend on building C code with `cc-rs`, let's skip passing this flag when cross-compilation with such a wrapper script is attempted.
1 parent a0b2fd6 commit 8a45e2b

File tree

1 file changed

+28
-0
lines changed

1 file changed

+28
-0
lines changed

src/lib.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3041,6 +3041,23 @@ impl Build {
30413041
};
30423042
}
30433043

3044+
// Under cross-compilation scenarios, llvm-mingw's clang executable is just a
3045+
// wrapper script that calls the actual clang binary with a suitable `--target`
3046+
// argument, much like the Android NDK case outlined above. Passing a target
3047+
// argument ourselves in this case will result in an error, as they expect
3048+
// targets like `x86_64-w64-mingw32`, and we can't always set such a target
3049+
// string because it is specific to this MinGW cross-compilation toolchain.
3050+
//
3051+
// For example, the following command will always fail due to using an unsuitable
3052+
// `--target` argument we'd otherwise pass:
3053+
// $ /opt/llvm-mingw-20250613-ucrt-ubuntu-22.04-x86_64/bin/x86_64-w64-mingw32-clang --target=x86_64-pc-windows-gnu dummy.c
3054+
//
3055+
// Code reference:
3056+
// https://github.com/mstorsjo/llvm-mingw/blob/a1f6413e5c21fd74b64137b56167f4fba500d1d8/wrappers/clang-target-wrapper.sh#L31
3057+
if !cfg!(windows) && target.os == "windows" && is_llvm_mingw_wrapper(&tool.path) {
3058+
tool.has_internal_target_arg = true;
3059+
}
3060+
30443061
// If we found `cl.exe` in our environment, the tool we're returning is
30453062
// an MSVC-like tool, *and* no env vars were set then set env vars for
30463063
// the tool that we're returning.
@@ -4244,6 +4261,17 @@ fn android_clang_compiler_uses_target_arg_internally(clang_path: &Path) -> bool
42444261
false
42454262
}
42464263

4264+
fn is_llvm_mingw_wrapper(clang_path: &Path) -> bool {
4265+
if let Some(filename) = clang_path
4266+
.file_name()
4267+
.and_then(|file_name| file_name.to_str())
4268+
{
4269+
filename.ends_with("-w64-mingw32-clang") || filename.ends_with("-w64-mingw32-clang++")
4270+
} else {
4271+
false
4272+
}
4273+
}
4274+
42474275
// FIXME: Use parsed target.
42484276
fn autodetect_android_compiler(raw_target: &str, gnu: &str, clang: &str) -> PathBuf {
42494277
let new_clang_key = match raw_target {

0 commit comments

Comments
 (0)