Skip to content

Commit fc03a8c

Browse files
committed
feat(blog): add post about SDL, CPM and CMake
1 parent 948da2a commit fc03a8c

7 files changed

Lines changed: 273 additions & 0 deletions

File tree

177 KB
Loading
99.3 KB
Loading
186 KB
Loading
177 KB
Loading
144 KB
Loading
Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
---
2+
date: 2023-09-09T03:11:08.658Z
3+
categories:
4+
- GameDev
5+
- C++
6+
- CMake
7+
- CPM
8+
- SDL3
9+
- SDL2
10+
- CLion
11+
authors:
12+
- tolstenko
13+
---
14+
15+
# Setup SDL with CMake and CPM
16+
17+
In my opinion, the minimum toolset needed to give you the hability to start creating games cross-platform from scratch is the combination of the following tools:
18+
19+
1. [CLion](https://www.jetbrains.com/clion/) - Cross-platform C++ IDE with embedded CMake support
20+
21+
- [Apply for a student license](https://www.jetbrains.com/community/education);
22+
- [Download](https://www.jetbrains.com/clion/download) and install it;
23+
- For Macs, you will need extra tools: `XCode` and the command line tools. You can install them by running `xcode-select --install` on the terminal;
24+
25+
2. (Required for Windows) [Git](https://git-scm.com/) - Version control system
26+
27+
- [Download](https://git-scm.com/downloads) only if you are on Windows and add don't forget to tick the option to add it to your environment path (CMake will be calling it). On Mac and Linux, you can install via your package manager (ex. brew on Mac e apt on Ubuntu).
28+
29+
3. (Optional but desirable) [GitKraken](https://www.gitkraken.com/) - Git GUI
30+
31+
- [Apply for a student license through GitHub Student Pack](https://education.github.com/pack)
32+
- [Login into GitKraken via social login with your GitHub account](https://www.gitkraken.com/github-student-developer-pack-bundle)
33+
34+
After installing the tools above, you can follow the steps below to create a new project:
35+
36+
## CLion project
37+
38+
1. Open CLion and select `New Project`:
39+
40+
![Welcome](CLionWelcome.png)
41+
42+
2. Create a new project and select `C++ Executable` and `C++XX` as the language standard. Use the default compiler and toolchain:
43+
44+
![New Project](CLionNewProject.png)
45+
46+
3. Start coding:
47+
48+
![CLionIDE](CLionIDE.png)
49+
50+
You might note the existence of a `CMakeLists.txt` file on the left side of the IDE on the `Project` tab. This file is used by CMake to generate the build files for your project. Now we are going it to set up everything you need to use `SDL3`. If you open the `CMakeLists.txt` file, you will see something similar to the following:
51+
52+
```cmake
53+
# cmake_minimum_required(VERSION <specify CMake version here>)
54+
cmake_minimum_required(VERSION 3.26)
55+
# project(<name> [<language-name>...])
56+
project(MyGame)
57+
# set(CMAKE_CXX_STANDARD <specify C++ standard here>)
58+
set(CMAKE_CXX_STANDARD 17)
59+
# add_executable(<name> file.cpp file2.cpp ...)
60+
add_executable(MyGame main.cpp)
61+
```
62+
63+
## CPM - C++ Package Manager
64+
65+
CPM is a setup-free C++ package manager. It is a single CMake script that you can add to your project and use it to download and install packages from GitHub. It is a great tool to manage dependencies and it is used by many C++ projects.
66+
67+
You can make this as simple as adding the following lines to your `CMakeLists.txt` file (after the `project` command):
68+
69+
```cmake
70+
set(CPM_DOWNLOAD_VERSION 0.38.2)
71+
72+
if(CPM_SOURCE_CACHE)
73+
set(CPM_DOWNLOAD_LOCATION "${CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
74+
elseif(DEFINED ENV{CPM_SOURCE_CACHE})
75+
set(CPM_DOWNLOAD_LOCATION "$ENV{CPM_SOURCE_CACHE}/cpm/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
76+
else()
77+
set(CPM_DOWNLOAD_LOCATION "${CMAKE_BINARY_DIR}/cmake/CPM_${CPM_DOWNLOAD_VERSION}.cmake")
78+
endif()
79+
80+
# Expand relative path. This is important if the provided path contains a tilde (~)
81+
get_filename_component(CPM_DOWNLOAD_LOCATION ${CPM_DOWNLOAD_LOCATION} ABSOLUTE)
82+
83+
function(download_cpm)
84+
message(STATUS "Downloading CPM.cmake to ${CPM_DOWNLOAD_LOCATION}")
85+
file(DOWNLOAD
86+
https://github.com/cpm-cmake/CPM.cmake/releases/download/v${CPM_DOWNLOAD_VERSION}/CPM.cmake
87+
${CPM_DOWNLOAD_LOCATION}
88+
)
89+
endfunction()
90+
91+
if(NOT (EXISTS ${CPM_DOWNLOAD_LOCATION}))
92+
download_cpm()
93+
else()
94+
# resume download if it previously failed
95+
file(READ ${CPM_DOWNLOAD_LOCATION} check)
96+
if("${check}" STREQUAL "")
97+
download_cpm()
98+
endif()
99+
unset(check)
100+
endif()
101+
102+
include(${CPM_DOWNLOAD_LOCATION})
103+
```
104+
105+
This will download the `CPM.cmake` file to your project and you can use it to download and install packages from GitHub.
106+
107+
In order to checx if `CPM` is being automatically downloaded, you can go to `CLion` and click on `CMake` :simple-cmake: icon the left side of the `Project`, it is the first one on the bottom. And then click the `Reload CMake Project` :material-reload: button:
108+
109+
![CLionRefreshCMake](CLionRefreshCMake.png)
110+
111+
Now that you have `CPM`, you can start adding packages to your project. Here goes some ways of doing that:
112+
113+
```cmake
114+
# A git package from a given uri with a version
115+
CPMAddPackage("uri@version")
116+
# A git package from a given uri with a git tag or commit hash
117+
CPMAddPackage("uri#tag")
118+
# A git package with both version and tag provided
119+
CPMAddPackage("uri@version#tag")
120+
# examples:
121+
# CPMAddPackage("gh:fmtlib/fmt#7.1.3")
122+
# CPMAddPackage("gh:nlohmann/json@3.10.5")
123+
# CPMAddPackage("gh:catchorg/Catch2@3.2.1")
124+
# An archive package from a given url. The version is inferred
125+
# CPMAddPackage("https://example.com/my-package-1.2.3.zip")
126+
# An archive package from a given url with an MD5 hash provided
127+
# CPMAddPackage("https://example.com/my-package-1.2.3.zip#MD5=68e20f674a48be38d60e129f600faf7d")
128+
# An archive package from a given url. The version is explicitly given
129+
# CPMAddPackage("https://example.com/my-package.zip@1.2.3")
130+
131+
# A complex package with options:
132+
CPMAddPackage(
133+
NAME # The unique name of the dependency (should be the exported target's name)
134+
VERSION # The minimum version of the dependency (optional, defaults to 0)
135+
OPTIONS # Configuration options passed to the dependency (optional)
136+
DOWNLOAD_ONLY # If set, the project is downloaded, but not configured (optional)
137+
GITHUB_REPOSITORY # The GitHub repository (owner/repo) to download from (optional)
138+
GIT_TAG # The git tag or commit hash to download (optional)
139+
[...] # Origin parameters forwarded to FetchContent_Declare
140+
)
141+
```
142+
143+
## SDL
144+
145+
Now that we have `CPM` set up, we can use it to download and install `SDL`. If you want to try the stable version `v2`, add the following lines to your `CMakeLists.txt` file and refresh CMake:
146+
147+
```cmake
148+
CPMAddPackage(
149+
NAME SDL2
150+
GITHUB_REPOSITORY libsdl-org/SDL
151+
GIT_TAG release-2.28.3
152+
VERSION 2.28.3
153+
)
154+
```
155+
156+
If you don't have `git` installed on your machine, you might want to use the `ZIP` version(it is even faster to download, but slower to switch versions). In this case, you can use the following lines and refresh CMake:
157+
158+
```cmake
159+
CPMAddPackage(
160+
NAME SDL2
161+
URL "https://github.com/libsdl-org/SDL/archive/refs/tags/release-2.28.3.zip"
162+
VERSION 2.28.3
163+
)
164+
```
165+
166+
If you want to try the bleeding edge version `v3`, add the following lines to your `CMakeLists.txt` file at your own risk:
167+
168+
```cmake
169+
CPMAddPackage(
170+
NAME SDL3
171+
GITHUB_REPOSITORY libsdl-org/SDL
172+
GIT_TAG main
173+
)
174+
```
175+
176+
Now that we have `SDL` set up, we should link it to our project. In order to do that, we can add the following lines after the line `add_executable` to our `CMakeLists.txt` file and refresh CMake:
177+
178+
```cmake
179+
target_link_libraries(MyGame SDL2::SDL2)
180+
# change SDL2 to SDL3 if you are using the bleeding edge version
181+
#target_link_libraries(MyGame SDL2::SDL2)
182+
```
183+
184+
And this will make `SDL` available to our project. Now we can start coding. Let's create a simple window:
185+
186+
```cpp
187+
#include <SDL.h>
188+
189+
int main(int argc, char** argv) {
190+
SDL_Init(SDL_INIT_VIDEO);
191+
192+
SDL_Window* window = SDL_CreateWindow(
193+
"SDL2Test",
194+
SDL_WINDOWPOS_UNDEFINED,
195+
SDL_WINDOWPOS_UNDEFINED,
196+
640,
197+
480,
198+
0
199+
);
200+
201+
SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
202+
203+
SDL_Event e;
204+
bool quit = false;
205+
while (!quit){
206+
while (SDL_PollEvent(&e)){
207+
if (e.type == SDL_QUIT){
208+
quit = true;
209+
}
210+
}
211+
212+
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
213+
SDL_RenderClear(renderer);
214+
SDL_RenderPresent(renderer);
215+
SDL_Delay(0);
216+
}
217+
218+
SDL_DestroyWindow(window);
219+
SDL_Quit();
220+
221+
return 0;
222+
}
223+
```
224+
225+
If you feel that you want to test the bleeding-edge version, you can use this code instead:
226+
227+
```cpp
228+
#include <SDL.h>
229+
230+
int main(int argc, char* argv[]) {
231+
SDL_Init(SDL_INIT_VIDEO);
232+
233+
SDL_Window *window = SDL_CreateWindow(
234+
"MyGame",
235+
640,
236+
480,
237+
0
238+
);
239+
240+
SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr, SDL_RENDERER_ACCELERATED);
241+
SDL_Event e;
242+
bool quit = false;
243+
244+
while (!quit) {
245+
while (SDL_PollEvent(&e)) {
246+
if (e.type == SDL_EVENT_QUIT) {
247+
quit = true;
248+
}
249+
}
250+
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
251+
SDL_RenderClear(renderer);
252+
SDL_RenderPresent(renderer);
253+
SDL_Delay(0);
254+
}
255+
256+
SDL_DestroyWindow(window);
257+
SDL_Quit();
258+
259+
return 0;
260+
}
261+
```
262+
263+
Now you have a way to code games with `SDL` in a way that is cross-platform, and easy to setup.
264+
265+
If you hit `Run` or `Debug` on `CLion`, you will see a window like this:
266+
267+
![ClionDebug](CLionDebug.png)
268+
269+
and then:
270+
271+
![MyGame](MyGame.png)
272+
273+
I hope it works for you. If you have any problems, please let me know on Discord or via GitHub issues.
42.4 KB
Loading

0 commit comments

Comments
 (0)