retroarch: opt out of SDL's main shim (SDL_MAIN_HANDLED)

RetroArch has its own entry point (main in retroarch.c) and runloop,
creates its own Win32 window, and initialises SDL subsystems
explicitly via SDL_Init/SDL_InitSubSystem in the SDL audio/video/input
drivers. SDL is a driver backend here, not the application framework.

retroarch.c includes SDL.h for SDL_WasInit/SDL_Quit in sdl_exit(). On
Windows, SDL.h pulls in SDL_main.h which does "#define main SDL_main"
and expects libSDL2main's WinMain to be the real entry point and call
SDL_main. That shim was never wanted: the Windows builds already set
-mwindows (GNU) and -ENTRY:mainCRTStartup (griffin/msvc), so the CRT
startup -> main path is the intended entry.

In C the implicit rename happened to chain through and link. Under
CXX_BUILD=1, retroarch.c compiles as C++, so the renamed entry is a
C++ SDL_main that no longer matches the C symbol libSDL2main's WinMain
calls:

  libSDL2main.a(SDL_windows_main.c.obj): undefined reference to SDL_main

Define SDL_MAIN_HANDLED before including SDL.h so SDL neither renames
main nor supplies WinMain; main stays main and links via the CRT
entry, and libSDL2main's WinMain object is never extracted (nothing
references it). Per the SDL_MAIN_HANDLED contract, call
SDL_SetMainReady() in main() before the drivers lazily SDL_Init, so
subsystem init does not fail/warn on platforms that check the flag.

Both are guarded for the SDL/SDL2/SDL3 configs; non-SDL builds are
unaffected. This is correct independent of CXX_BUILD; the C++ build
merely exposed the latent mismatch.

Follow-up to the CXX_BUILD fixes in 059ca26 / 7712d87 / a624ae1 /
8102d80 / 9c4e30a.
This commit is contained in:
libretroadmin authored and libretroadmin committed 2026-06-25 10:13:13 +02:00
1 parent 9c4e30a22e
commit decdce0439
1 file changed
+24
+24
View File
@@ -223,9 +223,27 @@
#include "ai/game_ai.h"
#endif
/* RetroArch provides its own entry point (main, below) and runloop,
* creates its own Win32 window (gfx/common/win32_common.c), and
* initialises SDL subsystems explicitly (SDL_Init/SDL_InitSubSystem
* in the SDL audio/video/input drivers). SDL is used purely as a
* driver backend, never as the application framework. Tell SDL not to
* #define main->SDL_main and not to supply its own WinMain: without
* this, SDL.h renames our main to SDL_main and the link pulls in
* libSDL2main's WinMain, which (a) is unwanted given -mwindows /
* -ENTRY:mainCRTStartup already designate our entry point, and (b)
* breaks under CXX_BUILD where the renamed main is compiled as C++
* and no longer matches the C 'SDL_main' that WinMain calls
* (undefined reference to SDL_main). */
#if defined(HAVE_SDL3)
#ifndef SDL_MAIN_HANDLED
#define SDL_MAIN_HANDLED
#endif
#include <SDL3/SDL.h>
#elif defined(HAVE_SDL) || defined(HAVE_SDL2) || defined(HAVE_SDL_DINGUX)
#ifndef SDL_MAIN_HANDLED
#define SDL_MAIN_HANDLED
#endif
#include "SDL.h"
#endif
@@ -6509,6 +6527,12 @@ extern "C"
#endif
int main(int argc, char *argv[])
{
/* We opted out of SDL's main shim with SDL_MAIN_HANDLED (see the
* SDL include block above), so tell SDL its entry point has run
* before any subsystem is initialised lazily by the SDL drivers. */
#if defined(HAVE_SDL3) || defined(HAVE_SDL) || defined(HAVE_SDL2) || defined(HAVE_SDL_DINGUX)
SDL_SetMainReady();
#endif
return rarch_main(argc, argv, NULL);
}
#endif