file.c: include <windows.h> before <stringapiset.h>

nasmlib/file.c included <stringapiset.h> directly (for
MultiByteToWideChar()/CompareStringOrdinal()) without first including
<windows.h>. Windows SDK headers like <stringapiset.h> are only
guaranteed to work when pulled in through the normal <windows.h>
pipeline, which sets up SDK-internal architecture macros (_X86_,
_AMD64_, ...) derived from the compiler's own _M_IX86/_M_X64/etc.
Including them directly skips that setup and can fail with a
'No Target Architecture' #error from <winnt.h> -- which is exactly
what happened building with a real cl.exe/nmake in CI.

<windows.h> is deliberately *not* pulled in globally from compiler.h:
it #defines NEAR and FAR as legacy no-op calling-convention keywords,
which clash with NASM's own NEAR/FAR opflags bits (include/opflags.h).
Keep the inclusion local to file.c, the only file that currently needs
Windows API declarations, guarded by WIN32_LEAN_AND_MEAN to keep the
exposed surface minimal.

Confirmed fixed with a real MSVC (cl.exe/nmake) build in CI.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
H. Peter Anvin (Intel) 2026-07-07 13:12:06 -07:00
parent e2f38a8aed
commit ace0078261

View file

@ -45,7 +45,24 @@
*/
#ifdef _WIN32
#include <wchar.h>
#include <stringapiset.h>
/*
* <windows.h> is needed for MultiByteToWideChar()/CompareStringOrdinal()
* (normally declared via <stringapiset.h>). Windows SDK headers like
* <stringapiset.h> are only guaranteed to work when pulled in through the
* normal <windows.h> pipeline, which sets up SDK-internal architecture
* macros (_X86_, _AMD64_, ...) derived from the compiler's own
* _M_IX86/_M_X64/etc; including such a leaf header directly can fail with
* a "No Target Architecture" #error from <winnt.h>.
*
* <windows.h> is deliberately *not* included from compiler.h: it #defines
* NEAR and FAR (as legacy no-op calling-convention keywords), which clash
* with NASM's own NEAR/FAR opflags bits from opflags.h. Keep the
* inclusion local to the few files, like this one, that actually need
* Windows API declarations, and define WIN32_LEAN_AND_MEAN to keep the
* exposed surface (winsock, GDI, shell, DDE, RPC, crypto, ...) minimal.
*/
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
typedef wchar_t *os_filename;
typedef wchar_t os_fopenflag;