CMake Config in Windows/Clion

Hey everyone,

I started toying with SDL again. Last time I was using Linux/Make and including and linking was relatively straight forward.
This time I am on a Windows 10 machine using CLion, MinGW as Toolchain and CMake. The whole thing is just a pain…

What I am trying to do is, have an “SDK” Folder in my project with all the libraries I need to link, so I can create a simple .zip/Git with the whole thing setup to start experimenting with small projects.

I managed to setup SDL2 and SDL2_image. Then I set up SDL2_ttf and SDL2_mixer in exactly the same way and it does not find the header files.
CMake on the other hand does not complain.

I can #include them directly, giving the full path, but that seems wrong.

I also seem to need to give the full path for libraries from the add-on libraries, while SDL2 is just fine with the path to a folder?

As I am new to this, I don’t even know exactly where to start debugging this. CMake right now feels super opaque in how it works to me.
Is there some kind of guide somewhere?

This is my CMakeLists.txt so far.

cmake_minimum_required(VERSION 3.24)
# Set the project Name
project(SDLBaseSetup)
#Set the C Standard to compile against
set(CMAKE_CXX_STANDARD 17)

#Set Directories for SDL2
set(SDL2_DIR ${CMAKE_SOURCE_DIR}/SDK/SDL2/cmake) #Here it will wind a config.cmake
set(SDL_LIB_DIR ${CMAKE_SOURCE_DIR}SDK/SDL2/lib) #Here are the library files located
#Set Directories for SDL2_image
set(SDL2_image_DIR ${CMAKE_SOURCE_DIR}/SDK/SDL2_image/cmake)
set(SDL2_IMAGE_LIBRARIES ${CMAKE_SOURCE_DIR}/SDK/SDL2_image/x86_64-w64-mingw32/lib/libSDL2_image.dll.a)
#Set Directories for SDL2_ttf
set(SDL2_ttf_DIR ${CMAKE_SOURCE_DIR}/SDK/SDL2_ttf/cmake)
set(SDL2_ttf_LIBRARIES ${CMAKE_SOURCE_DIR}/SDK/SDL2_ttf/x86_64-w64-mingw32/lib/libSDL2_ttf.dll.a)
#Set Directories for SDL2_mixer
set(SDL2_mixer_DIR ${CMAKE_SOURCE_DIR}/SDK/SDL2_mixer/cmake)
set(SDL2_mixer_LIBRARIES ${CMAKE_SOURCE_DIR}/SDK/SDL2_mixer/x86_64-w64-mingw32/lib/libSDL2_mixer.dll.a)


#Statically link the standard library into your executable
set(CMAKE_EXE_LINKER_FLAGS "-static")

find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
find_package(SDL2_ttf REQUIRED)
find_package(SDL2_mixer REQUIRED)
include_directories(${SDL2_INCLUDE_DIRS} ${SDL2_image_DIR} ${SDL2_ttf_DIR} ${SDL2_mixer_DIR})

add_executable(SDLBaseSetup main.cpp LTexture.cpp LTexture.h)
target_link_libraries(${PROJECT_NAME} ${SDL2_LIBRARIES} ${SDL2_IMAGE_LIBRARIES} ${SDL2_ttf_LIBRARIES} ${SDL2_mixer_LIBRARIES})

Thank you so much in advance for any info!

Best regards!
poetoem

Hi,

I’m using the same stack and successfully building using macOS, Linux, and Windows.

My project is divided into an internal library and the game executable. It did take a couple of weeks of trial and error to get everything to work.

The root CMake looks like this,

cmake_minimum_required (VERSION 3.8)
project ("Game" VERSION 1.0.0)

set(CMAKE_VERBOSE_MAKEFILE ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

if(NOT MSVC AND NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Debug")
endif()

if(MSVC)
    set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
endif()

include(FetchContent)
FetchContent_Declare(spdlog
        GIT_REPOSITORY https://github.com/gabime/spdlog
        GIT_TAG v1.11.0
        )
FetchContent_MakeAvailable(spdlog)

set(SDL2_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/SDL2/cmake)
set(SDL2_image_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/SDL2_image/cmake)
set(SDL2_ttf_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/SDL2_ttf/cmake)

find_package(SDL2 REQUIRED)
find_package(SDL2_image REQUIRED)
find_package(SDL2_ttf REQUIRED)

add_subdirectory(Internal)
add_subdirectory(Game)

In the internal library’s and game’s CMakeLists.txt, I then link the library/executable with appropriate libraries like this,

target_link_libraries(
        Game
        PUBLIC
        Internal
        SDL2::SDL2
        SDL2_image::SDL2_image
        SDL2_ttf::SDL2_ttf
        spdlog
)

The directory structure is something like this:

CMakeLists.txt
deps/SDL2
deps/SDL2_image
deps/SDL2_ttf
Internal/CMakeLists.txt
Game/CMakeLists.txt

Only Windows builds need the deps/ directory. Other OS’es find the SDL version I’ve installed using homebrew/pacman.

2 Likes

Thanks so much for the reply.

I tried to recreate the things that are different to my setup, but I still get this error on SDL2_ttf and SDL2_mixer:

fatal error: SDL_ttf.h: No such file or directory

SDL_image works fine with exactly the same setup.
I include them like this:

#include <SDL_ttf.h>
#include <SDL_mixer.h>

Not sure how to help you with that any further, it clearly doesn’t find some of the header files.

If it helps you, this is the cmake file I have in Game/CMakeLists.txt

project(Game)

file(GLOB_RECURSE GAME_SOURCES *.cpp *.h)

set(SOURCES
        main.cpp
        ${GAME_SOURCES}
        )

add_executable(
        Game
        ${SOURCES}
)
target_link_libraries(
        Game
        PUBLIC
        Internal
        SDL2::SDL2
        SDL2_image::SDL2_image
        SDL2_ttf::SDL2_ttf
)

add_custom_command(TARGET Game POST_BUILD
        COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_RUNTIME_DLLS:Game> $<TARGET_FILE_DIR:Game>
        COMMAND_EXPAND_LISTS
        )
1 Like

One thing I noticed. With a modern CMake, this is not required:

The find_package should set the appropriate directories automatically.

Also, maybe some of the headers are not found because target_link_libraries can’t find the library in question? I think you should use the alias the find_package creates, like in the example I gave.

1 Like

Thanks for that! That’s very interesting!

Okay, I got rid of include_directories but that did not resolve the problem, sadly.

So just to clarify: set(SDL2_image_DIR ${CMAKE_SOURCE_DIR}/SDK/SDL2_image/cmake) sets a variable to this path, which contains two cmake config files.

find_package(SDL2_image REQUIRED) would look into that path and configure SDL2_image and should complain if it does not find everything?
So if this works, it should find the headers and should be able to compile, right?

target_link_libraries tells the linker to link the libraries, but compilation should already work at this point?

I’m not an expert in cmake, but that’s how I got it working. The find_package should complain to CLion’s cmake tab if it doesn’t find it. For me, the header files start working properly only after the target_link_libraries finds the correct libraries.

These two threads helped me to get the compilation working,

1 Like

By the way, if it helps you in debugging CMake files, I use this snippet to print out all the variables for it available:

# debug
get_cmake_property(_variableNames VARIABLES)
list(SORT _variableNames)
foreach (_variableName ${_variableNames})
    message(STATUS "${_variableName}=${${_variableName}}")
endforeach ()
# /debug
1 Like

Thanks so much for the support!
The debug snippet was really useful.

I found that some paths were off - I guess while trying to solve the issue I broke some things…
I rebuild the whole project using fresh downloads of the libraries and a fresh CLion project, and now it seems to work.

Thanks!

1 Like

Hey, if you are using the latest CLion version it includes a debugger on the CMake it ships alongside - it’s 3.24.2 I believe.

It’s pretty amazing to understand things not working in CMake.

Oh wow, thanks! Somehow I’ve completely missed this feature.

1 Like