Building SDL2 from Source (GCC and Make)
This guide walks you through the process of compiling SDL2, SDL_image, and SDL_ttf libraries from source
In this lesson, we'll get SDL installed, along with two extensions which we'll need later in this chapter.
SDL
is a cross-platform library that allows us to create windows, access input devices, and create graphics.SDL_image
is an extension that allows us to work with images in all the common formats (jpeg, png, etc)SDL_ttf
is an extension that we can use to render text at run-time
This setup guide downloads the source code for the libraries and compiles them on our local machine. We then demonstrate how to add these libraries to projects that use either Xcode or CMake
Note that this guide is more advanced than our earlier options. If we just want to get up and running with SDL on Windows, most will find it easier to use a package manager:
Installing vcpkg on Windows
An introduction to C++ package managers, and a step-by-step guide to installing vcpkg on Windows and Visual Studio.
If we're using Windows or Mac, we do not need to compile the SDL libraries ourselves. Precompiled packages are available for those operating systems, which we can just download:
Setting up SDL2 in Windows (Visual Studio)
A step-by-step tutorial on configuring SDL2, SDL_image and SDL_ttf in a Visual Studio C++ project on Windows
Setting up SDL2 in macOS (Xcode or CMake)
This step-by-step guide shows you how to set up SDL2 in an Xcode or CMake project on macOS
If we want or need to build the libraries from source, and our environment supports CMake, this guide is recommended:
Building SDL2 from a Subdirectory (CMake)
A step-by-step guide on setting up SDL2 and useful extensions in a project that uses CMake as its build system
C++ Toolchains
Compiling SDL following this guide relies on using a suite of command line tools that can build C++ projects. This is sometimes referred to as a toolchain.
- On most Linux-based systems, the tools we need are installed by default
- On macOS, the tools are available if we've installed Xcode. Alternatively, we can install them from the official Apple Developer site. A dedicated guide for installing them is available on freecodecamp.org
- We don't cover Windows in this guide, but those interested in setting up a similar environment should consider the Windows Subsystem for Linux or follow the using MinGW guide on Microsoft's site.
Download the SDL Source Code
We'll be building SDL2 from the source code. This may seem daunting, but the SDL2 code comes with some very helpful scripts that make things much easier.
Once we have our compilation toolchain set up, we need to download the SDL source code from GitHub. The latest version of SDL will be available on the releases page on GitHub.
Important Note: this release page may include preview versions of SDL3. This course is using SDL2, so ensure the release you download starts with 2
(for example, 2.30.2
)
Once we've found the latest version 2 release, we want to download the source code - either as a zip
or tar.gz
file:

Once downloaded, we can decompress that into any location on our hard drive.
Building the Source Code
Next, we should navigate to the folder that was decompressed - typically it will be called SDL-main
. Within that folder, we should create a new folder, called build
.
Then, we should navigate to that build
folder within a terminal window:
- In MacOS, we can right-click on the folder and select New Terminal at Folder
- On Windows, we can right-click on the folder and select Open in Terminal
Step 1: configure
Once our terminal is open at the correct location, we can run the command:
../configure
The configure
script will scan your system to better understand how SDL2 should be compiled. It should be completed within a few seconds.
Step 2: make
When it is complete, run the command make
in the same build
location.
make
This command will take a little longer, as it is compiling SDL2.
Step 3: make install
When the make
process completes, we next need to install the software onto our machine. That can be done with the command: sudo make install
.
Again, we run this from the same build
folder we've used for all the previous commands:
sudo make install
Step 4: sdl2-config
Finally, when our make install
completes, we need to find out where the SDL libraries were installed, so we can use them in our projects.
To do this, we can run the following command, again from the build
folder:
sdl2-config --libs --cflags
This script will report where our SDL libraries were installed, and where the header files are that we will #include
in our source files.
The output may look something like below:
-L/usr/local/lib -lSDL2
-I/usr/local/include/SDL2 -D_THREAD_SAFE
We should make a note of this output, as we'll need it when we want to add SDL to one of our projects.
Summary
In summary, the 4 commands we need to run, in order, from the build folder are:
../configure
make
sudo make install
sdl2-config --cflags --libs
With this step complete, we have successfully compiled and installed SDL2 in our system, and we're ready to use it in our projects!
Adding SDL to a Project
Now that SDL is installed on our system, we can add it to our C++ projects. The way we do this depends on what tool we're using, but the basic idea involves updating our project settings based on the output from the sdl2-config
command we ran earlier.
The command outputs two directories:
- The directory where the SDL libraries were installed
- The directory where the SDL header files are, so the compiler can find them when we use the
#include
directive
In my case, the output of sdl2-config --cflags --libs
was:
-L/usr/local/lib -lSDL2
-I/usr/local/include/SDL2 -D_THREAD_SAFE
The exact formatting of this output is intended to be used in a command-line environment. But, if we're using an IDE to configure our project, we can extract the output we need.
For my example output, we can infer that:
- the libraries are available in
/usr/local/lib
- the header files are available in
/usr/local/include/SDL2
Your output may have been different, and therefore the paths you need to use may also be different.
Example: Xcode Project
Let's see an example of using these directories to add SDL to an Xcode project. The process for other IDEs is likely to be quite similar
Step 1: Adding the Library as a Dependency
Within the General tab, under the Frameworks and Libraries section, we can add a library using the + icon.

At the bottom of the popup menu, select Add Other, followed by Add Files.
Next, we need to navigate to the location suggested when we ran sdl2-config --libs --cflags
earlier.
My output was the following:
-L/usr/local/lib -lSDL2
-I/usr/local/include/SDL2 -D_THREAD_SAFE
We're interested in the lib
folder, so in my case, the location we want is /usr/local/lib
. Your location may have been different.
Either way, we need to navigate to the folder listed. The path may be hidden, so you may need to show hidden files (Command + Shift + . on macOS) to see the required path.
Once we're in the location, we want to select the .dylib
file:

Note that when configuring a project on Windows, the library will have a .dll
extension instead.
After selecting our library, the Framework and Libraries section of the project settings should be updated:

Step 2: Adding the Library and Header Search Paths
Finally, within the Build Settings tab of our project settings, we need to scroll down to the Search Paths section. There, we need to add the respective SDL locations to the Header Search Paths and Library Search Paths.
Again, these were the paths given by the sdl2-config --libs --cflags
command. We need to put the lib
path in the Library Search Paths section, and the include path in the Header Search Paths section.
In my case, it looks like this, but your paths may have been different:

With everything set up, we should now be able to #include
SDL files in our code, and start using it!
Example: CMake Project
Imagine we have the following cmake project:
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 20)
project(Sandbox VERSION 1.0.0)
add_executable(Sandbox main.cpp)
We need to add the SDL library and include directory to this file. Our earlier call to sdl2-config --libs --cflags
should have given us two directories we need. For example, my output was:
-L/usr/local/lib -lSDL2
-I/usr/local/include/SDL2 -D_THREAD_SAFE
This means:
- The SDL library is located in
/usr/local/lib
- The SDL header files are located in
/usr/local/include/SDL2
Adding the Libraries
To add the library as a project dependency, we need to find it within the library directory provided above. The library will have a .dylib
extension in macOS or Linux-based operating systems, and .dll
in Windows.
Once we've found it, we add it to our CMakeLists.txt
. This should come after our project()
call, and we should replace Sandbox
with the name of our project:
target_link_libraries(
Sandbox PRIVATE /usr/local/lib/libSDL2.dylib
)
Adding the Include Directories
Finally, we need to add the include directories to our CMakeLists.txt
. Again, this should come after our project()
call, and we replace Sandbox
with the name of our project:
target_include_directories(
Sandbox PRIVATE /usr/local/include/SDL2
)
My complete CMakeLists.txt
file looks like this:
cmake_minimum_required(VERSION 3.16)
set(CMAKE_CXX_STANDARD 20)
project(Sandbox VERSION 1.0.0)
add_executable(Sandbox main.cpp)
target_include_directories(
Sandbox PRIVATE
/usr/local/include/SDL2
)
target_link_libraries(
Sandbox PRIVATE
/usr/local/lib/libSDL2.dylib
)
Creating a Window
The following is a minimalist main.cpp
file that will test our setup. We'll explain every line of this program in the next chapter but, for now, let's just confirm it compiles and runs:
#include <SDL.h>
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
SDL_CreateWindow(
"Hello Window",
100, 100, 800, 300, 0
);
while(true) {
SDL_PumpEvents();
}
return 0;
}
If everything is working correctly, we'll see a window pop up when our program runs:

Note that this example program does not allow itself to be closed. We'll add that capability later in the course. For now, we can close it using our IDE if possible, or force it to close through our operating system (Ctrl + Alt + Del on Windows or Cmd + Option + Esc on macOS).
We'll update our program to support quitting early in the next chapter.
Building SDL_image and SDL_ttf
SDL2 has a collection of official extensions, that can add further capabilities to our project. In this course, we'll use SDL_image for handling images, and SDL_ttf for rendering text.
Step 1: Download the Source Code
To add them to our project, we first retrieve the source code for the latest 2.x releases. These are available from GitHub:
- The SDL_image releases are available here: https://github.com/libsdl-org/SDL_image/releases
- The SDL_ttf releases are available here: https://github.com/libsdl-org/SDL_ttf/releases
Step 2: Download External Dependencies
Building the SDL extensions from source involves an additional step that didn't apply to the base SDL library. The extensions have external dependencies, that we also have to download.
After we unzip the SDL_image and SDL_ttf releases, we'll see they contain an /external
directory. This is where their dependencies need to be inserted. There are some scripts in that directory that can automate this for us.
Linux / macOS users can open a terminal in the external
folder, and run the download.sh
script:
download.sh
Windows users can run the Get-GitModules.ps1
script in PowerShell instead:
Get-GitModules.ps1
Step 3: Build the Library
Once the /external
folder is populated with our dependencies, the remaining steps are the same as we covered when building the main SDL library:
- Create a
build
folder within the downloaded source code, then navigate to that build folder within a terminal - Run
../configure
- Run
make
- Run
sudo make install
- Run
sdl2-config --cflags --libs
and make a note of the output
Step 4: Add the Library as a Dependency
Once we've built the library, we need to add it as a dependency to our project. How we do that depends on the tools we're using, but it broadly involves following the same steps we performed when setting up the base SDL2 library.
In an IDE such as Xcode, this involves repeating the steps we covered earlier to add a new entry under the Frameworks and Libraries section
After adding SDL2, SDL_image, and SDL_ttf to my Xcode project, the libraries and framework section looks like this:

In a CMake project, this involves adding new entries to our target_link_libraries()
call:
target_link_libraries(Sandbox PRIVATE
/usr/local/lib/libSDL2.dylib
/usr/local/lib/SDL2_image.dylib
/usr/local/lib/SDL2_ttf.dylib
)
Step 5: Update the Search Paths
Finally, we need to update our search paths so our project can find the header files we #include
to access the library functions.
Note that the header files may be installed in the same location as the base SDL2 header files, so we may not need to make any further changes in this step.
In my case, make install
placed the SDL_image and SDL_ttf libraries and headers into the same folders as the base SDL2 library and headers, so no additional search paths were required:

In a CMake project, the target_include_directories
call of our CMakeLists.txt
could also remain the same:
target_include_directories(
Sandbox PRIVATE
/usr/local/include/SDL2
)
If our new header files were located elsewhere, we'd simply need to expand the search list in our IDE, or add additional include directories in our CMakeLists.txt
:
target_include_directories(
Sandbox PRIVATE
/usr/local/include/SDL2
/usr/local/include/SDL2-image
/user/local/include/SDL2-ttf
)
Step 6: Compiling and Running The Program
After completing these 5 steps for the SDL2, SDL_image, and SDL_ttf, we can test that everything is working correctly by adding and initializing SDL_image
and SDL_ttf
to our previous program, and ensure everything still runs as before:
#include <SDL.h>
#include <SDL_image.h>
#include <SDL_ttf.h>
int main(int argc, char** argv) {
SDL_Init(SDL_INIT_VIDEO);
IMG_Init(IMG_INIT_PNG);
TTF_Init();
SDL_CreateWindow(
"Hello Window",
100, 100, 800, 300, 0
);
while(true) {
SDL_PumpEvents();
}
return 0;
}

If the previous program fails to compile, it's generally going to be one of two problems - either the compiler can't find the files we're trying to #include
, or the linker can't find the symbols we're attempting to use, such as SDL_Init()
.
We can generally infer which problem we're dealing with based on the error messages. The inability to find an include file usually generates a descriptive error message, whilst linker errors will typically use terminology like "undefined symbol".
Summary
The key steps in building SDL2 from source involve downloading the code from GitHub, running the configuration and build scripts, and linking the compiled libraries to your project. With SDL2 and its extensions set up, you'll be ready to start developing! Key takeaways:
- SDL2 can be built from source on Linux and macOS using the provided configuration and build scripts
- SDL_image and SDL_ttf extensions add support for images and fonts
- Linking the compiled SDL2 libraries to your project requires specifying the library and include paths
- Troubleshooting common compilation, linking, and runtime errors is essential for a smooth development experience
Creating a Window
Learn how to create and customize windows, covering initialization, window management, and rendering