Skip to content

Fix Windows/MinGW cross-compilation of the yep packer#2

Open
SchwartzKamel wants to merge 2 commits into
yoyoengine:mainfrom
SchwartzKamel:fix/windows-cross-compile
Open

Fix Windows/MinGW cross-compilation of the yep packer#2
SchwartzKamel wants to merge 2 commits into
yoyoengine:mainfrom
SchwartzKamel:fix/windows-cross-compile

Conversation

@SchwartzKamel
Copy link
Copy Markdown

Summary

Fixes two issues that break building the yep resource packer for Windows when cross-compiling from a Linux host with MinGW (mingw-w64 15.x), which is how the yoyoengine CTF game distribution is built.

1. yepfs.c fails to compile under MinGW 15.x

yep_set_fs_times() uses struct _stat / _stat() on the _WIN32 branch, but <sys/stat.h> was only included on the non-Windows branch. Under MinGW 15.x, _stat is a macro expanding to _stat64i32, declared in <sys/stat.h>. Without the include:

error: implicit declaration of function '_stat64i32'

Reproduced and fixed; with the include, yepfs.c compiles cleanly for Windows (0 errors).

2. Cross builds try to run the target packer on the host

pack_resources() executes the yep binary at build time to produce .yep archives. When the consuming project cross-compiles, the in-tree yep target is built for the target platform, so the pack step tries to run a Windows PE on the Linux host:

cannot execute binary file: Exec format error   (exit 126)

This adds a host/target split: yep publishes (via global properties) which packer pack_resources() should run — the in-tree target for native builds, or a host-runnable copy when cross-compiling. The host copy is built via ExternalProject_Add (a fresh CMake invocation that doesn't inherit the cross toolchain, so it configures for the host; being non-cross it doesn't recurse). Consumers may instead point YEP_HOST_EXECUTABLE at a prebuilt host packer, with YEP_HOST_C_COMPILER / YEP_HOST_CXX_COMPILER to override host compiler detection.

Testing

End-to-end with a real mingw-w64 cross build of a consumer that uses FetchContent + pack_resources():

  • Cross (Linux → Windows): a host ELF packer is built and run, producing resources.yep; the in-tree target remains a Windows PE (what previously ran and failed).
  • Native (Linux → Linux): unchanged — the in-tree yep target is used to pack.

Both produce identical archives. Hardened for multi-config generators (deterministic host output path) and toolchain/env leakage (toolchain cleared in the nested build; explicit host-compiler overrides available).

yep_set_fs_times() uses `struct _stat` and `_stat()` on the _WIN32 branch,
but <sys/stat.h> was only included in the non-Windows branch. With MinGW 15.x,
`_stat` is a macro expanding to `_stat64i32`, whose declaration lives in
<sys/stat.h>. Without that include the Windows build fails:

    error: implicit declaration of function '_stat64i32'

Add <sys/stat.h> to the _WIN32 include block so the packer builds under MinGW.
pack_resources() runs the `yep` packer at build time to produce .yep
archives. When the consuming project cross-compiles (e.g. Linux host ->
Windows target), the in-tree `yep` target is built for the target platform,
so the resource-packing step tried to execute a target binary (e.g. a
Windows PE) on the build host and failed with "Exec format error".

Add a host/target split:

- yep's CMakeLists.txt now publishes, via global properties, which packer
  pack_resources() should invoke:
    * native build  -> the in-tree `yep` target (unchanged behavior)
    * cross build   -> a host-runnable packer
  Global properties are used so the choice is visible from the consumer
  scope (FetchContent adds yep in a child scope) and is recomputed on every
  configure (so it stays correct across reconfigures).

- When cross-compiling and no packer is supplied, build one for the host via
  ExternalProject_Add. The nested CMake invocation does not inherit the cross
  toolchain, so it configures for the host; being non-cross, it does not
  recurse. The host binary is emitted to a deterministic path (robust for
  multi-config generators).

- Consumers may instead set YEP_HOST_EXECUTABLE to a prebuilt host packer
  (validated to exist), and YEP_HOST_C_COMPILER / YEP_HOST_CXX_COMPILER to
  override host compiler detection.

Verified end-to-end with a mingw-w64 cross build: the host ELF packer is
built and run, producing resources.yep, while the in-tree target remains a
Windows PE. Native (non-cross) builds are unchanged.
@zoogies
Copy link
Copy Markdown
Member

zoogies commented Jun 2, 2026

#2 is an interesting problem, unique to MingW cross compilation. I'll have a look at this soon and see if I can think of a better way...

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