How to use Dear ImGui and SDL2 with CMake and vcpkg (C++)
This tutorial walks through setting up CMake, vcpkg, Dear ImGui and SDL2 into a simple cross-platform (Windows, Linux) project.
Assumes basic CMake knowledge, and some C++ knowledge.
Full source code is on GitHub.
If you enjoy the post or want to help out, my social media links, as well as contact and donation options are in the about section, or at the bottom of the page.
The result of this post:
… Contained in a single .git repo, with OpenGL, CMake and git as the only hard dependencies.
Table of Contents
Motivation
CMake1 and vcpkg2 work quite well together, when set up correctly.
All it takes, then, to pull all dependencies and build, is simply having git
, cmake
and running cmake -S . -B build
- a pretty good dev experience as far as C++ goes.
You can find an example CMakeLists.txt with vcpkg in my kv-api project on GitHub (the template will be published on GitHub soon, follow me on GitHub, or use the RSS feature of this blog as I will publish an article on it).
BUT: A lot of packages and libraries available on vcpkg do not actually give an explanation of how to use them. Dear ImGui3 is one of those - it doesn’t even come with a CMakeLists.txt file.
In this post, I aim to walk through the entire process of setting up a cross-platform GUI app using these technologies.
Integrating CMake and vcpkg
You will need git
, cmake
and a C++ compiler. vcpkg
is not required to be installed (and will be ignored if it is).
As a demo, we will also install the fmt
library via vcpkg
in this tutorial.
1. Create a git repository for your project
Now add your remote(s), create some project files, etc.
2. Add vcpkg
By adding vcpkg as a git submodule, it is included in our source tree, while staying up-to-date. To update vcpkg later (like when you run into any “ports” related errors), simply run git -C vcpkg pull -r
or similar.
3. Make a CMakeLists.txt
You can skip this step and step 4, if you already have a working cmake + vcpkg setup and cmake is set up to use the vcpkg toolchain file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
include(cmake/Vcpkg.cmake) # needs to happen before project()
project(
"MY_PROJECT" # replace this with the name of your executable
VERSION 0.1.0
LANGUAGES CXX
)
# add all headers (.h, .hpp) to this
set(PRJ_HEADERS )
# add all source files (.cpp) to this, except the one with main()
set(PRJ_SOURCES )
# set the source file containing main()
set(PRJ_MAIN src/main.cpp)
# add library targets here
set(PRJ_LIBRARIES
fmt::fmt
)
# add dependency find_package calls and similar here
find_package(fmt CONFIG REQUIRED)
add_executable(${PROJECT_NAME} ${PRJ_HEADERS} ${PRJ_SOURCES} ${PRJ_MAIN})
target_link_libraries(${PROJECT_NAME} PRIVATE ${PRJ_LIBRARIES})
This is a long file, and needs explaining.
Line 1: requires a modern version of CMake – this one assumes we want C++20, so 3.16 is reasonable, but you can change it.
Line 3: Includes cmake/Vcpkg.cmake
– a file we didn’t make yet. It will bootstrap vcpkg for us, from the cloned vcpkg submodule (from step 2). Don’t worry about this just yet.
Lines 5-9: Set up the project name, version. Replace the project name and version with your own.
Lines 12, 14, 16: Variables where you add your source files. As your project grows, you will add headers and source files – simply put them here. src/main.cpp
is assumed to exist, make it with a simple “hello world” file, if it doesn’t. The reason it’s separate is to make it easier to integrate with doctest
or similar unit testing later.
Lines 19-21: Libraries! This is where you put targets, all these go into a target_link_libraries
CMake call. If vcpkg tells you to put something there, put it here instead.
Line 24: Looks for the fmt
library. This is our example dependency.
The rest of the file is default CMake stuff, like declaring a executable target.
4. Create cmake/Vcpkg.cmake
Make a folder called cmake
. Create a file cmake/Vcpkg.cmake
:
This is quite complicated, but what it does is quite simple:
- Checks if the vcpkg git submodule is checked out. If not, finds
git
(orgit.exe
), and runsgit submodule update --init --recursive vcpkg
to clone it. - Sets the
CMAKE_TOOLCHAIN_FILE
to thevcpkg.cmake
toolchain file included invcpkg
.
This causes the vcpkg submodule to be checked out if it wasn’t (it won’t be if someone just clones your repo), and then causes vcpkg to be used as the toolchain file, which causes vcpkg to bootstrap (“install”) itself (just locally in the build folder).
5. Create vcpkg.json
vcpkg.json
specifies our dependencies. The find_package()
call in the CMakeLists.txt
only finds a dependency if it’s actually installed! vcpkg installs it for us, if its specified in the vcpkg.json
. This way of using vcpkg is called “manifest mode”.
Here, again, replace name
and version-string
to match your project’s name and version (if you want).
In the dependencies
array, we can see the fmt
dependency. You can find these package names on vcpkg.io2, but they are usually intuitive.
6. Add Dear ImGui and bindings
Now to add SDL2 and ImGui! In this example, we will use Dear ImGui with SDL2 and OpenGL3 support. I recommend you follow along with this for now.
To your vcpkg.json
, add the dependencies imgui
and sdl2
with the relevant features enabled:
A vcpkg.json
dependency may specify additional features – this is necessary here, as only the imgui package itself doesn’t include the opengl3 or sdl2 bindings needed.
Next, to your CMakeLists.txt
, modify the PRJ_LIBRARIES
so it looks as follows:
… And finally, add the following below the similar call to find_package(fmt...
:
NOTE: You will need to make sure, if you’re not on Windows, that you do have OpenGL installed.
7. Write ImGui + SDL2 code
Create src/main.cpp
if you didn’t already, and write the following code:
Now is a good time to run cmake and see if it builds. This may be a point where any issues or missing packages will become apparent.
This may take a while the first time you run (the configure step downloads and builds the dependencies). It should run without issues. If you run into problems, make sure you executed all steps properly. The vcpkg CMake output may also show you possible fixes, such as installing other packages on the system.
You should now have an executable in the bin
folder. On Linux, you are likely to find it in ./bin/<name>
where <name>
is the name you gave your project in the CMakeLists.txt
. On Windows, it will likely be in ./bin/Debug/
in a subfolder somewhere, named <name>.exe
(again, <name>
will be the name of the project). Running it should print “hello, world!”.
If this works without issues, move on to write more code. In the following part, we just adapted the example from ImGui to use the right #include
s, and to make it easier to read and less complicated.
This is quite long - you can pull the full source code from GitHub.
8. Running & next steps
If you ran the code before, when it was a “hello world”, you can skip the configure step, and just run the build step.
Now, you are set up and can start developing your application.
It should look like this when run:
For your convenience, I’ve left some resources for learning SDL2, OpenGL and ImGui here, though you can skip all setup code for SDL2, ImGui and OpenGL (like GLEW, GLFW, etc.) as that’s included in the code from this tutorial.
If you enjoy the post or want to help out, my social media links, as well as contact and donation options are in the about section, or at the bottom of the page.
Troubleshooting
If you run into issues, here is a collection of common problems and solutions I ran into while researching / writing this post.
Sanity checks
Please carefully walk through these points and check all of them. After, try again.
- Ensure
git
is installed.git --version
should run without errors. - Ensure
cmake
is installed.cmake --version
should run without errors. - Ensure you have a C++ compiler installed. For example, on Linux,
cxx --version
should work without errors. On windows, you need the Windows SDK installed (included with Visual Studio (not Visual Studio Code)). - Ensure your C++ compiler supports a recent version of the C++ standard, such as C++17.
- Ensure OpenGL is installed and working. For example, on Linux, you can install and run
glxgears
, orglinfo
. - Pull the source code from GitHub and try it out. That way, you can check if you missed something.
vcpkg error(s)
If you get vcpkg errors, you may need to update vcpkg. For this, run the following from your project’s root directory:
or simply git -C vcpkg pull
. This can sometimes fail - but basically, you want to update vcpkg by checking out the latest commit.