Bundling SDL Libraries in app bundle

I’ve tried using the pre-packaged frameworks for development but nothing I did (after many many many web searches) would get rid of the codesign problem.

I ended up going the homebrew route and setting up the libraries that way. That works great for development but deployment of my game & editor require those libraries which end users won’t likely have.

My xcode experience is pretty limited… I haven’t do much coding since Xcode was Project Builder… should give you an idea.

I cannot figure out how to get my library search path to be “myapp.app/Contents/Frameworks” rather the @execution_path gives me “myapp.app/Contents/MacOS/” instead…



How do I set up Xcode to move my needed libraries / frameworks to the folder I need? right now they are moved into the “myapp.app/Contents/Frameworks” but if anyone else tries to run my app it is still looking for them in the “usr/local/Opt/” folder that is on my comp.

1 Like

ferrusloki I have those set up in xcode just fine and my project is finding them. I can add them as framework dependencies.

What exactly is the problem?

Alex

The issue is if the end user doesn’t have the libraries installed in the folder /usr/local/opt, then the executable cannot find them. (obviously)

I have all the needed libraries and external dependencies loaded into my Project and they reside in the same folder as the executable. I’ve used the terminal command otool to see where the binary is referencing the libraries and also used the install_name_tool to change their load path to the executable directory in the bundle. After doing that the app just doesn’t launch.

I would love to be able to setup the search paths properly in Xcode but all the options I’ve tried don’t work.

I had a couple friends manually put the libraries where they need to be, but thats hardly a solution. I changed the loader paths in Xcode to:

But this doesn’t work either.

I would expect libraries that are needed by your program to be:
a) packed, and linked statically (add them to the project and add the frameworks as dependencies)
b) packed, and linked dynamically (don’t know about your specifics, but should imply adding the HEADERS to your search path during compilation and adding the dynamic libraries to the bundle).
c) distributed separately, linked dynamically. They either need to be in standard paths (e.g., /usr/lib), findable by the OS (via pkg-config) or in a variable included in the LD_CONFIG_PATH or a similar variable.

How are those libraries normally installed?

I once had this case and this stackoverflow question helped me: https://stackoverflow.com/questions/7285587/what-are-the-default-search-directories-to-link-a-library-on-mac-os-x

Alex

EDIT: hit enter too quickly by mistake.

I used homebrew to install the SDL libraries. They are installed in the folder
/usr/local/Cellar/

But are referenced by the path /usr/local/opt/

I have the dylibs included in my project and added as dependencies.

I cannot find any LD_CONFIG_PATH setting in the build settings… older version of xcode perhaps?

Sorry for all the screenshots but this is my setup:

and when I use otool -l on my executable it says:

As the file path still. I will try using the install_name_tool to change it… but that hasn’t worked in the past.

I guess the other option here is to install the libraries on the destination mac when installing the app itself.

edit: even after changing the names it won’t open.

For a desktop computer, and if you were using linux, I would say, yes, you want to create a dependency between your package and for example, SDL2.

Everything I can find online suggests adjusting the paths to where the mac expects those libraries during installation with a script (see this link, or this one). To me this looks like hack, but Macs work in mysterious ways.

I think it would work better if you add them to your project under frameworks if you haven’t. I think right now you are depending on the library file directly, which is why otool is showing that path. If you add it as a framework and depend on it, then Xcode knows how to copy it during the installation.

Alex

1 Like

Thank you!

that first link, the script he wrote worked perfectly for me.

I figured it was my lack of knowledge that was the main issue. I was not aware that you could put scripts in the build phase, within Xcode.

I need to pull up some tutorials on Xcode I guess.

Thanks again, very helpful!

1 Like

Just add the framework as a dependency. For the last couple versions of Xcode, adding an external framework as a dependency will set everything up for you, as far as copying the framework to the right place in your app bundle, code signing it, etc.

You don’t need to mess with header paths or library paths or linker paths or any of that.

  1. Rip out any changes you made to make it work with the SDL from Homebrew.
  2. Then copy SDL2.framework to the same folder as YourProject.xcodeproj
  3. Add it as a dependency in Xcode. In your build settings, under the General tab, in the Frameworks, Libraries, and Embedded Content section, hit the +, choose Add Other, and select the SDL2.framework.
  4. Xcode should set everything up for you
  5. In your code, include SDL like #include <SDL2/SDL.h>

I also agree, that this would be a better way to do it. As I also said in my message, it’s less likely to break (if Apple does not break xcode).

This is how I have it set. The ones I set up manually, are the ones I have to fix often.

Alex

I’ve done this at least 20 different times… and every single time it won’t build. Always gives me a codesign error. Library Validation on or off along with Allow Unsigned Executable Memory on or off.

I agree it SHOULD be the easier way to this… but it refuses to work properly. I’ve tried stripping the frameworks of their codesigns but nothing.

Thoughts?

Unsigned executable memory has nothing to do with code signing (it’s for applications that generate executable code at runtime, like Java). You really don’t want to allow it unless you’re 100% certain you need it (you don’t).

Your screenshot shows a codesign error on SDL_TTF. IDK how it is now, but it used to be that stripping the code signing on something didn’t allow it to be re-signed. What is the actual error you’re getting?

(I’ve shipped an SDL2.framework that I built myself in a codesigned app without any trouble, as well as ones signed by someone else with Disable Library Validation checked).

The codesign error is the only one I am getting. And it is only a problem when I try to use the .frameworks.

It appears to be an issue with sub components “FreeType.framework” (a few others in SDL_image as well… webcp.framework).

If a framework has other frameworks within it, they need to be set up right by whoever built them. A lot of times the Info.plist is wrong, or outdated, but worked fine before code signing was a requirement so the developers never fixed it (especially true of “hand-crafted” Info.plist’s). I’ve had issues code signing SDL_mixer in the past because of this. Someone posted a fix in another thread, but I can’t find it right now.

It looks like it isn’t able to sign SDL_ttf, probably for the same reason as above. I let my Mac developer program membership expire because my little one person studio is out of business, or else I’d spin up a project with SDL_ttf and see what it took to get it code signing successfully.

Also, this is a reason I try to avoid external dependencies, and especially dependencies with other dependencies.

I use stb_image instead of SDL_image, since it’s one file with no external dependencies, and ditto for stb_truetype vs SDL_ttf (though stb_truetype requires more work from you).

I don’t have a real cure.
But I have just hit exactly the same problem, which goes away completely if the SDL_TTF Framework is not added.
XCode 11.6
MacOS 10.15.6

Yeah, it’s because codesign doesn’t sign frameworks-within-frameworks, and so having the FreeType framework inside the SDL_ttf framework causes signing SDL_ttf to fail.

Apple’s guidance is to avoid putting frameworks inside frameworks, and instead have them all be top-level (which is the only option on iOS, AFAIK), but that if you absolutely must, you should manually sign them inside-out (such as by having a Run Script build phase running a shell script that signs all the inner frameworks first).

1 Like