retroarch: provide WinMain forwarding to main on Windows (CXX_BUILD)

The Windows GUI subsystem (-mwindows) needs an entry point that the C
runtime startup calls. Some toolchains' startup calls main (Ubuntu
mingw's crt2.o); others call WinMain (MSYS2 mingw's crtexewin.o, whose
__tmainCRTStartup references WinMain). Until now RetroArch had no
WinMain of its own -- on Windows+SDL it came from SDL's shim library
libSDL2main, via the chain WinMain -> SDL_main (RetroArch's main,
renamed by SDL_main.h's "#define main SDL_main").

That chain is gone after SDL_MAIN_HANDLED (main stays main) and after
dropping -lSDL*main. On a toolchain whose GUI startup calls WinMain
(MSYS2), the link then fails:

  libmingw32.a(crtexewin.o): in function `main':
  undefined reference to `WinMain'

Provide WinMain in-tree, forwarding to main() with the CRT-supplied
__argc/__argv -- exactly the one-line bridge libSDL2main used to give
us, but no longer dependent on SDL being enabled or on which startup
object the toolchain selects. Guarded to desktop Win32 (not XBOX, not
WinRT/UWP -- uwp_main.cpp already supplies wWinMain there) and given
extern "C" for CXX_BUILD. windows.h is already included in retroarch.c
so the canonical WINAPI signature is used.

A previous attempt swapped -mwindows for -Wl,--subsystem,windows on
the theory it would keep a main-calling startup; that was wrong --
MSYS2 selects crtexewin.o for the GUI subsystem regardless of which
flag requests it, so it did not help. That Makefile change is reverted
here; -mwindows is restored and the in-tree WinMain is the actual fix.

Verified with an x86_64-w64-mingw32 g++ link harness: the full chain
(SDL_MAIN_HANDLED + no libSDL*main + this WinMain, compiled as C++
with -mwindows) links, produces a Windows GUI-subsystem binary
exporting both main and WinMain, with main not renamed.

Completes the SDL/entry-point series: decdce0 / 80f343b / 0bf5d29.
This commit is contained in:
libretroadmin authored and libretroadmin committed 2026-06-25 10:32:00 +02:00
1 parent ba850ba063
commit 9f1531a5e5
2 files changed
+27 -14

No files matched your search

+1 -14
View File
@@ -108,20 +108,7 @@ ifeq ($(HAVE_DRMINGW), 1)
endif
ifneq ($(findstring Win32,$(OS)),)
# Use the GUI subsystem (no console window) but keep the default
# CRT entry that calls main(), rather than -mwindows which selects
# crtexewin.o and requires a WinMain. RetroArch provides main() (in
# retroarch.c) and its own Win32 window; it has no WinMain. This
# mirrors the MSVC/griffin builds, which use
# '-SUBSYSTEM:WINDOWS -ENTRY:mainCRTStartup' for the same effect.
# Doing it this way means the build needs neither a hand-written
# WinMain nor SDL's WinMain shim library (-lSDL*main), and it lets
# the CXX_BUILD=1 link resolve (-mwindows -> WinMain -> SDL_main was
# the chain that broke once main correctly stayed main). RetroArch
# links the Win32 libraries it needs explicitly (gdi32, ole32,
# winmm, comdlg32, ...), so it does not rely on -mwindows to pull
# them in.
LDFLAGS += -Wl,--subsystem,windows
LDFLAGS += -mwindows
endif
ifneq ($(CXX_BUILD), 1)
+26
View File
@@ -6535,6 +6535,32 @@ int main(int argc, char *argv[])
#endif
return rarch_main(argc, argv, NULL);
}
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
/* RetroArch builds for the Windows GUI subsystem (no console window).
* Depending on the toolchain, the C runtime startup that the GUI
* subsystem pulls in calls WinMain rather than main: notably MSYS2's
* mingw-w64 selects crtexewin.o, whose __tmainCRTStartup references
* WinMain. Previously that WinMain was supplied by SDL's shim library
* (libSDL2main); now that we set SDL_MAIN_HANDLED and no longer link
* -lSDL*main, we must provide it ourselves. Forward to main() with the
* CRT-provided argc/argv. (__argc/__argv are declared by <stdlib.h> on
* MinGW/MSVC.) This is the same one-line bridge SDL2main provided, kept
* in-tree so the link does not depend on SDL being enabled.
* windows.h is already included above, so use the canonical signature. */
#ifdef __cplusplus
extern "C"
#endif
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nShowCmd)
{
(void)hInstance;
(void)hPrevInstance;
(void)lpCmdLine;
(void)nShowCmd;
return main(__argc, __argv);
}
#endif
#endif
/* DYNAMIC LIBRETRO CORE */