Repository navigation
Conversation
The SFML versions can be linked statically or dynamically, I believe. And the first point here implies the second, as any code using SFML on MacOS will necessarily lead to runtime lookup of the Objective-C symbols.
That's also a good idea. |
I'm not sure that's correct, although I won't claim to be an expert on the matter, my understanding is it only applies when looking up by name e.g. regardless I think this is pretty much a hypothetical issue, and one that users can workaround without modifying SFML source code |
|
I don't think that's quite right, the name conflict is an issue in the global symbol table at the process level, not just for runtime string lookups. And, it's not a hypothetical issue, it's a real documented issue with recommended steps to avoid it in Apple's documentation: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/LoadingCode/Tasks/NameConflicts.html Aside from Apple's documentation, I mention in the linked issue that I experienced this issue myself when running newer software my company has developed alongside older unsupported software (but still in customer use). I was able to circumvent it by applying Apple's recommended procedure from the link above, but your solution would also work. Anybody building their SFML-based project as a dynamic lib or other type of runtime-loadable code will run the risk of encountering the same issue. |
|
Only if they are loading SFML's internal implementation classes at runtime by name right? And even then for it to be a problem they'd need to be doing something that has issues between the two mixed versions? I agree the problem in the abstract is real, but is mostly hypothetical as it pertains to SFML, partly due to SFML code, and also how we expect users to use SFML. I would be very interested to know if you have a real use case or reproduction which causes issues with SFML, other than just a warning in the log? |
|
Okay, I spent some time this morning doing some more research and working on an example. It turns out that @JonnyPtn is correct here about directly invoking class/function names in code. If two dynamic libraries define the same class/function name, by default they are tagged separately by dylib in the symbol table and so they can coexist without conflicting, with some caveats. Caveat 1: Caveat 2: String lookups Caveat 3: Pointer casts This is less serious than Apple's docs led me to believe. I do think providing an easy ready-to-go solution is worthwhile, but if we want to simply document somewhere that objective-C symbol collisions can be avoided by redefining the SFML Obj-C class names with a custom prefix, I'd be okay with that too. DAW plugin development is exploding in recent years, especially with people using AI to generate 80-100% of it, and I'm sure I won't be the last person to encounter this warning and try to fix it. |
|
I'm not sure we'd even want to document that as a solution to be honest, it's creating two distinct versions of the classes so would only fix things if the host process knows which plugin it wants to use the class from, which would seem a backwards way to develop a plugin system I think really the correct solution if the host process needs to use SFML internals it should either require that all the plugins use a shared version it provides, or that they all statically link the same version. |
The two distinct version of the classes is exactly the point -- it guarantees that any code on top of SFML that might use obj-c string lookups or pointer casts will be safe. It's not about protecting the host process, it's about protecting the plugin code that uses SFML. In the case of developing DAW plugins, the host process doesn't even know SFML exists. We are talking about Apple Logic/GarageBand, FL Studio, Steinberg Cubase, UAD Luna, Ableton Live, and so on. There are many different hosts for a plugin dev to support, and many different UI and audio plugin framework combinations that could be used to develop a plugin that works across all hosts. One of the most common audio plugin development frameworks these days, JUCE, solves this by postfixing obj-C class names with random hex strings upon instantiation to guarantee that multiple plugins using JUCE can be using different versions and still use all the features of Objective-C without fear of symbol collisions. I'm not suggesting any such thing here, just a simple way to change the SFML obj-C class names at build time, or at the very least, a description of the issue and a way to solve it. It's not always the case that the developer has full control over the system they are working in. |
|
Do any of your plugins access SFML internal classes like that? or can you find any plugins which do? In my opinion we shouldn't be documenting "solutions" to problems which only exist in specific use cases AND only when they are misusing SFML internals. I don't really have much more to add |
Mine don't, and most plugins aren't open source so I have no idea how many people use this feature of objective-C and in what scenarios. Seems like other library devs wouldn't go through the trouble of hardening their libraries against it if it didn't matter. All use cases end up being "specific", at the end of the day, and it seems like a slam dunk to broaden the horizon of supported use cases for an open source library such as this without breaking anything, as this PR achieves. But I'm curious what rule is being broken if a dev uses e.g. |
|
Primarily that it's an internal implementation detail of SFML, not part of its API, much like we try to prevent users from accessing any other platform specific implementation classes, it's just harder (or impossible?) to prevent with the objective-c bits Apple requires If there was any reason someone needed to access the internal classes directly then it would be good to know, as perhaps it indicates something lacking from the public API |

Description
When multiple binaries embed SFML, the Objective-C runtime raises duplicate-class errors because internal SF* class names collide. This PR adds a CMake option to prefix those names at build time.
CMake will generate SFMLObjcPrefix.h via configure_file(@only). This file will effectively rename all SF* Obj-C classes. Defines one rename macro per class:
Empty prefix (default) → no-op macros (#define SFWindow SFWindow), zero behavior change for existing builds.
This PR is related to the issue #3718
Tasks
How to test this PR?
Build and run
test-sfml-windowwithSFML_OBJC_CLASS_PREFIXset to empty (default). ChangeSFML_OBJC_CLASS_PREFIXto a custom prefix (e.g.ComMyApp) and build and run again. All tests pass.