This book builds the game with Visual Studio, on Windows, because it's the smoothest start there is for C++ games: one installer, and a debugger that's hard to beat. But nothing in the game belongs to Windows. It's standard C++ and SDL, and SDL runs on macOS and Linux just as happily.
What changes is the tools around the code. Instead of Visual Studio, you'll write and debug in VS Code, a free editor from Microsoft that runs everywhere. And instead of Chapter 1's project settings, a tool called CMake builds the game, and fetches SDL for you. This appendix takes you from a bare machine to building and running every chapter's project, and your own. Then it goes through the places where the book's Windows steps work differently for you.
One difference is worth knowing before you start: on a Mac or on Linux, a seed makes a different dungeon. The game turns the dice's numbers into a range with std::uniform_int_distribution, and each standard library does that its own way, as Chapter 2's FAQ explains. So where a checkpoint gives a seed and says what you'll find, such as a jackal eight steps down, your dungeon has something else there. The game plays exactly the same; only the dice fall differently.
In this appendix, we will:
- Install a compiler, CMake, and VS Code, on a Mac or on Linux
- Build every chapter's project in the book's repository with one
CMakeLists.txtfile - Run the game from a terminal, and debug it from VS Code
- Type the game into a project of your own, beside the book's
- Translate the book's Visual Studio steps, and its error messages, into their Mac and Linux equivalents
First, though, a look at how the pieces fit together.
How It Fits Together
On Windows, each chapter's folder in the book's repository holds a Visual Studio project, and Chapter 1's settings tell it where SDL is. Visual Studio doesn't run on a Mac or on Linux, so the repository has one file that does that job there, for every chapter at once: CMakeLists.txt, at its top.
CMake reads that file, and works out how to build each chapter's game with whatever compiler your system has: Clang on a Mac, or GCC on Linux. It also checks whether SDL 3 and SDL_ttf are installed. If they aren't, it downloads their source code and builds them, once, the first time. After that, VS Code's CMake Tools extension puts the building behind a few commands.
So the plan is short. Install the tools, download the book's repository, open it in VS Code, and let CMake do the rest.
Setting Up a Mac
You need Apple's command-line developer tools, which include the Clang compiler and the LLDB debugger; Homebrew, which installs everything else; and VS Code.
- Open Terminal, from Applications > Utilities, and type this, then press Return:
xcode-select --install
A window asks whether to install the command line developer tools. Click Install. The tools are a few hundred megabytes, so they can take a while to arrive. When it's done, check that it worked:
clang --version
The answer should start with "Apple clang version", followed by a number.
-
Go to https://brew.sh, and copy the one-line install command shown on the page into Terminal. It explains what it's about to do, and asks for your password. When it finishes, it may print two or three commands under "Next steps", to add Homebrew to your path, and you should run those too.
-
Install CMake, and FreeType, which SDL_ttf uses to read fonts:
brew install cmake freetype
Then check CMake's version, which needs to be 3.24 or later:
cmake --version
- Download VS Code from https://code.visualstudio.com, open the download, and drag Visual Studio Code into your Applications folder. Start it, click the Extensions icon on the left, the one made of four squares, search for C/C++ Extension Pack, and install the one published by Microsoft. It brings the two extensions we need: C/C++, for editing and debugging, and CMake Tools, for building.
If you'd rather not wait for SDL to build the first time, Homebrew can install it ready-made, with brew install sdl3 sdl3_ttf. The CMakeLists.txt uses those whenever they're recent enough, and downloads its own copies when they aren't, so either way works.
That's the Mac ready. Skip ahead to Getting the Projects.
Setting Up Linux
On Linux, the package manager installs everything: the compiler, the debugger, CMake, FreeType, and the development files that SDL needs to open windows and play sound on your system. The commands here are for Ubuntu and Debian, and for Fedora. SDL lists the packages for other distributions, such as Arch and openSUSE, at https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md.
- Open a terminal, and install the tools and libraries. On Ubuntu or Debian, that's this one long command, which you can paste in as it is:
sudo apt install build-essential gdb git cmake ninja-build pkg-config \
libfreetype-dev libasound2-dev libpulse-dev libaudio-dev libjack-dev \
libsndio-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev \
libxfixes-dev libxi-dev libxss-dev libxtst-dev libxkbcommon-dev \
libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev \
libfribidi-dev libthai-dev libpipewire-0.3-dev libwayland-dev \
libdecor-0-dev liburing-dev
On Fedora, it's this one:
sudo dnf install gcc-c++ gdb git-core make cmake ninja-build freetype-devel \
alsa-lib-devel fribidi-devel pulseaudio-libs-devel pipewire-devel \
libX11-devel libXext-devel libXrandr-devel libXcursor-devel \
libXfixes-devel libXi-devel libXScrnSaver-devel libXtst-devel \
dbus-devel ibus-devel systemd-devel mesa-libGL-devel libxkbcommon-devel \
mesa-libGLES-devel mesa-libEGL-devel vulkan-devel wayland-devel \
wayland-protocols-devel libdrm-devel mesa-libgbm-devel libusb1-devel \
libdecor-devel pipewire-jack-audio-connection-kit-devel libthai-devel \
liburing-devel zlib-ng-compat-static
Most of those packages are SDL's: they let it find your windowing system, whether it's X11 or Wayland, and your sound system, when it's built. The rest are the compiler (build-essential or gcc-c++), the debugger (gdb), CMake, and FreeType, for SDL_ttf.
- Check CMake's version, which needs to be 3.24 or later:
cmake --version
Ubuntu 22.04's CMake is older than that. If yours is, swap it for a newer one: run sudo apt remove cmake, and then sudo snap install cmake --classic. Close the terminal, and open a new one before checking again. The old one has to go first, because Ubuntu looks for commands in the snap's folder last.
- Download VS Code from https://code.visualstudio.com, choosing the
.debpackage for Ubuntu or Debian, or the.rpmfor Fedora, and open it to install it. Start VS Code, click the Extensions icon on the left, the one made of four squares, search for C/C++ Extension Pack, and install the one published by Microsoft. It brings the C/C++ extension, for editing and debugging, and CMake Tools, for building.
That's Linux ready.
Getting the Projects
The book's repository is at https://github.com/EliteIntegrity/Using-C-to-Build-a-Traditional-Roguelike-2nd-Edition. Choose Code > Download ZIP, and extract the zip anywhere you like. Inside, there's a folder for each chapter, from Chapter 01 to Chapter 27, and the CMakeLists.txt file. The Windows copies of SDL are there too, and a Mac or Linux build ignores them.
If you're comfortable with Git, you can clone the repository instead, which makes it easy to fetch any fixes later.
The CMakeLists.txt File
The CMakeLists.txt file is in the repository, so you don't have to type it, but it's worth reading once. It's short, and it's the only thing standing between the game's code and your system. It starts by saying what it's for, and what it needs:
# Builds every chapter's project in this folder with CMake, on macOS, Linux,
# or Windows. Appendix B of the book, For Mac and Linux Users, explains it.
#
# Every folder here with .cpp files in its src folder becomes a program
# called AmuletsOfSDL, built into that folder, beside its data and assets,
# so it runs as it does in Visual Studio. A folder of your own works the
# same way: make it, put your .cpp and .h files in its src folder, and
# configure again.
cmake_minimum_required(VERSION 3.24)
project(AmuletsOfSDL LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Debug)
endif()
In the preceding code, the set lines ask for C++20, the same standard as Chapter 1's project. The if asks for a Debug build, the kind that's easiest to investigate, unless you choose another. The next part matters only on Windows, and switches off the parts of SDL and SDL_ttf that the game never uses:
# On Windows, use the copies of SDL that sit beside the projects
if(WIN32)
list(APPEND CMAKE_PREFIX_PATH
"${CMAKE_CURRENT_SOURCE_DIR}/SDL3"
"${CMAKE_CURRENT_SOURCE_DIR}/SDL3_ttf")
endif()
# Only what the game needs: no SDL tests, and none of SDL_ttf's extras
set(SDL_TEST_LIBRARY OFF CACHE BOOL "" FORCE)
set(SDLTTF_HARFBUZZ OFF CACHE BOOL "" FORCE)
set(SDLTTF_PLUTOSVG OFF CACHE BOOL "" FORCE)
set(SDLTTF_SAMPLES OFF CACHE BOOL "" FORCE)
In the preceding code, the if(WIN32) part points CMake at the copies of SDL that come with the repository, and on a Mac or on Linux, it's skipped. The set lines switch off SDL's own test library, and SDL_ttf's text shaping and color emoji, which saves a good deal of building. Then comes SDL itself:
# SDL and SDL_ttf: if they're installed already, in new enough versions,
# CMake uses them, and if not, it downloads and builds them, the first time
# only
string(CONCAT sdl_url "https://github.com/libsdl-org/SDL/releases/download/"
"release-3.4.4/SDL3-3.4.4.tar.gz")
string(CONCAT ttf_url "https://github.com/libsdl-org/SDL_ttf/releases/download/"
"release-3.2.2/SDL3_ttf-3.2.2.tar.gz")
include(FetchContent)
FetchContent_Declare(SDL3
URL ${sdl_url}
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
FIND_PACKAGE_ARGS 3.4 CONFIG)
FetchContent_Declare(SDL3_ttf
URL ${ttf_url}
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
FIND_PACKAGE_ARGS 3.2 CONFIG)
FetchContent_MakeAvailable(SDL3 SDL3_ttf)
In the preceding code, the two string(CONCAT ...) lines make the addresses of the releases the book was written with, each from two halves, so that neither line is too long to read. Each FetchContent_Declare names a library, and says where to download its source code from. The words FIND_PACKAGE_ARGS ask CMake to look for the library on your system first, in at least the version given, and only download it if it isn't there. Then FetchContent_MakeAvailable does whichever is needed, for both.
The last part is what makes the file work for every chapter:
# One program for each folder with .cpp files in its src folder
file(GLOB folders LIST_DIRECTORIES true RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}/*")
foreach(folder IN LISTS folders)
set(dir "${CMAKE_CURRENT_SOURCE_DIR}/${folder}")
if(NOT IS_DIRECTORY "${dir}")
continue()
endif()
file(GLOB sources CONFIGURE_DEPENDS "${dir}/src/*.cpp")
if(NOT sources)
continue()
endif()
file(GLOB headers CONFIGURE_DEPENDS "${dir}/src/*.h")
# A target's name can't have spaces, so "Chapter 01" is Chapter_01
string(REGEX REPLACE "[^A-Za-z0-9_.+-]" "_" target "${folder}")
add_executable(${target} ${sources} ${headers})
target_link_libraries(${target} PRIVATE SDL3_ttf::SDL3_ttf SDL3::SDL3)
set_target_properties(${target} PROPERTIES
OUTPUT_NAME AmuletsOfSDL
RUNTIME_OUTPUT_DIRECTORY "${dir}"
RUNTIME_OUTPUT_DIRECTORY_DEBUG "${dir}"
RUNTIME_OUTPUT_DIRECTORY_RELEASE "${dir}")
endforeach()
In the preceding code, the loop looks at every folder beside the file, and each one with .cpp files in its src folder becomes a program, built from all of them. CMake's name for each program is the folder's name, with an underscore where the space was, so Chapter 05 gives a program that CMake calls Chapter_05. The program's own file, though, is always called AmuletsOfSDL, as on Windows. It's built into its chapter's folder, beside the data and assets folders.
The words CONFIGURE_DEPENDS make CMake look for new files at every build, so a file you add to src is built without any more fuss. The folders that hold SDL have no src folder, so they're skipped.
Building, Running and Debugging
The first time, building a chapter's game takes four steps, and after that, one:
- Start VS Code, and open the repository's folder itself, the one with
CMakeLists.txtin it, with File > Open Folder. If VS Code asks whether you trust the authors of the files in the folder, choose to trust them, since this is the book's code. - CMake Tools notices the
CMakeLists.txtfile, and asks which kit to use, which means which compiler. On a Mac, choose the one that starts with Clang, and on Linux, the one that starts with GCC. If no question appears, press Cmd+Shift+P on a Mac, or Ctrl+Shift+P on Linux, for the Command Palette, and run CMake: Select a Kit from there. - CMake Tools then configures the project: it reads
CMakeLists.txt. The first time, unless SDL is installed already, it also downloads SDL and SDL_ttf, about 17 MB in all. Watch the Output panel at the bottom of the window. It's done when the last lines say "Build files have been written to" a folder calledbuild. - Open the Command Palette, run CMake: Set Build Target, and choose the chapter you want, such as
Chapter_05. Then run CMake: Build. The first build takes a few minutes, because SDL itself is being built, and later builds only rebuild what you've changed.
To run the game, use a terminal in the chapter's own folder. In VS Code, choose Terminal > New Terminal, and type this, for Chapter 5:
cd "Chapter 05"
./AmuletsOfSDL
The quotes are there because the folder's name has a space in it. Starting the game from its own folder matters until Chapter 16. Until then, the game finds its font and its tiles by paths measured from the folder it's started in. Chapter 16 makes it find every file from its own folder instead, wherever it's started from. The game's messages, which the console window shows on Windows, appear in the terminal.
A seed, or anything else the book types into Command Arguments, goes after the program's name, with a space between:
./AmuletsOfSDL 42
To debug, VS Code needs to know how to start the game: which program, from which folder, and with which arguments. Choose Run > Add Configuration, and if it offers a choice of debuggers, choose C++ (GDB/LLDB). It makes a file called launch.json, in a folder called .vscode. Replace everything in it with this, and save it:
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug the chapter",
"type": "cppdbg",
"request": "launch",
"program": "${command:cmake.launchTargetPath}",
"args": [],
"cwd": "${command:cmake.getLaunchTargetDirectory}",
"osx": { "MIMode": "lldb" },
"linux": { "MIMode": "gdb" }
}
]
}
In the preceding code, the two ${command:...} values are filled in by CMake Tools: the program of the chapter you've chosen, and the folder it was built in, which is its chapter's folder. Choose the chapter with CMake: Set Launch/Debug Target, then press F5, and the game starts in the debugger. A seed goes in the brackets after args, in quotes, as "args": ["42"].
On a Mac, the first time you debug, macOS may ask for your password so that the debugger can take control of the program. That's normal: it's the permission that every debugger on a Mac needs.
The debugger works just like Visual Studio's, with the same keys. Click in the margin beside a line's number, or press F9, to set a breakpoint. When the game stops on it, the Variables view on the left shows every variable, as Visual Studio's Locals and Autos windows do. F10 steps over a line, F11 steps into a function, and F5 carries on.
Where the Game Keeps Its Files
From Chapter 17 on, the game keeps its save, its settings, its morgue files and its high scores in a folder of its own, which SDL_GetPrefPath finds. On Windows, that's in %APPDATA%\GameCodeSchool\AmuletsOfSDL. A Mac keeps it in ~/Library/Application Support/GameCodeSchool/AmuletsOfSDL, and Linux in ~/.local/share/GameCodeSchool/AmuletsOfSDL. The ~ means your home folder, and Chapter 27's bot keeps its own folder, AmuletsOfSDL-bot, beside the game's.
Where a chapter opens the folder in File Explorer, open it in Finder on a Mac, with Go > Go to Folder, or Shift+Cmd+G, and the path above. On Linux, most file managers take a typed path after Ctrl+L. Where a chapter opens a file in Notepad, TextEdit on a Mac, any text editor on Linux, or VS Code itself does just as well.
Names Must Match Exactly
Windows doesn't care whether you write Player.h or player.h: it finds the same file either way. Linux does care, and treats them as two different names, so an #include "player.h" that works on Windows stops the build on Linux, when the file is called Player.h. Most Macs don't care either, until code written on one moves to Linux.
Every name in the book's code matches its file exactly, letter for letter, and the same goes for the names of the files in each data and assets folder. Keep to that as you type, and the game you build on one system builds on all three.
A Project of Your Own
The book has you type the game into a project of your own, and any folder with a src folder of .cpp files in it becomes a program. So your project is a folder beside the chapters' folders:
- In VS Code's Explorer, right-click the empty space below the folders, choose New Folder, and give it a name, such as
My Game. Right-click the new folder, choose New Folder again, and call itsrc. - Wherever a chapter adds a file to
src, right-click yoursrcfolder, choose New File, and give it the chapter's name, capitals and all. - Wherever a chapter copies a folder or a file from the book's repository, copy it into your own folder, in the same place as in the chapter's folder. The font in Chapter 1 is one, and the data files' folder in Chapter 16 is another.
The first time, open the Command Palette and run CMake: Configure, so that CMake finds your folder, and then choose My_Game with CMake: Set Build Target and CMake: Set Launch/Debug Target. After that, your project builds and runs just as the chapters' projects do.
Where the Book's Windows Steps Differ
Most of the book reads exactly the same on a Mac or on Linux, but the steps that belong to Visual Studio or to Windows have their own equivalents:
- Chapter 1's setup. Downloading SDL and SDL3_ttf, the project's settings, and copying the DLLs are all the
CMakeLists.txtfile's job. There's no DLL to copy on a Mac or on Linux: the build tells the game where SDL's libraries are. - Adding a file. Where a chapter adds a file with Add > New Item in Solution Explorer, add it to your
srcfolder in VS Code's Explorer, as in A Project of Your Own. - F5 and Ctrl+F5. Running the game is
./AmuletsOfSDLin a terminal, in the chapter's folder. Debugging it is F5, with thelaunch.jsonfile from Building, Running and Debugging. - Command Arguments. A seed, from Chapter 2 on, and Chapter 27's
--botand--hits, go after the program's name in the terminal, as in./AmuletsOfSDL --bot 5. For the debugger, they go inlaunch.json'sargs, as in"args": ["--bot", "5"]. - Compiling one file. Where a checkpoint compiles one file with Ctrl+F7, run CMake: Compile Active File from the Command Palette instead, with that file open.
- Release builds. Where Chapter 27 changes Debug to Release, run CMake: Select Variant, choose Release, and build again. Choose Debug again afterward.
- Task Manager. Where Chapter 1 watches the game's CPU in Task Manager, use Activity Monitor, in Applications > Utilities, on a Mac, or System Monitor on Linux.
- Starting the game from File Explorer. Where Chapter 16 starts the game by double-clicking it, run it from a terminal in another folder instead, by its full path. On a Mac, a double-click on
AmuletsOfSDLin Finder works too: it runs the game in a Terminal window, from your home folder, and Chapter 16 is what lets it find its files from there. - Seeds. A seed makes a different dungeon on a Mac or on Linux, as the start of this appendix explains. So the checkpoints' directions won't find what they describe, and Chapter 27's bot reports different numbers, though the game and the bot work exactly as the chapters say.
- Function keys. On a Mac keyboard, the function keys usually do something else, such as dim the screen. That includes F2, which switches between letters and tiles, and the debugging aids on F1, F3, F4, F6 and F7. Hold fn and press them, and the game gets them.
- Alt+Enter. On a Mac, the key SDL calls Alt is Option, so full screen is Option+Return.
- No numeric keypad. The vi keys, h, j, k, l, y, u, b and n, move in all eight directions. The period waits a turn, so a keyboard without a keypad plays the whole game.
- Error messages. The book quotes Visual Studio's errors, such as C2065 and LNK2019. Clang and GCC report the same mistakes in their own words: C2065, an undeclared identifier, is "use of undeclared identifier" from Clang, and "was not declared in this scope" from GCC; LNK2019, an unresolved external symbol, is "Undefined symbols" on a Mac, and "undefined reference to" on Linux. The explanation in each Common Errors section still applies, so search for what a message is about, rather than its number.
- DLLs. The Common Errors about a missing DLL, such as Chapter 1's for
SDL3_ttf.dll, are Windows' alone.
Everything else in the chapters, the code above all, is the same on all three systems.
When Something Goes Wrong
CMake says it needs version 3.24 or later. Your CMake is too old. Install a newer one, as in Setting Up a Mac or Setting Up Linux, and configure again.
Configuring stops with "Could NOT find Freetype". SDL_ttf needs FreeType to read fonts, and it isn't installed. Run brew install freetype on a Mac, sudo apt install libfreetype-dev on Ubuntu or Debian, or sudo dnf install freetype-devel on Fedora, then run CMake: Delete Cache and Reconfigure.
On Linux, configuring stops because SDL can't find X11 or Wayland, or the game opens no window, or plays no sound. SDL was built without the packages it needs for your windowing system, or your sound system. Install the whole list from Setting Up Linux, then run CMake: Delete Cache and Reconfigure, so that SDL is built again with them.
Configuring fails while downloading. The first configure needs an internet connection, to download SDL. Once it has succeeded, the downloads are kept in the build folder, and it doesn't need the internet again, unless you delete that folder.
The window opens and closes at once, and the terminal says the font couldn't be opened. Before Chapter 16, the game finds its files from the folder it's started in. Start it from a terminal in its own chapter's folder, as in Building, Running and Debugging.
The build can't find a header, such as SDL3_ttf/SDL_ttf.h. The configure step didn't finish. Read the Output panel from the top, fix the first problem it reports, and configure again.
Everything was working, and now it isn't. Run CMake: Delete Cache and Reconfigure. It starts CMake's bookkeeping afresh, which cures most of the strange problems that come from moving folders around or changing tools.
With that, you're set up the way the rest of the book assumes: a project open, a game running, and a debugger ready when you need it. Every chapter, from the first window of glyphs to the bot that plays the finished game, is yours to build, on whichever computer you have.
