If you need a single executable file for the game that doesn't rely on other shared libraries being present, then what you want to do is to create a 'static' compilation. Whether or not this is possible will depend on what the libraries you depend on are, as they will need to be compiled statically into the binary along with the code that you write. This sometimes doesn't work... I guess an example would be libcurl, something to do with the networking part of glibc that it, in turn, relies on, so you will have a difficult time statically compiling code that relies on libcurl.
But of course, many games don't rely on libcurl (or any of the other libs that are resistant to static linking), so often it is quite possible, in the case of SDL2 you need to first do a static build of SDL2, this will produce a file libSDL2.a
, the .a
extension is used for static libraries. Then, when you compile your program, you need to link to libSDL2.a
instead of the dynamic version of the library and you need to use your compiler's flag for a static build, in the case of GCC the flag is -static
.
I think SDL's default build creates both the static and dynamic versions, so follow their normal compilation instructions to get the .a
file. An example of its use and more details are provided in Wasin's blog, reproduced here:
gcc -Wall appcode.c /usr/local/lib/libSDL2.a -lm -liconv
-Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,ForceFeedback -lobjc -Wl,-framework,CoreVideo -Wl,-framework,Cocoa -Wl,-framework,Carbon -Wl,-framework,IOKit -Wl,-weak_framework,QuartzCore -Wl,-weak_framework,Metal
Let's break that down a bit. Most of this is generated by SDL2's compilation helper and is for what libraries SDL2 needs to pull in for what you're doing, these will all be in your .a
file, but must still be named. We'll come back to these in a minute, but first, the parts that are important here are:
gcc -Wall appcode.c /usr/local/lib/libSDL2.a
gcc
here is our compiler, -Wall
just means to give 'all' warnings (but not really all, just a lot, to actually get all warnings you need some more flags, off the top of my head maybe -Wextra
or -pedantic
), not strictly needed for this. appcode.c
is the game code you wrote, so put your file name there, and finally there is the statically compiled SDL2, the .a
file.
How did we find this other long list of stuff? As Wasin explains on his page, it comes from the command sdl2-config --static-libs
, and then he removes the -L ... -lSDL2
part from the front because that is for the dynamic compilation of SDL2 itself and we want even that to be static here. The sdl2-config
should come from SDL2 when you compile the library.
I think the key part that you need is that, in order to not have external dependencies, what you need to search for is how to statically compile your program. A statically compiled program should be good to go typically across a given OS+architecture combination, e.g. 64-bit Arm+Linux or 32bit x86 + Windows98 so you probably want to use only those general optimizations for as broad of architecture support as possible (that is, use a compiler flag for architecture like -m64
and -m32
, which targets 64 and 32 bit in general in order to support a wide range of architectures, not something -march=native
).
To build a statically compiled SDL2 app for Windows is basically the same main steps.
- Build SDL2 on your Windows dev machine and find where it put the static library (
libSDL2.a
).
- Use the SDL2 tool to find the other libs that need pulling in (
sdl2-config --static-libs
).
- Use some compiler on Windows to compile your program while linking to the static version of SDL2 (the
.a
file) and the static libs that the tool listed).
Alternatively, this can be possible to do all from Linux while targeting a Windows build via cross-compiling, but the details of that are beyond the scope I wish to cover here.
NOTE: This answer is for SDL2, it is my understanding that SDL1.2 is not as friendly to static linking.
Also note that if you do something like getting your game on Steam for your Windows users, they provide an included version of SDL1.2 and SDL2 with the Steam Runtime, so anyone downloading from Steam will not need to install SDL on their own as they will already have it. Actually, if they have Steam but your game isn't on Steam, I think it is still possible for them to use the runtime for your game. They would use the option to add a non-Steam game to their Steam library, and then right-click it and go to properties, then to the compatibility part and check the box to force compatibility settings and pick Steam Runtime from the dropdown menu. I mean, you probably don't want to ask them to install Steam just to play your game, but it might be an easy option if they mostly have Steam anyway.
Finally, there are reasons NOT to use a static library. Their benefits are mainly that they tend to be portable and reliable due to having few dependencies, mainly just OS and CPU architecture. Some of their downsides go hand-in-hand with the benefits. For instance, when shared libraries are patched for security and performance, the versions in the static compilation will not be unless you rebuild it with the new versions and your users download the new version. If you rely on large shared libraries normally (dynamic linking), then building statically can make your executable very large, as those shared libs all need to be in there in static form. Also, remember how I mentioned that when we build statically, we typically only optimize for a very general architecture? This means we may have less performance since the dynamic libraries on a particular user's system might be built for their specific architecture (e.g. I hear Gentoo users like to compile with -march=native
). But on the plus side, static compilation could potentially allow better joint compilation optimization across libs and avoid the (arguably quite small) overhead of calling to an external dynamic library.
I'm sure there may be other potential snags I have overlooked, having not tested the process myself firsthand. Please feel free to add corrections and details in the comments. I know the question is old, but I answered because I was looking myself and it came up high in the search results.
libgcc...dll
,libstdc++...dll
,libwinpthreads...dll
- all of those are distributed with the compiler). \$\endgroup\$