Open nbriggs opened 7 months ago
An .xcframework
isn't the same as a .framework
Does it work if you put SDL3.framework
in /Library/Frameworks
?
I've recently upgraded the build system to run macOS Ventura.
@sridenour I tried symlinking /Library/Frameworks/SDL3.framework to the corresponding directory (for macOS) in SDL3.xcframework -- didn't work, but it did expose this warning:
CMake Warning (dev) at /Library/Frameworks/SDL3.framework/Resources/CMake/sdl3-config-version.cmake:14 (message):
Cannot not find SDL_version.h. This script is meant to be placed in
share/cmake/SDL3, next to SDL3.xcframework
Call Stack (most recent call first):
CMakeLists.txt:99 (FIND_PACKAGE)
This warning is for project developers. Use -Wno-dev to suppress it.
CMake Error at /Library/Frameworks/SDL3.framework/Resources/CMake/sdl3-config.cmake:17 (message):
File or directory
/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework/Versions/SDL3.xcframework
referenced by variable _sdl3_xcframework_path does not exist !
Call Stack (most recent call first):
/Library/Frameworks/SDL3.framework/Resources/CMake/sdl3-config.cmake:73 (set_and_check)
CMakeLists.txt:99 (FIND_PACKAGE)
and if you put a copy of .../SDL3.framework/Resources/CMake/sdl3-config-version.cmake
in /Library/Frameworks/share/cmake/SDL3/
, and get rid of the symlink so it's just /Library/Frameworks/SDL3.xcframework/...
then it almost works. Configuration using find_package(SDL3 REQUIRED)
is OK, compilation is OK, but the resulting executable (on macOS Ventura 13.6.7) fails because it depends on:
@rpath/SDL3.framework/Versions/A/SDL3 (compatibility version 101.0.0, current version 101.0.0)
and @rpath
is not set (there's neither a system default that would point to the SDL3.framework under the SDL3.xcframework; nor is there an LC_RPATH in the executable). With SDL2 builds on Ventura I had to add a "-rpath /Library/Frameworks" to handle the dependency on @rpath/SDL2.framework/...
- I suppose for SDL3 builds I could add -rpath /Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64/
-- but this amount of tweaking is getting ridiculous.
A couple things:
1) Why are you using SDL3.xcframework
? I built and use SDL3.framework
and it works just fine.
2) Speaking of using a .framework
instead of an .xcframework
, it's better to embed SDL3 in your app bundle rather than require users to install it to a system location and have to deal with version conflicts, requiring extra steps to install, etc
3) I don't know very much about CMake. For macOS, I use Xcode, which makes it so much easier to deal with stuff like building correct app bundles, embedding any .framework
s and other resources in the bundle, code signing, etc. That said, it looks like trying to symlink into the .xcframework
is part of the problem.
Are you using CMake 3.28+? That version introduced support for xcframeworks, which the xcframework cmake config file uses. https://github.com/libsdl-org/SDL/blob/4d32f66fe7a1946384b062cea87f520b75139536/Xcode/SDL/pkg-support/resources/CMake/sdl3-config.cmake#L93-L100
@sridenour -
@madebr
% cmake --version
cmake version 3.29.2
@madebr - BTW, it's annoying that from the SDL3 dmg one can't just drop the SDL3.xcframework into /Library/Frameworks -- one has to then go and install /Library/Frameworks/share/cmake/SDL3/sdl3-config.cmake by hand. I think it's a CMake bug that they don't automatically look in the right places in the .xcframework -- there's a feature request in with Kitware to fix that, but no idea if/when they'll do it.
Let's verify things first, are you extracing the 2 complete directories from the dmg into /Library/Frameworks
? SDL3.xcframework
and share
?
The share
folder situation is annoying indeed. I created that issue upstream, but I don't know what priority they assigned it.
During generation of the release binaries, a small test project is built, that generates this output. Perhaps you can experiment a bit with your CMake arguments?
Also, I assume your project is not fiddling with *_RPATH
cmake properties?
Looking at the actions output, it seems like we don't test running macos executables so the problem might appear there as well.
Does doing set_property(TARGET yourgame APPEND PROPERTY BUILD_RPATH "/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64")
fix anything?
You might need to play a bit with the path: I can't test due to no access to an Apple.
edit: my initial message had a wrong cmake command. Please try the final iteration :)
I didn't initially copy over the share
directory (it was hidden in/behind the SDL logo as Finder displayed the contents to me), but I did install the required file by hand. Thanks for putting in the CMake issue (I think that's where I commented on having the same problem)
Yeah, everything links OK, it just doesn't run - it would be good to test that in the verification ;-)
I haven't tried your set_property...
hack yet - I was just seeing if I could get the target_link_options(...)
to let me just add -rpath ...
BTW - the ReadMe.txt in the prerelease SDL3.dmg only talks about it as SDL3.framework, not SDL3.xcframework, and it doesn't mention the need to copy over the share directory.
I didn't initially copy over the
share
directory (it was hidden in/behind the SDL logo as Finder displayed the contents to me), but I did install the required file by hand. Thanks for putting in the CMake issue (I think that's where I commented on having the same problem)
Indeed, you were the only non-kitware person to comment on that issue. Before creating that issue, I asked on the #cmake channel at cpplang.slack.com, where the response was lukewarm. So I don't expect a fix anytime soon.
I haven't tried your
set_property...
hack yet - I was just seeing if I could get thetarget_link_options(...)
to let me just add-rpath ...
It would be nice if you can get it to work with set_property(...)
, and create a CMake issue with a minimum project (I'll help you trimming it down).
When using defaults, the binaries inside the build directory should "just work". (Installed binaries is another matter)
BTW - the ReadMe.txt in the prerelease SDL3.dmg only talks about it as SDL3.framework, not SDL3.xcframework, and it doesn't mention the need to copy over the share directory.
Thanks, I'll make sure to add a few lines to the readme.
Re: "I had to add a -rpath /Library/Frameworks for Ventura" -- that was in my alternative Makefile builds, not CMake. CMake for SDL2 appears to add an LC_RPATH
command to the executable. It doesn't do that automatically for SDL3. Not sure if that's a difference between the sdl2-config.cmake and sdl3-config.cmake, or CMake itself doing something differently for .framework vs .xcframework, or...
I think it has everything to do with CMake's support for xcframworks not being complete.
The project below should reproduce your issue, with these commands to reproduce:
cmake -S /path/to/cmake/script -B /tmp/sdl3-minimum-example --fresh
cmake --build /tmp/sdl3-minimum-example
ctest --test-dir /tmp/sdl3-minimum-example
cmake_minimum_required(VERSION 3.29)
project(use_sdl3_xcframework LANGUAGES C)
set(SDL3_XCFRAMEWORK "/Library/Frameworks for Ventura/SDL3.xcframework")
# Create imported shared library for the SDL3 xcframework
add_library(SDL3::SDL3-shared SHARED IMPORTED)
set_property(SDL3::SDL3-shared PROPERTY IMPORTED_LOCATION "${SDL3_XCFRAMEWORK}")
# Source for minimal SDL3 executable
file(WRITE main.c [==[
#include <SDL3/SDL.h>
int main(int argc, char *argv[]) {
(void)argc; (void)argv;
SDL_Init(SDL_INIT_EVENTS);
SDL_Quit();
return 0;
}
]==])
enable_testing()
# Create executable, not setting rpath
add_executable(mygame_without_rpath main.c)
target_link_libraries(mygame_without_rpath PRIVATE SDL3::SDL3-shared)
add_test(NAME mygame_without_rpath COMMAND mygame_without_rpath)
# Create executable, setting rpath
add_executable(mygame_with_rpath main.c)
target_link_libraries(mygame_with_rpath PRIVATE SDL3::SDL3-shared)
set_property(TARGET mygame_with_rpath APPEND PROPERTY BUILD_RPATH "${SDL3_XCFRAMEWORK}")
add_test(NAME mygame_with_rpath COMMAND mygame_with_rpath)
I did not test this, so please correct my errors.
@madebr - cool, thanks -- I'll check that out. I had just made my program runnable by adding
SET_PROPERTY(TARGET ldesdl APPEND PROPERTY BUILD_RPATH "/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64/")
``
-- i'll swap over to using `"${SDL3_XCFRAMEWORK}"` instead of the raw path, and then run your example.
It would be nice if you could make my minimum project above working, and create a cmake issue for this. As I said before, the executable should work without setting rpath properties.
OK -- with your example, need this change:
diff CMakeLists.txt~ CMakeLists.txt
8c8
< set_property(SDL3::SDL3-shared PROPERTY IMPORTED_LOCATION "${SDL3_XCFRAMEWORK}")
---
> set_property(TARGET SDL3::SDL3-shared PROPERTY IMPORTED_LOCATION "${SDL3_XCFRAMEWORK}")
There are questions about what the value of SDL3_XCFRAMEWORK
should be:
set(SDL3_XCFRAMEWORK "/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework")
compiles OK, but results in
% ./mygame_with_rpath
dyld[32771]: Library not loaded: @rpath/SDL3.framework/Versions/A/SDL3
Referenced from: <6A9B892D-AC32-3278-AD53-CD930FCA4A85> /private/tmp/sdl3-minimum-example/mygame_with_rpath
Reason: tried: '/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework/SDL3.framework/Versions/A/SDL3' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework/SDL3.framework/Versions/A/SDL3' (no such file), '/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework/SDL3.framework/Versions/A/SDL3' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64/SDL3.framework/SDL3.framework/Versions/A/SDL3' (no such file)
while
set(SDL3_XCFRAMEWORK "/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64")
results in the compile failing with
[ 25%] Building C object CMakeFiles/mygame_without_rpath.dir/main.c.o
/Users/briggs/Projects/sdl3link/main.c:1:10: fatal error: 'SDL3/SDL.h' file not found
#include <SDL3/SDL.h>
^~~~~~~~~~~~
1 error generated.
and
set(SDL3_XCFRAMEWORK "/Library/Frameworks/SDL3.xcframework")
compiles OK but fails with
% /tmp/sdl3-minimum-example/mygame_with_rpath
dyld[32956]: Library not loaded: @rpath/SDL3.framework/Versions/A/SDL3
Referenced from: <4D619860-ABA6-34EC-B463-DB565C4104DA> /private/tmp/sdl3-minimum-example/mygame_with_rpath
Reason: tried: '/Library/Frameworks/SDL3.xcframework/SDL3.framework/Versions/A/SDL3' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Library/Frameworks/SDL3.xcframework/SDL3.framework/Versions/A/SDL3' (no such file), '/Library/Frameworks/SDL3.xcframework/SDL3.framework/Versions/A/SDL3' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Library/Frameworks/SDL3.xcframework/SDL3.framework/Versions/A/SDL3' (no such file)
So there isn't a combination that seems to work for both compilation and running. I'm looking at what might need to be added to get things working.
We're trying to use the xcframework here, so it should be set(SDL3_XCFRAMEWORK "/Library/Frameworks/SDL3.xcframework")
.
Try doing set_property(TARGET mygame_with_rpath APPEND PROPERTY BUILD_RPATH "${SDL3_XCFRAMEWORK}/macos-arm64_x86_64")
.
Yes -- that's the answer. So, with CMakeLists.txt
:
cmake_minimum_required(VERSION 3.29)
project(use_sdl3_xcframework LANGUAGES C)
set(SDL3_XCFRAMEWORK "/Library/Frameworks/SDL3.xcframework")
# Create imported shared library for the SDL3 xcframework
add_library(SDL3::SDL3-shared SHARED IMPORTED)
set_property(TARGET SDL3::SDL3-shared PROPERTY IMPORTED_LOCATION "${SDL3_XCFRAMEWORK}")
# Source for minimal SDL3 executable
file(WRITE main.c [==[
#include <SDL3/SDL.h>
int main(int argc, char *argv[]) {
(void)argc; (void)argv;
SDL_Init(SDL_INIT_EVENTS);
SDL_Quit();
return 0;
}
]==])
enable_testing()
# Create executable, not setting rpath
add_executable(mygame_without_rpath main.c)
target_link_libraries(mygame_without_rpath PRIVATE SDL3::SDL3-shared)
add_test(NAME mygame_without_rpath COMMAND mygame_without_rpath)
# Create executable, setting rpath
add_executable(mygame_with_rpath main.c)
target_link_libraries(mygame_with_rpath PRIVATE SDL3::SDL3-shared)
set_property(TARGET mygame_with_rpath APPEND PROPERTY BUILD_RPATH "${SDL3_XCFRAMEWORK}/macos-arm64_x86_64")
add_test(NAME mygame_with_rpath COMMAND mygame_with_rpath)
doing
cmake -S . -B /tmp/sdl3-minimum-example --fresh # from the directory with CMakeLists.txt
cmake --build /tmp/sdl3-minimum-example
ctest --test-dir /tmp/sdl3-minimum-example
produces, for the ctest output:
% ctest --test-dir /tmp/sdl3-minimum-example
Internal ctest changing into directory: /tmp/sdl3-minimum-example
Test project /tmp/sdl3-minimum-example
Start 1: mygame_without_rpath
1/2 Test #1: mygame_without_rpath .............Subprocess aborted***Exception: 0.00 sec
Start 2: mygame_with_rpath
2/2 Test #2: mygame_with_rpath ................ Passed 0.05 sec
50% tests passed, 1 tests failed out of 2
Total Test time (real) = 0.05 sec
The following tests FAILED:
1 - mygame_without_rpath (Subprocess aborted)
Errors while running CTest
Output from these tests are in: /tmp/sdl3-minimum-example/Testing/Temporary/LastTest.log
Use "--rerun-failed --output-on-failure" to re-run the failed cases verbosely.
That's a good reproducer, I'd say. Thanks for investing time into this!
No worries - it's a small amount of my time invested that (a) lets me fix my builds, and (b) may help others avoid the same issue. Thank you for sharing your knowledge of CMake to get to a workaround. I'll file an issue over on CMake's gitlab.
@madebr - would you like credit for working out the details over in CMake issue 25998 ?
There's no need for that.
I'm honestly not sure what's the appropriate solution for this.
The xcframework can theoretically have a macos-arm64
and a macos-x86_64
subdirectory (instead of macos-arm64_x86_64
).
Then, a fat binary would need to add 2 paths to the runpath.
From a developer standpoint, being a consumer of the tools and libraries/frameworks, something that "just works" on all the different systems that CMake and SDLx are available on, without my having to special-case for macOS, would be a good choice. If I were creating frameworks, I think i'd prefer it to be a fix in CMake, so everybody doesn't have to fuss around in their cmake config. As it stands now, I have an if(APPLE)...fix the rpath...
clause in the SDL3 part of my CMakeLists.txt, which will suffice until things get sorted, I guess.
Regarding the .xcframework subdirectories -- is that true? Would xcodebuild -create-xcframework [-framework path]+
not combine all the macOS architectures into a single universal blob? (as you can tell, I've never had to build a framework).
@nbriggs
Can you try the SDL3-3.1.2.dmg
asset from the recent 3.1.2 release?
I think we might need to use the frameworks inside the xcframework, and unconditionally disable this if
.
I have the same problem with the framework from the SDL 3.1.3 preview release. I copied both SDL3.xcframework and share to /Library/Frameworks
If I link to the SDL3.framework inside the xcframework, it links, but then it fails to link at runtime with
dyld[85945]: Library not loaded: @rpath/SDL3.framework/Versions/A/SDL3
Referenced from: <08A14158-99A6-3A5D-90BA-573BA6D06C04> /private/tmp/test
Reason: no LC_RPATH's found
zsh: abort ./test
This happens both with clang and with rust
Clang command that fails to find SDL:
clang -framework SDL3 test.c -o test
Clang command that links but fails to run with rpath error:
clang -F/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64 -framework SDL3 test.c -o test
When building on the command line, you always need to add the runpath yourself. This is also required on Linux, and other unixes.
The issue with CMake is that it should set the runpath automatically, but it doesn't.
On Linux the command is -Wl,-rpath,/path/to/directory/containing/library
.
Try adding -Wl,-rpath,/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64
I'm new to building on mac, but on Linux the rpath is inherited from the library. From searching it seems this should happen on mac as well, but it doesn't here?
Anyway, adding the rpath makes it go a step further, but now it fails to verify the framework and wants to move it to the trash. Isn't the preview signed?
I'm new to building on mac, but on Linux the rpath is inherited from the library. From searching it seems this should happen on mac as well, but it doesn't here?
On Linux, when an executable does not have an rpath, then the loader looks in standard paths (amonst many LD_LIBRARY_PATH
). When rpath is set, it first looks in those.
Anyway, adding the rpath makes it go a step further, but now it fails to verify the framework and wants to move it to the trash. Isn't the preview signed?
The assets were built on Github Actions, and supposedly signed by slouken.
About the warning, I've been told the following:
I've always had the warnings for SDL prebuilt frameworks, you have to go to the systems "Privacy & Security" settings to clear it the first time
GitHub actions don't sign the frameworks. Typical workflow is that Xcode will automatically sign and embed frameworks when assembling your app.
I see, thanks. I'll have to put off dealing with that until later, but at least I can get it to link...
@madebr I think maybe I misunderstood something, but I meant that when you link with a library that has an rpath, you don't have to repeat that rpath yourself
@madebr - I'm back online. Currently dealing with the fallout of all the API changes between 2 and 3, but should be able to test soon. Regarding adding the RPATH, my fix was to include in my CMakeLists.txt:
MESSAGE("-- Applying fixup for macOS RPATH for SDL3.xcframework")
SET_PROPERTY(TARGET foo APPEND PROPERTY BUILD_RPATH "/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64")
@madebr - I'm back online. Currently dealing with the fallout of all the API changes between 2 and 3, but should be able to test soon. Regarding adding the RPATH, my fix was to include in my CMakeLists.txt:
MESSAGE("-- Applying fixup for macOS RPATH for SDL3.xcframework") SET_PROPERTY(TARGET foo APPEND PROPERTY BUILD_RPATH "/Library/Frameworks/SDL3.xcframework/macos-arm64_x86_64")
Happy to have you back :)
The "fix" you mentioned is not a fix, but a workaround because it wouldn't work for ios/tvos/ios-simulator/tvos-simulator etc.
In the next prerelease, cmake will probably use the internal framework as IMPORTED_FRAMEWORK
instead of the xcframework.
Can you test these?
SDL: https://github.com/madebr/SDL/actions/runs/11309111417 SDL_image: https://github.com/madebr/SDL_image/actions/runs/11309547411 SDL_mixer: https://github.com/madebr/SDL_mixer/actions/runs/11309699802 SDL_ttf: https://github.com/madebr/SDL_ttf/actions/runs/11309827817
note: SDL_TARGET_IS_SIMULATOR
detection of prerelease 3.1.3 is broken, so you need to configure in a fresh build folder.
Yeah, I didn't put the quotes around "fix" - they were in my head but not in the text. As soon as I have a chance to update all the source incompatibilities for 2=>3 I'll be trying a build with 3.
@nbringgs why would you quote something you say?
@TheZitroX https://en.wikipedia.org/wiki/Scare_quotes
Thanks for ref Wikipedia. But being ironic in a workflow? I just want to get SDL3 working to try making a small project with it🥲
@TheZitroX - I shared what I needed to do to get my CMake to run. madebr pointed out that from the SDL devs perspective it's not a real fix, but rather a workaround because I (and everyone else trying to build with SDL3) shouldn't have to do that, and it won't work in the general case of building for iOS/iPadOS/tvOS anyway. From my perspective: it's a couple of lines in one file that I control that solves the problem for the only Apple OS I care about building for at the moment (macOS).
The real fix is for the CMake devs to make changes that allow seamless use of .xcframework frameworks for all the platforms in the framework.
As far as irony in the comments on an issue... that's just part of human communication.
But thanks for your help, for now I went back to Windows to start my project until this issue is solved for Mac🙌
@nbriggs Can you try today's 3.1.6 prerelease?
The CMake script no longer uses the xcframework as IMPORTED_LOCATION
, so the rpath issue should be gone.
https://github.com/libsdl-org/SDL/releases/tag/preview-3.1.6
Hey, just tested the 3.1.6 prerelease. Looks like it’s finally working on macOS (M2p)
On macOS Monterey, 12.7.4 - have both SDL2 and SDL3 installed in /Library/Frameworks:
and while compiling with
-framework SDL2
works, compiling with-framework SDL3
does not, and produces the errorIt looks as though clang
isn't prepared to deal with the .xcframework properly?