Skip to content

Set windres target explicitly to better support LLVM cross-compilation#33

Merged
BenjaminRi merged 1 commit intoBenjaminRi:masterfrom
AlexTMjugador:fix/explicit-windres-target
Jul 13, 2025
Merged

Set windres target explicitly to better support LLVM cross-compilation#33
BenjaminRi merged 1 commit intoBenjaminRi:masterfrom
AlexTMjugador:fix/explicit-windres-target

Conversation

@AlexTMjugador
Copy link
Contributor

@AlexTMjugador AlexTMjugador commented Jul 9, 2025

As stated on its man page, windres uses a default binutils BFD format when the --target option is not explicitly set. This usually works fine with the binutils windres implementation even in cross-compilation scenarios, as these have to be set up with a toolchain that's already wired to produce objects for the desired target architecture.

However, the LLVM toolchain ships with a windres implementation that has a significant behavioral difference in this regard: LLVM is a native cross-platform compiler, which means that no separate toolchains are needed to target a different platform. As such, LLVM's windres defaults to a target that matches the host platform, producing artifacts that target the wrong platform when cross-compiling.

To fix this situation, let's explicitly pass a target to windres that matches the desired target architecture (all Windows targets can be assumed to generate PE files), which helps ensuring that no different defaults cause miscompilations.

I've verified this change to make cross-compilation from an AArch64 MacOS host to the x86_64-pc-windows-gnullvm target possible (as that target, being GNU-like, goes through the windres path), without breaking cross-compilation to x86_64-pc-windows-gnu via the more classical binutils-based (non-LLVM) MinGW toolchain.

[As stated on its man
page](https://man7.org/linux/man-pages/man1/windres.1.html), `windres`
uses a default binutils`BFD format when the `--target` option is not
explicitly set. This usually works fine with the binutils `windres`
implementation even in cross-compilation scenarios, as these have to be
set up with a toolchain that's already wired to produce objects for the
desired target architecture.

However, the LLVM toolchain ships with a `windres` implementation that
has a significant behavioral difference in this regard: LLVM is a native
cross-platform compiler, which means that no separate toolchains are
needed to target a different platform. As such, [LLVM's `windres`
defaults to a target that matches the host
platform](https://github.com/llvm/llvm-project/blob/1431f8f76fa2270cedc88efdebcc236bf374b144/llvm/tools/llvm-rc/llvm-rc.cpp#L423-L436),
producing artifacts that target the wrong platform when cross-compiling.

To fix this situation, let's explicitly pass a target to `windres` that
matches the desired target architecture (all Windows targets can be
assumed to generate PE files), which helps ensuring that no different
defaults cause miscompilations.

I've verified this change to make cross-compilation from an AArch64
MacOS host to the `x86_64-pc-windows-gnullvm` target possible, without
breaking cross-compilation to `x86_64-pc-windows-gnu` via the more
classical binutils-based (non-LLVM) MinGW toolchain.
@BenjaminRi
Copy link
Owner

Thank you for your contribution, this looks good. Unless I discover some breakage caused by the change, I will merge this shortly.

@BenjaminRi BenjaminRi merged commit f015de2 into BenjaminRi:master Jul 13, 2025
4 checks passed
@BenjaminRi
Copy link
Owner

Your change is merged and was released in version 0.1.23.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants