Linking kernel32 when cross compiling

I’m on macOS and cross compiling to windows. This has been working fine until I needed to use GetCurrentDirectory(), which requires linking Kernel32.

Despite adding -lKernel32, the following build command gets the linker error undefined symbol: GetCurrentDirectory:

zig cc  -DSOKOL_D3D11 \
		-target aarch64-windows-gnu \
		-lKernel32 -lopengl32 -lgdi32 -ld3d11 -lwinmm -Wl,--subsystem,windows \
		src/win/info.rc src/main.c src/sokol.c src/win/admin.manifest \
		-o build/app-arm.exe

Is there a way to cross compile and link against Kernel32?
zig version 0.15.1

Just to double check can you try -lkernel32 (lower case)? I noticed the respective file is spelled lib/libc/mingw/lib-common/kernel32.def.in in the Zig installation.

Also the exported symbols are:

GetCurrentDirectoryA
GetCurrentDirectoryW

I know there is some C preprocessor trickery to make GetCurrentDirectory lower to the A or W version depending on UNICODE but personally I like to explicitly call the W one since it has behavior independent of the system-wide code page setting that the user can arbitrarily modify at any point in time.

Edit: actually the case shouldn’t matter… kernel32 is always linked on that target anyway:

pub const always_link_libs = [_][]const u8{
    "api-ms-win-crt-conio-l1-1-0",
    "api-ms-win-crt-convert-l1-1-0",
    "api-ms-win-crt-environment-l1-1-0",
    "api-ms-win-crt-filesystem-l1-1-0",
    "api-ms-win-crt-heap-l1-1-0",
    "api-ms-win-crt-locale-l1-1-0",
    "api-ms-win-crt-math-l1-1-0",
    "api-ms-win-crt-multibyte-l1-1-0",
    "api-ms-win-crt-private-l1-1-0",
    "api-ms-win-crt-process-l1-1-0",
    "api-ms-win-crt-runtime-l1-1-0",
    "api-ms-win-crt-stdio-l1-1-0",
    "api-ms-win-crt-string-l1-1-0",
    "api-ms-win-crt-time-l1-1-0",
    "api-ms-win-crt-utility-l1-1-0",
    "advapi32",
    "kernel32",
    "ntdll",
    "shell32",
    "user32",
};
1 Like

Ah yeah, it was C preprocessor trickery. Maybe I missed it or docs don’t make it clear that GetCurrentDirectory is a macro and I had manually forward declared it instead of including windows.h. I’m too much of a windows noob to remember that lots of functions are macros.

Thanks!

2 Likes

FWIW when I do zig build -Dtarget=aarch64-windows-gnu examples in the sokol-zig repository (GitHub - floooh/sokol-zig: Zig bindings for the sokol headers (https://github.com/floooh/sokol)) the examples seem to link correctly and I get .exe files in zig-out/bin (I never tried to run them though).

The linkage for Windows is setup here:

Those link settings should ‘trickle up’ the build process if you’re using sokol-zig as a package.

…specifically for Windows, the sokol headers also have #pragma comment(lib, ...) specifications, but I’m not sure if Zig can pick those up (IIRC Clang does at least for ‘msvc’ targets):