floooh / sokol-zig

Zig bindings for the sokol headers (https://github.com/floooh/sokol)
zlib License
341 stars 46 forks source link

cross compiling sokol_app.h for windows #74

Open danielchasehooper opened 1 month ago

danielchasehooper commented 1 month ago

I have a sokol app written in C that I would like to cross compile from mac to windows. (there is no zig code, I'm just using zig as a C cross compiler)

building with the following command produces an exe that shows a "missing ucrtbase.dll" error when launched on windows 7.

daniels-mac$ zig cc -I include -ld3d11 -lgdi32 -target x86_64-windows-gnu -DSOKOL_WIN32_FORCE_MAIN -DSOKOL_D3D11 -o test.exe src/main.c

I tried instead compiling these other ways but they each produced other errors:

zig cc -I include -ld3d11 -lgdi32 -target x86_64-windows-gnu -DSOKOL_D3D11 -o $@ src/main.c  # linker error: missing main symbol

zig cc -I include -ld3d11 -lgdi32 -target x86_64-windows-msvc -DSOKOL_D3D11 -o $@ src/sokol_main.c # linker error: unable to find Dynamic system library 'd3d11' using strategy 'paths_first'. searched paths: none

let me know if you need a project zip to reproduce.

floooh commented 1 month ago

Just a couple of tidbits before I'll get around to actually try the result on Windows:

Slightly different scenario (a Zig+sokol project with a build.zig), but in the pacman.zig project (https://github.com/floooh/pacman.zig), I can compile a Windows exe on macOS with:

zig build -Dtarget=x86_64-windows

This will link the following Windows DLLs:

https://github.com/floooh/sokol-zig/blob/7e23aa316df157b38ea03841a0c1f48eeffaf784/build.zig#L251-L260

Also, I think this uses MUSL instead of the MSVC C library (e.g. it shouldn't require the ucrtbase.dll at runtime). I did not yet actually try running this executable on Windows, but I will check this later (not today though).

For a C application compiled with Zig I can imagine that there will be problems with main() vs WinMain() entry points (sokol_app.h uses WinMain on Windows, unless SOKOL_WIN32_FORCE_MAIN or SOKOL_NO_ENTRY is defined). sokol-zig apps define SOKOL_NO_ENTRY and instead use the regular Zig main function as entry point.

Zig can be instructed to build a WinMain executable via a 'Target.subsystem', not sure how that's activated from the cmdline though, and I also didn't experiment with this yet:

https://ziglang.org/documentation/master/std/#std.builtin.subsystem

PS: for the missing ucrtbase.dll runtime error you're seeing, this basically says that the executable was not statically linked with the Microsoft C runtime but instead tries to load the C runtime DLL (which AFAIK isn't present by default on Windows but is expected to be installed by applications - however, that article I link below seems to say otherwise hmm...).

On Visual Studio the better fix (IMHO) is to use static linking for the C runtime (see: https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-170). I don't know if this option is available on Zig. But what should definitely work is to statically link with MUSL (which seems to be the case when using the target x86_64-windows). If this then still requires ucrtbase.dll when starting then I'm out of ideas though. It should be possible to investigate where that depedency comes from via the MSVC command line tool dumpbin (https://learn.microsoft.com/en-us/cpp/build/reference/dumpbin-reference?view=msvc-170).

floooh commented 1 month ago

Btw that cross-compiled pacman exectuable (via zig build -Dtarget=x86_64-windows) works on my Windows 10 laptop.

kassane commented 1 week ago

Cross-compiling for Windows target in Zig defaults to MinGW, the reason being indisputable. However, it still lacks some support for Windows libraries in a non-Windows environment.

Unlike msvc-wine(docker), I tried using xwin with zig (Linux/macos/Windows) hermetic building exclusively to msvc and linking extra Windows libraries (vsruntime + winsdk) C and C++.