libsdl-org / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
9.71k stars 1.8k forks source link

sdl2-compat vs SDL2 vs SDL3 vs SDL_DYNAMIC_API #6709

Closed icculus closed 2 months ago

icculus commented 1 year ago

So this is a weird situation that isn't an emergency but could become one later:

What will happen is that the app will load SDL2, which will see SDL_DYNAMIC_API and load sdl2-compat, which will load SDL3.

And this will (currently) work correctly, but it prints this to stderr:

objc[76642]: Class SDL_RumbleMotor is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0cc0) and /usr/local/lib/libSDL3.dylib (0x105088828). One of the two will be used. Which one is undefined.
objc[76642]: Class SDL_RumbleContext is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0d10) and /usr/local/lib/libSDL3.dylib (0x105088878). One of the two will be used. Which one is undefined.
objc[76642]: Class SDLApplication is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0810) and /usr/local/lib/libSDL3.dylib (0x1050888c8). One of the two will be used. Which one is undefined.
objc[76642]: Class SDLAppDelegate is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0860) and /usr/local/lib/libSDL3.dylib (0x105088918). One of the two will be used. Which one is undefined.
objc[76642]: Class SDLTranslatorResponder is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae08d8) and /usr/local/lib/libSDL3.dylib (0x105088990). One of the two will be used. Which one is undefined.
objc[76642]: Class SDLMessageBoxPresenter is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0900) and /usr/local/lib/libSDL3.dylib (0x1050889b8). One of the two will be used. Which one is undefined.
objc[76642]: Class SDL_cocoametalview is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0950) and /usr/local/lib/libSDL3.dylib (0x105088a08). One of the two will be used. Which one is undefined.
objc[76642]: Class SDLOpenGLContext is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae09a0) and /usr/local/lib/libSDL3.dylib (0x105088a58). One of the two will be used. Which one is undefined.
objc[76642]: Class SDL_ShapeData is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0a18) and /usr/local/lib/libSDL3.dylib (0x105088ad0). One of the two will be used. Which one is undefined.
objc[76642]: Class SDL_CocoaClosure is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0a68) and /usr/local/lib/libSDL3.dylib (0x105088b20). One of the two will be used. Which one is undefined.
objc[76642]: Class SDL_VideoData is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0ab8) and /usr/local/lib/libSDL3.dylib (0x105088b70). One of the two will be used. Which one is undefined.
objc[76642]: Class SDL_WindowData is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0b08) and /usr/local/lib/libSDL3.dylib (0x105088bc0). One of the two will be used. Which one is undefined.
objc[76642]: Class SDLWindow is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0b30) and /usr/local/lib/libSDL3.dylib (0x105088be8). One of the two will be used. Which one is undefined.
objc[76642]: Class Cocoa_WindowListener is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0b58) and /usr/local/lib/libSDL3.dylib (0x105088c10). One of the two will be used. Which one is undefined.
objc[76642]: Class SDLView is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0bd0) and /usr/local/lib/libSDL3.dylib (0x105088c88). One of the two will be used. Which one is undefined.
objc[76642]: Class METAL_RenderData is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0c48) and /usr/local/lib/libSDL3.dylib (0x105088d00). One of the two will be used. Which one is undefined.
objc[76642]: Class METAL_TextureData is implemented in both /usr/local/lib/libSDL2-2.0.0.dylib (0x104ae0c98) and /usr/local/lib/libSDL3.dylib (0x105088d50). One of the two will be used. Which one is undefined.

Note that we don't use real SDL2, except for its entry points serving to bounce us into sdl2-compat's entry points, but the system's dynamic loader will still dump its Objective-C classes into the global namespace, apparently.

This doesn't happen with DYLD_LIBRARY_PATH=/path/to/sdl2-compat, because real SDL2 is never loaded at all, and sdl2-compat doesn't have any of these Objective-C classes itself, since it relies of SDL3 for the heavy lifting.

None of these Objective-C classes are public APIs, so we could either find a command line that tells the compiler not to export them (if such a thing exists; this might just be how Objective-C works), a command line to say "all Objective-C classes should be wrapped in a namespace" if something like that exists, or we should go manually change all these in SDL3 to have an SDL3_ prefix.

madebr commented 1 year ago

Are the .m files built with -fvisibility=hidden?

slime73 commented 1 year ago

I did some quick googling and couldn't find anything obvious to prevent those class symbols from being exported, but maybe I'm missing something.

Changing the prefix seems like a reasonable backup option but I still hope there's a better way..

icculus commented 3 months ago

I'm just going to rename all the symbols from "SDL" to "SDL3" in SDL3, which is honestly probably Good Enough until someone says otherwise. It'll prevent both the dynapi issue and prevent issues with something that links against SDL2 and SDL3 for some reason, as well.

madebr commented 3 months ago

Does apple have a concept similar to the symbol versioning we do on Linux?

icculus commented 3 months ago

They might, but not for the Objective-C class namespace.