I use sublime text 3 with a build_system on OSX to compile a c++ game using SDL2. The game works on my machien but as soon as I try to use it on an other machine, the SDL2 libary is not found.
How can I incorporate the SDL2 framework into my game or my own game folder structure, so that it is easy to copy to any machine?
I use this build_system:
"build_systems": [
{
"name": "Debug",
"working_dir": "${project_path}",
"cmd": ["g++ -c src/*.cpp -std=c++14 -m64 -g -Wall -I include && g++ *.o -o bin/debug/main -lSDL2main -lSDL2 -lSDL2_image && ./bin/debug/main"],
"selector": "source",
"shell": true
},
{
"name": "Release",
"working_dir": "${project_path}",
"cmd": ["g++ -c src/*.cpp -std=c++14 -m64 -O3 -Wall -I include && g++ *.o -o bin/release/main -s -lSDL2main -lSDL2 -lSDL2_image && ./bin/release/main"],
"selector": "source",
"shell": true
}
The error on the machine, where SDL2 is not installed:
dyld: Libary not loaded: /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib
My preferred scenario would be that I have a compiled game main
with a subfolder lib
or framework
, which includes the necessary SDL2 files (I am also not sure which SDL2 files this should be).
Thanks for any help.
This post helped me to find a solution: Building OSX App Bundle
First, the file I needed was libSDL2-2.0.0.dylib
buried deep in the system /usr/local/Cellar/sdl2/2.0.9_1/lib/libSDL2-2.0.0.dylib
I think the .dylib
suffix shows that this is a dynamic library file, which means that it only needs to be installed once on the system, and each program can use and share the same files. Which makes it kind of nice, if everyone has installed it. But of course, if you haven't installed the SDL library globally, the program doesn't work.
So that's why it is important to create an application bundle main.app
, in which the used libraries are incorporated. The main.app
is actually just a special folder with a special subfolder structure:
main.app/
Contents/
Info.plist
MacOS/
main
Resources/
(you can learn more about that in the other stackoverflow answer above)
(I created the main.app
folder in my ./bin/release/
folder, where g++ outputs the release binaries)
Open a terminal window and go into the directory where g++
outputs your binary file. For me it is ./bin/release
With the following command you can see which libraries your app uses and where your app looks for the libraries:
otool -L main
(main ist the name of the executable binary)
My output was:
main:
/usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib (compatibility version 10.0.0, current version 10.0.0)
/usr/local/opt/sdl2_image/lib/libSDL2_image-2.0.0.dylib (compatibility version 3.0.0, current version 3.2.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.250.1)
So I hade to change the first 2, as the other answer describes, you have to change the libraries which doesn't start with System/Library/
and /usr/lib/
.
So to do that I used this 2 commands:
install_name_tool -change /usr/local/opt/sdl2/lib/libSDL2-2.0.0.dylib @executable_path/libSDL2-2.0.0.dylib main
install_name_tool -change /usr/local/opt/sdl2_image/lib/libSDL2_image-2.0.0.dylib @executable_path/libSDL2_image-2.0.0.dylib main
and moved the main executable binary into the bundle main.app/Contents/MacOS
;
and copied the libraries into the same bundle directory:
mv main main.app/Contents/MacOS/
cp /opt/local/lib/libSDL-1.2.0.dylib main.app/Contents/MacOS/
cp /usr/local/opt/sdl2_image/lib/libSDL2_image-2.0.0.dylib main.app/Contents/MacOS/
if you now copy the main.app bundle to an other computer, and you double click on the app, it should work.
But this is quite a lot to do manually, so one answer talks about a tool that does all of that automatically dylibbundler
-> https://github.com/auriamg/macdylibbundler/
This tool auto changes the paths in you binary and copies all libraries into its own main.app/Contents/libs
folder, which is nice, because now your libraries are separated from the binary, and it adds the right corresponding paths.
I added the mv main
command and the dylibbundler
into the release build-system as follows:
{
"folders":
[
{
"path": "bin/.."
}
],
"build_systems": [
{
"name": "Debug",
"working_dir": "${project_path}",
"cmd": ["g++ -c src/*.cpp -std=c++14 -m64 -g -Wall -I include && g++ *.o -o bin/debug/main -lSDL2main -lSDL2 -lSDL2_image && ./bin/debug/main"],
"selector": "source",
"shell": true
},
{
"name": "Release",
"working_dir": "${project_path}",
"cmd": ["g++ -c src/*.cpp -std=c++14 -m64 -O3 -Wall -I include && g++ *.o -o bin/release/main -lSDL2main -lSDL2 -lSDL2_image && mv bin/release/main bin/release/main.app/Contents/MacOS/ && dylibbundler -od -b -x ./bin/release/main.app/Contents/MacOS/main -d ./bin/release/main.app/Contents/libs/ && ./bin/release/main.app/Contents/MacOS/main"],
"selector": "source",
"shell": true
}
]
}