Issues using SDL2 on Xcode on macOS

Hey guys, I’ve been having this issue with my SDL2 install and its been driving me crazy, I’ve asked around everywhere but no one can fix my issue for some reason, so I thought I’d come here. So, I’ve been trying to follow lazy foo’s tutorial and his first step isn’t working. I’m developing on both Intel and Apple Silicon computers and every time I install the framework to the /Library/Framework folder, I can’t seem to use it. Whenever I use “#include<SDL2/SDL.h>” the path autocompletes but when I try building, it says the file cannot be found. I have included the framework into the project and tried both the dev and runtime frameworks and neither work.

I then moved onto building the libraries myself following the instructions on the site but every time I run make, a bunch of alias files are created but when I tell macOS to show e the actual files, it says they cannot be found. So right now, I’m stuck, I don’t know what else to try and its really beginning to frustrate me. I feel like I’m just going round in circles. I’m currently on macOS Monterey and Xcode 13. Has anyone else had this issue or can anyone else fix it?

These are the steps I follow:

Put SDL2.framework in the same folder as YourProject.xcodeproj (don’t put it in /Library/Frameworks). Don’t use the command line to copy it, as in my experience it doesn’t preserve the internal symlinks.

In Xcode, in your project’s settings, select your project’s target. In the General tab, in the Frameworks, Libraries, and Embedded Content section, click the + to add another framework. Click Add OtherAdd Files and select SDL2.framework. This will make Xcode link your app against the SDL2 framework, and also tell Xcode to put it inside your app bundle so your users won’t have to have SDL installed.

In the Xcode project settings, in the Build Settings tab, find the Framework Search Paths setting. Make sure $(PROJECT_DIR) is included. Apparently this is automatically done on the latest Xcode, but still make sure to check because it didn’t use to be.

In the project settings Signing & Capabilities tab, scroll down and tick the box that says Disable Library Validation unless the SDL2.framework you’re using was built and signed by you. This will keep macOS from refusing to run your app (because your app is signed by you, but the framework is signed by someone else).

edit: Also, if you’re going to build SDL yourself for macOS or iOS, use the Xcode project that comes with the SDL sourcecode instead of messing around with make etc.

I have the same exact issue, and I am still trying to get to figure out a solution. If it helps, a Clean Build Folder should get your program running, but making any changes to your code afterwards will re-trigger the issue and you’ll have to clean build folder again. I have also found that going to Build Phases > Embedded Frameworks and checking the “Copy only when installing” box, then running will cause the program to crash with an __abort_with_payload. Then unchecking “Copy only when installing” again should allow the program to run again. This is a good (if a bit clunky) workaround for running a program that takes a long time to build.

If anyone has any idea what could possibly be going on here, that would be immensely helpful. I’ve been battling this weird error for almost a week now. If it helps, here’s the console log for when I get the __abort_with_payload error:

dyld[5340]: Library not loaded: @rpath/SDL2.framework/Versions/A/SDL2

Referenced from: <4710FA6C-D433-3D0F-94FA-91E0E31849EE> /Users/[username]/Library/Developer/Xcode/DerivedData/[project_name]-ctbicgopgppphhdyvhsejvjfyonf/Build/Products/Debug/[project_name]

Reason: tried: ‘/Users/[username]/Library/Developer/Xcode/DerivedData/[project_name]-ctbicgopgppphhdyvhsejvjfyonf/Build/Products/Debug/SDL2.framework/Versions/A/SDL2’ (no such file), ‘/System/Volumes/Preboot/Cryptexes/OS@rpath/SDL2.framework/Versions/A/SDL2’ (no such file), ‘/Library/Frameworks/SDL2.framework/Versions/A/SDL2’ (no such file), ‘/System/Library/Frameworks/SDL2.framework/Versions/A/SDL2’ (no such file, not in dyld cache)

The reason you get the __abort_with_payload is because it isn’t copying SDL2.framework to your app bundle when building. So it looks in other standard places it expects to find it, but doesn’t find it there either.

Did you follow the steps in my earlier post?

LazyFoo’s tutorials are… not always correct.

Whilst drafting my reply to you and re-executing your steps, I (well, mostly you) actually solved the issue.

Yes, I followed the steps in your post, but unfortunately it didn’t fix it. I tried setting both my Framework and System Framework search paths to $(PROJECT_DIR) but that didn’t work either (even though the SDL2.framework is in there). Even after setting those search paths, I still get __abort_with_payload and the same error message that says it’s searching in /Library/Frameworks. I got: dyld[16532]: Library not loaded: @rpath/SDL2.framework/Versions/A/SDL2

Where I incorrectly assumed @rpath is my project directory. Then I googled and found that this is actually the Runpath Search Path. So, I went to project settings>Target>Build Settings, searched “Runpath” (or, it’s in the ‘Linking’ section), and set the Runpath Search Paths to $(PROJECT_DIR).

So, from what I can tell, the problem is totally solved, but I assume it will involve downloading SDL2 for each project, since I need the framework to sit in my project directory.

Thanks so much for the help sjr, as I would never have solved this without your instructions. And @Armature89 , make sure to do this step if you’re still having this problem so many months later.

You don’t want to change the runpath. The reason is because, at runtime, you want it loading SDL2 from the framework shipped inside your app bundle.

You are building your game/whatever as an app bundle, right? The instructions were written with the assumption you’re building/distributing a macOS app bundle.

You put SDL2.framework next to YourProject.xcodeproj so that it’ll be in your source code repository, so you can always go back to the specific version of SDL that a given version of your app was built with. And Xcode will, by default, copy that into your app bundle when building so that you can just ship it with your app and your users won’t have to manually copy SDL2.framework to ~/Library/Frameworks or anything like that.

But changing @rpath can mess with that: at runtime, instead of looking inside your app bundle for SDL2.framework, and then system search paths, it will look at the hard-coded path to your source code repository, even on the end user’s machine! So leave it at the default of @executable_path/../Frameworks

Apologies as I’m not 100% clear on terminology, but I don’t think so. I am building my game as a command line tool (mainly for learning game dev). I don’t know if it’s straightforward to build it as an app bundle instead, or if I’m totally misunderstanding what that even means (google wasn’t overly helpful).

This makes sense to me, and I’d definitely like to find another solution but in the meantime I think I’ll have to live with it, just in the interest of getting some stuff done for my project. I wish I had a better idea of how this stuff works (and Xcode project templates as well) but it’s all a bit overwhelming and I’m not really sure of the best way to go about learning it.

You definitely want your game to be distributed as an app bundle. Basically, that’s a regular macOS app. It has the executable and everything else all bundled into one folder with a specific layout and a name that ends in .app. All resources, artwork, etc., will all be inside the app bundle. Picking any of the Xcode app templates besides Command Line Tool creates an app bundle.

You can’t get your app notarized if it isn’t an app bundle.

To make a regular macOS app that uses SDL:

  1. Create a new project in Xcode, and pick plain vanilla Mac App. You don’t need to choose the game one, just the regular “App” one. On the next screen, make sure the language is set to Objective-C (you don’t need to know Objective-C, as you’ll see).
  2. Delete any file that ends with .xib, .nib, or .storyboard
  3. Delete AppDelegate.h and AppDelegate.m
  4. Don’t delete Assets.xcassets. You’ll want to put macOS assets in there later, like your game’s icon.
  5. Delete main.m and replace it with your main.c or main.cpp or whatever
  6. Add your game’s other source code, if this is for an existing game.
  7. Add your game’s assets: In the file browser on the left side of Xcode, right click on the first folder and pick New Group without Folder. Name it “Assets” or “Resources” or whatever. Right click on the new group and pick “Add Files to [YourProject]”. Add the files, make sure that Copy If Needed is turned OFF, set Added Folders to Create Folder References, and make sure your game’s target is the one selected under Add to Targets
  8. Make sure that any file loading your code is doing is taking into account that the game’s assets will not be in the same folder as the executable or a sub-folder of it. Instead, use the SDL function SDL_GetBasePath() to find out what folder the game assets are in (will be something like /Applications/ This function also returns the appropriate directory on Windows and Linux.
  9. Do everything from my earlier post.
1 Like

I copied all your steps and everything worked perfectly. Thanks so much for taking the time to help me and explain how this stuff works. Much appreciated!

1 Like

No problem, glad it all worked out! :+1:

Some of the confusion I think is that the tutorial has you start with a Command Line Tool “template”. You don’t in fact want to ultimately end up with a command line tool however.

Many of the steps from sjr (" 1. Delete any file that ends with .xib, .nib, or .storyboard", etc.) are essentially stripping down the plain vanilla Map App template … very much like what the Command Line Tool template gives you.

I was in a similar rut until I made the change to the source file:

-- #include <SDL.h>
++ #include <SDL2/SDL.h>

Not quite. The App template still builds an actual, full-fledged macOS app (an app bundle), even after you remove some of the unneeded files it creates. The Command Line Tool template just gives you a bare binary.

Removing any .xib, .nib, and .storyboard files is just removing the default UI stuff the template creates for you. Since SDL will be creating the window programmatically, we don’t need it.

As I pointed out in my earlier post, you can’t get your app notarized if it isn’t an app bundle.