SFML as a Dependency in a CMake Project
Note: This article was written in 2021, and targets SFML 2.5 and CMake version 3.19. Details may differ for newer versions of SFML or CMake.
In my last two posts, I introduced SFML, the Simple and Fast Multimedia Library, and CMake, the cross-platform build system for C++ projects. Now I'll be showing how to use the FetchContent module to pull in SFML as a dependency in a CMake project.
This post is relevant for Visual Studio, and should be fine for all Windows or MacOS compilers. For Linux developers, there may be additional steps needed to handle SFML's own dependencies.
Example CMake Project with an SFML Dependency
In a previous blog post, I included a reference to an example Visual Studio project that just opens a window and draws a circle. Here I'll be referencing an example CMake project with the exact same C++ source code. Instead of a Visual Studio solution and project file, there is a single CMakeLists.txt file that acts as the cross-platform build script.
cmake_minimum_required(VERSION 3.19)
project(SfmlWithCMake VERSION 1.0)
include(FetchContent)
set(BUILD_SHARED_LIBS OFF)
FetchContent_Declare(
SFML
GIT_REPOSITORY https://github.com/SFML/SFML.git
GIT_TAG 2.5.1
)
FetchContent_MakeAvailable(SFML)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED true)
add_executable(
SfmlWithCMake
main.cpp
)
target_link_libraries(
SfmlWithCMake
sfml-graphics
)
The include command tells CMake to make use of the FetchContent module.
The line set(BUILD_SHARED_LIBS OFF) is specific to the way I wanted to pull in SFML. I'm deciding that I want CMake to build SFML as a static library. Looking through SFML's own CMakeLists.txt build file, its default behaviour is to build it as a shared library for every platform but iOS:
# add an option for choosing the build type (shared or static)
if(NOT (SFML_OS_IOS OR SFML_OS_ANDROID))
sfml_set_option(BUILD_SHARED_LIBS TRUE BOOL "TRUE to build SFML as shared libraries, FALSE to build it as static libraries")
else()
if(SFML_OS_IOS)
set(BUILD_SHARED_LIBS FALSE)
elseif(SFML_OS_ANDROID)
set(BUILD_SHARED_LIBS TRUE)
endif()
endif()
The FetchContent_Declare command is used to tell CMake where it can find your dependency. In this example, CMake will download SFML from the Git tag named 2.5.1 during its generator phase.


The FetchContent_MakeAvailable command is then used to add the referenced project to the main build. Its targets become available for your own executables or libraries. In this example, the target_link_libraries command indicates that our SfmlWithCMake executable should link to the sfml-graphics library.
General Information About Dependencies in CMake
I've found that most third-party libraries have their own ideas on how their library should get built. Some default it to shared, others to static. Some force CMake to cache certain global variable values. Some provide variables that act as options for what targets get built. These decisions can sometimes have a negative impact on how the CMake environment behaves when the library is brought in through FetchContent.
In general, you'll need to scan through the library's CMake scripts to determine if there's anything special you'll need to do.
For the libraries I'm building, I've made a few key decisions that I believe can help make them work as a FetchContent dependency more easily:
- Avoid setting pre-defined variable values, such as
BUILD_SHARED_LIBS. - Avoid messing with the CMake cache.
- Provide separate targets for both a static and shared copy of the library.
- When providing any sort of compiler or build option, decide on a distinct common prefix for all such variable names. This will avoid naming conflicts with other third-party libraries.
I'll be continuing to post more about C++, CMake, and SFML in the future. Watch this blog, or check out the Riley Entertainment website for ongoing updates!