libsdl-org/sdl2-compat

SDL_*RunApp

DanielGibson opened this issue · 17 comments

SDL2 has SDL_WinRTRunApp(), SDL_GDKRunApp(), and SDL_UIKitRunApp(); in SDL3 they're unified as SDL_RunApp().

As I have no idea how to build sdl2-compat for any of those platforms (in SDL3 they're built with VS solutions instead of CMake), I can't really implement this to create a pull request..

The three functions should be implemented in sdl2-compat (and enabled when building for the corresponding platform), the implementations should look like:

int SDLCALL SDL_WinRTRunApp(SDL_main_func mainFunction, void *reserved)
{
    return SDL3_RunApp(0, NULL, mainFunction, reserved);
}

int SDLCALL SDL_GDKRunApp(SDL_main_func mainFunction, void *reserved)
{
    return SDL3_RunApp(0, NULL, mainFunction, reserved);
}

int SDLCALL SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction)
{
    return SDL3_RunApp(argc, argv, mainFunction, NULL);
}
1bsyl commented

added in e843119
check it builds, on linux and still runs, but not sur if this is 100% ok!

The windows build using cmake + MSVC in github CI fails with duplicated
main symbol:
https://github.com/libsdl-org/sdl2-compat/actions/runs/4064214712/jobs/6997379618

MSBuild version 17.4.1+9a89d02ff for .NET Framework
  Checking Build System
  Building Custom Rule D:/a/sdl2-compat/sdl2-compat/CMakeLists.txt
  sdl2_compat.c
  SDL_dynapi.c
  Generating Code...
SDL_dynapi.obj : error LNK2005: main already defined in sdl2_compat.obj [D:\a\sdl2-compat\sdl2-compat\build\SDL2.vcxproj]
SDL_dynapi.obj : error LNK2005: WinMain already defined in sdl2_compat.obj [D:\a\sdl2-compat\sdl2-compat\build\SDL2.vcxproj]
     Creating library D:/a/sdl2-compat/sdl2-compat/build/Debug/SDL2.lib and object D:/a/sdl2-compat/sdl2-compat/build/Debug/SDL2.exp
sdl2_compat.obj : error LNK2019: unresolved external symbol SDL_main referenced in function main [D:\a\sdl2-compat\sdl2-compat\build\SDL2.vcxproj]
SDL_dynapi.obj : error LNK2001: unresolved external symbol SDL_main [D:\a\sdl2-compat\sdl2-compat\build\SDL2.vcxproj]
sdl2_compat.obj : error LNK2019: unresolved external symbol IGNORE_THIS_VERSION_OF_SDL_RunApp referenced in function main [D:\a\sdl2-compat\sdl2-compat\build\SDL2.vcxproj]
SDL_dynapi.obj : error LNK2001: unresolved external symbol IGNORE_THIS_VERSION_OF_SDL_RunApp [D:\a\sdl2-compat\sdl2-compat\build\SDL2.vcxproj]
D:\a\sdl2-compat\sdl2-compat\build\Debug\SDL2.dll : fatal error LNK1120: 2 unresolved externals [D:\a\sdl2-compat\sdl2-compat\build\SDL2.vcxproj]

However, nmake /f Makefile.vc builds and links fine for me. The Watcom
and MinGW windows builds link fine too.

1bsyl commented

not sure what should be done, but I see there is some doc:

If you provide your own WinMain(), you may define SDL_MAIN_HANDLED

maybe @DanielGibson knows better:

In the meantime, here's some attempt: #39

However, nmake /f Makefile.vc builds and links fine for me. The Watcom and MinGW windows builds link fine too.

Silly me, I was testing build with an older revision: The current revision fails linkage with all windows compilers.

Simply defining SDL_MAIN_HANDLED before including SDL_main.h fixes
things. I pushed a6405e1 for that, and I also defined SDL_MAIN_HANDLED
universally, not just for windows: If you think that's wrong, tell me.

I also pushed 0d5f97f to undefine SDL_WinRTRunApp, SDL_UIKitRunApp and SDL_GDKRunApp in wrapper.h

1bsyl commented

ok!

not sure what should be done, but I see there is some doc:

If you provide your own WinMain(), you may define SDL_MAIN_HANDLED

maybe @DanielGibson knows better:

SDL_MAIN_HANDLED should be fine here, but in general, with SDL3 there's actually two (related) #defines you can set:

  • #define SDL_MAIN_HANDLED - like in SDL2, #define main SDL_main is skipped, and so are the #defines for SDL_MAIN_NEEDED/SDL_MAIN_AVAILABLE and of course the actual main()/WinMain(), ... implementation.
  • #define SDL_MAIN_NOIMPL - just skips the main() (WinMain(), whatever) implementation, but does set SDL_MAIN_NEEDED and SDL_MAIN_AVAILABLE, if appropriate for the platform, and also includes #define main SDL_main - mostly useful for SDL-internal usage (there was one place where SDL_MAIN_NEEDED/AVAILABLE was used, but obviously we didn't want to drag an actual main() implementation into libSDL itself).
    Also useful for WinRT, if you have your main() implementation in a plain-C source file, you can #define SDL_MAIN_NOIMPL there before #include <SDL3/SDL_main.h> (so your main is renamed to SDL_main, but WinMain() is not implemented there), and then in another (.cpp) file you do the regular #include <SDL3/SDL_main.h> to drag in the WinMain implementation (which must be in C++ for WinRT).
    (Actually, in WinRT you can just #include <SDL3/SDL_main.h> in both files, but the compiler will show a warning in the plain-C file to remind you to include SDL_main.h in a C++ source file - #define SDL_MAIN_NOIMPL suppresses that warning)

SDL_MAIN_HANDLED should be fine here, but in general, with SDL3 there's actually two (related) #defines you can set:

We include SDL_main.h of SDL3 only when building the sdl2-compat library:
What is the suggestion if SDL_MAIN_HANDLED alone is not enough?

1bsyl commented

@sezero I've just added "include SDL_main.h" in the previous commit. maybe this is wrong !

What is the suggestion if SDL_MAIN_HANDLED alone is not enough?

what do you mean with "not enough"?

@sezero I've just added "include SDL_main.h" in the previous commit. maybe this is wrong !

Without it, build fails:

In file included from sdl2_compat.c:111:
sdl3_syms.h:917: error: expected declaration specifiers or ‘...’ before ‘SDL_main_func’

What is the suggestion if SDL_MAIN_HANDLED alone is not enough?

what do you mean with "not enough"?

Well, you mentioned other macros to define, so I asserted SDL_MAIN_HANDLED may
not be enough??

It is enough (well, except that for this specific usecase you need to #undef a few things, as you have already done, but that's not an issue for regular users who don't use SDL2 and SDL3 headers/symbols at the same time), as I wrote "SDL_MAIN_HANDLED should be fine here".

FWIW, in this case SDL_MAIN_NOIMPL probably would've worked just as well as SDL_MAIN_HANDLED, unless SDL_MAIN_NEEDED and/or SDL_MAIN_AVAILABLE would create additional conflicts (and thus would've to be #undef'ed as well).

I was just describing the two similar things that can be defined, and what their differences are, because I thought it'd be good to know in general :)

Is there more to do, or is this ticket closable now?

I think it can be closed, thanks you two! :)