1
\$\begingroup\$

TL, DR: Will I be able to get a single .exe file which will work smooth in a PC which does not have SDL or so installed ever. If not, how close will be the closest approach?

Yes, now, I want to start game development using C/C++ and I am on a Linux machine.

From the resources on the web, I saw that SDL2 is a common API to use. However, I could not get satisfying answers about the following:

For me, it is important to be able to distrubite my games to my friends(let's say) with little amount of file. So, I wonder how this process works with SDL2. Will it be easy(or even possible, maybe?) to distribute a .exe file to my friends who are using Windows OS and don't have SDL2 installed? If it is so, a short description of the process would be very nice.

To make my point more clear, while I was using pygame module of python to develop a game(which includes sounds, images etc.), I was able to run pyinstaller with --onefile option on a Windows machine to get a single executable (.exe) and my friends who does not have even python installed was able to run the game without any problem. So my question is simply asking that whether it will be similar to this or not with SDL2 case.

Thanks in advance.

p.s: Using a Windows machine to build the game is something I can do.

\$\endgroup\$
14
  • \$\begingroup\$ You can't create a game on Linux and distribute it on Windows. If you want to distribute a game on Windows, you need to build it on Windows. \$\endgroup\$
    – Vaillancourt
    Commented Apr 9, 2020 at 23:26
  • \$\begingroup\$ If you decide to build and distribute with Windows, this recent question could be of interest. \$\endgroup\$
    – Vaillancourt
    Commented Apr 9, 2020 at 23:29
  • \$\begingroup\$ @Vaillancourt right, pardon me, of course, I cannot. What I want to say is this: suppose I have done my work for days and weeks and etc. and finally finished my game and works perfect on my machine. Now, how will the next steps, will going to a Windows machine(or a VM) and building it in there be enough? \$\endgroup\$
    – muyustan
    Commented Apr 9, 2020 at 23:29
  • 1
    \$\begingroup\$ Yes, correct. I want to note though that while using SDL_Image, the developer have to include some additional dll files, like libpng, libtiff etc, besides SDL_Image.dll, which is used by the SDL_Image library while loading different image file formats. \$\endgroup\$ Commented Apr 10, 2020 at 11:07
  • 1
    \$\begingroup\$ @muyustan Depending on the compiler, you might need to provide some other dlls. If you use MSVC, users will either have to install a "Visual C++ Redistributable", or you can redistribute dlls from it alongside the game. If you use MinGW (which should be easier, if you're used to linux), you'll need to ship some extra dlls too (something along the lines of libgcc...dll, libstdc++...dll, libwinpthreads...dll - all of those are distributed with the compiler). \$\endgroup\$ Commented Apr 10, 2020 at 20:32

1 Answer 1

1
\$\begingroup\$

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.

  1. Build SDL2 on your Windows dev machine and find where it put the static library (libSDL2.a).
  2. Use the SDL2 tool to find the other libs that need pulling in (sdl2-config --static-libs).
  3. 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.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .