Project setup
Choose how your game obtains Cheryl before writing main(). During
development, adding a source checkout to your game’s CMake project is sufficient:
building the game also builds the libraries it uses. A development SDK is a
directory containing compiled libraries, public headers and CMake package files;
use it when you want to link already compiled Cheryl libraries. Both paths
provide the same public CMake names, such as Cheryl::Cheryl, for
target_link_libraries(), and the same cheryl/ headers.
flowchart LR
accTitle: Two ways to obtain Cheryl targets
accDescr: Adding a source checkout or finding an installed SDK supplies Cheryl's public CMake targets. The game links those targets in either case.
source["Source checkout"] -->|add_subdirectory| targets["Cheryl targets"]
sdk["Installed SDK"] -->|find_package| targets
targets -->|target_link_libraries| game["Your game"]
After setup, continue with Your first game. It introduces startup, the game hooks and resource ownership before putting a sprite and text on screen. The consumption reference covers other library selections and the full SDK requirements.
Dependencies
Use CMake 3.28 or newer, Ninja, and a C++23 compiler and standard library with
std::format support. Install the
system dependencies required by
your selected modules. The first game uses FreeType, HarfBuzz and ICU for text,
plus Cheryl::NativeGLFW for its window/input and Cheryl::OpenGL for rendering.
It needs a desktop graphics driver supporting an OpenGL 3.3 core context.
For source builds, initialize the checkout’s recorded recursive submodules and
install shared development packages or prepare a dependency prefix.
Windows requires version 10 1903 or later and a Windows SDK with icu.h/icu.lib;
it uses the operating system’s ICU runtime.
Python
and Jinja2 are needed when GLAD generates OpenGL bindings. The first game supplies
its own sprite image and assets/graphics/graphics-manifests.json, an index
selecting its graphics definitions. Its default material shaders are embedded
in the OpenGL library. The embedded fallback font comes from
the engine checkout’s assets/ submodule. No optional artwork download is needed.
For an SDK, install its consumer prerequisites instead of rebuilding Cheryl. Some native development/runtime libraries remain external on Linux. Shared native dependencies keep their linkage with either shared or static Cheryl. SDKs provide their owned toolkit runtimes and Windows external DLLs; static Cheryl SDKs also retain the embedded archive closure. The host’s graphics/system runtime and matching C++ runtime remain requirements.
Build your game with a source checkout
A simple layout keeps your game independent of the engine checkout:
projects/
├── cheryl-engine/
└── my-game/
├── CMakeLists.txt
├── src/
│ ├── main.cpp
│ ├── first-game.h
│ └── first-game.cpp
└── assets/
Clone Cheryl at a revision matching the manual you are reading: main for stable,
develop for latest, or the matching release tag. Replace /path/to/projects with
your chosen parent directory. This block preserves your shell’s starting directory:
(
set -e
cd /path/to/projects
git clone --branch main https://github.com/cppcooper/cheryl-engine.git
cd cheryl-engine
git submodule update --init --recursive
)
Copy the maintained first game’s src/ and
assets/ directories into my-game/ to use its code unchanged. Create
my-game/CMakeLists.txt as follows. The CHERYL_BUILD_* options select the first
game’s Native GLFW/OpenGL libraries and omit unrelated applications and integrations.
block(SCOPE_FOR VARIABLES) limits those settings to the enclosed Cheryl setup;
it does not replace saved command-line/IDE options in CMakeCache.txt.
cmake_minimum_required(VERSION 3.28)
project(my_game LANGUAGES CXX)
set(CHERYL_ENGINE_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/../cheryl-engine"
CACHE PATH "Cheryl Engine source checkout")
block(SCOPE_FOR VARIABLES)
set(CHERYL_BUILD_NATIVE_GLFW ON)
set(CHERYL_BUILD_OPENGL ON)
set(CHERYL_BUILD_STARTUP ON)
set(CHERYL_STARTUP_OPENGL ON)
set(CHERYL_BUILD_WORKERS OFF)
set(CHERYL_NATIVE_INPUT ON)
set(CHERYL_NATIVE_NULL_PLATFORM OFF)
set(CHERYL_BUILD_TESTS OFF)
set(CHERYL_BUILD_CONSUMER_TESTS OFF)
set(CHERYL_BUILD_DEMO OFF)
set(CHERYL_BUILD_FIRST_GAME OFF)
set(CHERYL_BUILD_TUTORIAL_GAME OFF)
set(CHERYL_BUILD_DOCS OFF)
set(CHERYL_BUILD_SDK OFF)
set(CHERYL_BUILD_DEBUG_TERMINAL_LINUX OFF)
set(CHERYL_BUILD_UI_TGUI OFF)
set(CHERYL_BUILD_UI_RMLUI OFF)
set(CHERYL_BUILD_AUDIO_MINIAUDIO OFF)
set(CHERYL_BUILD_WORKER_TOPOLOGY_HWLOC OFF)
set(CHERYL_BUILD_WORKER_TOPOLOGY_JSON OFF)
add_subdirectory("${CHERYL_ENGINE_SOURCE}" cheryl EXCLUDE_FROM_ALL)
endblock()
add_executable(my_game src/main.cpp src/first-game.cpp)
target_link_libraries(my_game PRIVATE Cheryl::Cheryl)
target_compile_definitions(my_game PRIVATE
CHERYL_FIRST_GAME_ASSETS="${CMAKE_CURRENT_SOURCE_DIR}/assets")
add_subdirectory() reads the engine checkout’s CMake project and places its
build files under the game’s cheryl/ build subdirectory. add_executable()
creates the executable target named my_game; target_link_libraries() attaches
the selected Cheryl libraries and their compiler settings to it.
The scoped set() values fix this template’s module selection; edit them
when adding a module. A same-name -D cache option does not override those local
values.
CHERYL_FIRST_GAME_ASSETS supplies the example’s default asset-root string, so
launching from an IDE or another directory still finds your game’s files. As you
replace the example with your own game, keep that explicit connection between
the executable target and the asset path read by main().
Cheryl::Cheryl is an interface target: it links Engine and the selected
module/support libraries and supplies their include directories and preprocessor
definitions. It produces no combined library of its own. Your sources can use
#include <cheryl/cheryl.h>: this aggregate header includes Engine and the public
module/support headers selected by those definitions. For example, linking
Cheryl::OpenGL supplies CHERYL_HAS_OPENGL=1, which enables
<cheryl/modules/opengl.h> inside the aggregate header.
A module option such as CHERYL_BUILD_OPENGL makes Cheryl::OpenGL available;
linking its target supplies that library to your game. Cheryl::Cheryl links the
configured set. Reload CMake in the IDE after changing selections.
Configure and build from the game directory. Replace
/path/to/projects/my-game with its location:
(
set -e
cd /path/to/projects/my-game
cmake -S . -B build/release -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DGLFW_BUILD_WAYLAND=OFF -DGAINPUT_ENABLE_HID=OFF
cmake --build build/release --target my_game --parallel
)
cmake -S . -B build/release configures the build. CMAKE_BUILD_TYPE=Release
selects the optimization/debug/logging configuration; module options such as
CHERYL_BUILD_OPENGL select libraries. cmake --build ... --target my_game
then compiles that executable and the libraries it links.
These commands use Linux shared development packages. For Windows, prepare
dependencies in the sibling Cheryl checkout with
python tools/dependencies/prepare.py --native --without-hwloc. Configure the game
with the printed toolchain and installed prefix, VCPKG_TARGET_TRIPLET=x64-windows,
the manifest/project-include settings in the
build reference, and
-DCMAKE_MSVC_RUNTIME_LIBRARY='MultiThreaded$<$<CONFIG:Debug>:Debug>DLL'.
The optional prepared Linux prefix uses x64-linux-dynamic.
The policy setting accommodates pinned legacy dependencies on CMake 4 hosts.
The GLFW setting chooses X11 on Linux; the Gainput setting avoids the optional
HID backend and its dependency download. Use the
build reference
for other platform choices. No separate engine build or SDK installation is
required. To run the maintained example before writing your own entry point,
follow First game: setup.
On Windows, complete the shared-library runtime setup before launching the source-built game.
Run the copied game
After building my_game, launch it from your game project:
(
set -e
cd /path/to/projects/my-game
./build/release/my_game
)
On Windows use build/release/my_game.exe after the runtime setup above. Expect
a 640 × 360 window with a cyan sprite and Score: 0. Left/right arrows move the
sprite, Space selects its amber cell, and Escape closes the window. The score
is deliberately static in this first example. Resizing should keep the actor
within the framebuffer and the score near the upper-left. Run again with
--concurrent to use a separate simulation thread.
The compiled asset-root definition locates your copied image and manifests
regardless of the process’s working directory. An explicit --assets override
uses the path you supply. Continue with Your first game to
understand and extend the code you have just run. The same launch checkpoint
applies after the installed-SDK build below.
Choose smaller target sets when needed
Link Cheryl::Cheryl for all selected libraries, or choose individual public
targets for fewer dependencies:
Link target |
What the game obtains |
|---|---|
|
Engine and the configured module/support libraries, including the Linux Debug terminal when selected in a source build. |
|
Standard |
|
Neutral Engine interfaces and implementation, without selecting a window or graphics implementation. |
|
Selected audio integration; add it when your game needs sound. |
|
The selected UI integration. |
For example, replace the Cheryl::Cheryl link with
target_link_libraries(my_game PRIVATE Cheryl::Startup) for the native
startup libraries alone. In source builds, names such as Cheryl::Engine are
aliases for concrete build targets: link Cheryl::Engine, but use
cmake --build ... --target cengine to build its library directly. SDKs expose
the same public names as imported targets referring to existing libraries. The
target reference maps the other public and build names.
<cheryl/cheryl.h> includes only the modules supplied by linked targets, so a
narrower link can make a feature’s conditional include inactive even when its
build option is enabled.
Use an installed SDK instead
Choose an SDK providing Cheryl::Startup and Native GLFW with native input
for the first game. Its package must match your OS, CPU architecture,
compiler/standard-library ABI (the binary conventions needed to link C++ code)
and build configuration, such as Release. With an extracted SDK, replace the
source-checkout block(...) through endblock() in the game CMake file with:
find_package(Cheryl 4 CONFIG REQUIRED)
find_package() loads the SDK’s CherylConfig.cmake, which provides its public
targets and dependency settings. Keep add_executable, target_link_libraries
and your asset-root definition. The SDK prefix is the extracted root directory
containing include/, libraries and CMake package files. Set CMAKE_PREFIX_PATH
to that directory so find_package() can locate it; replace both paths below:
(
set -e
cd /path/to/projects/my-game
cmake -S . -B build/release -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/absolute/path/to/extracted-sdk
cmake --build build/release --target my_game --parallel
)
This builds your game, using the libraries already in the SDK. Keep the SDK’s headers, libraries, CMake files and dependencies together. On Windows, make the selected Cheryl DLLs available to the process and use a matching MSVC runtime; see the SDK consumption contract. The Linux Debug terminal currently requires source composition and is not exported in SDKs.
Build the maintained example independently
The first game’s own projects/apps/first-game/CMakeLists.txt also works outside
the engine’s top-level build, without copying files or writing another CMake
project. CHERYL_FIRST_GAME_ENGINE_SOURCE selects an engine checkout for that
project. From anywhere inside the checkout, configure against engine source:
(
set -e
cd "$(git rev-parse --show-toplevel)"
cmake -S projects/apps/first-game -B build/first-game-source -G Ninja \
-DCHERYL_BUILD_WORKERS=OFF \
-DCMAKE_BUILD_TYPE=Release -DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
-DCHERYL_FIRST_GAME_ENGINE_SOURCE="$PWD" \
-DGLFW_BUILD_WAYLAND=OFF -DGAINPUT_ENABLE_HID=OFF
cmake --build build/first-game-source --target first-game --parallel
./build/first-game-source/first-game
)
Alternatively, leave CHERYL_FIRST_GAME_ENGINE_SOURCE empty to use
find_package(Cheryl) and select a compatible SDK containing
Cheryl::Startup and Native GLFW with native input:
(
set -e
cd "$(git rev-parse --show-toplevel)"
cmake -S projects/apps/first-game -B build/first-game-sdk -G Ninja \
-DCMAKE_BUILD_TYPE=Release -DCHERYL_FIRST_GAME_ENGINE_SOURCE= \
-DCMAKE_PREFIX_PATH=/absolute/path/to/extracted-sdk
cmake --build build/first-game-sdk --target first-game --parallel
./build/first-game-sdk/first-game
)
The example’s compiled asset path points to its source assets directory. Use
--assets when relocating those files with a packaged game. Windows executables
have an .exe suffix.
Produce engine artifacts
The SDK is optional for source consumers. To produce a file or directory for others, choose its build, install or packaging operation:
Need |
Operation |
Result |
|---|---|---|
Run the introductory walkthrough |
Select |
The small sprite/text game and its linked libraries. |
Run the Controller/Character/HUD example |
Select |
Includes player join/leave, patrol and the TGUI HUD. The RmlUi document guide is a separate extension. |
Build a library directly |
Build |
The selected library and dependencies in the build tree. |
Build selected SDK libraries |
Select |
Compiled installable libraries; headers have not yet been collected. |
Collect libraries and headers |
After that build, use |
One SDK directory with headers, libraries, CMake package files and licenses. |
Create a distributable SDK archive |
Run |
Archive, |
Build the website and API reference |
Run |
Generated HTML, without compiling Engine. |
Use the artifact commands for exact configuration, build, install and packaging blocks.
Keep headers and binaries matched
A build’s module selections determine which libraries and dependencies exist.
CMAKE_BUILD_TYPE also affects compiled logging and Debug instrumentation. Keep
separate build directories and installed SDK prefixes for different configurations
and module selections. Compile each game .cpp file against the headers and
target settings that belong to those libraries. For a packaged SDK, check its
SDK-MANIFEST.json for the producer’s source/submodule revisions, features,
toolchain, configuration, linkage and enabled component versions. Matching filenames
alone do not establish compatibility.
Cheryl defaults to shared Engine, modules and support libraries. Set
CHERYL_BUILD_SHARED_LIBS=OFF when configuring a source build or producing an
SDK to select static libraries, whose code is linked into the executable. The same
public targets and includes work with either selection; keep their build directories and SDK
prefixes separate. Shared native dependencies remain required with either Cheryl
linkage; shared Cheryl libraries also need to be available at runtime.
Follow the SDK runtime-path contract
and linkage reference for deployment
and versioned artifact names.