Building an application with CMake
Everything needed to start an application on shuffle_engine: a generator that creates a project from scratch, three ways to bring the framework in, and two CMake functions.
Create a project from scratch
Section titled “Create a project from scratch”cmake -D NAME=MyShow -D DIR=path/to/MyShow -P path/to/shuffle_engine/cmake/ShuffleEngineNewProject.cmakecd path/to/MyShowcmake --preset default # or: cmake --preset windowscmake --build --preset defaultOptions:
| Variable | Values | Default |
|---|---|---|
NAME |
a C++/CMake identifier | required |
DIR |
a new or empty folder | required |
BACKEND |
core (plain C++20), juce (JUCE 9 app), tracktion (JUCE 9 + Tracktion Engine) |
core |
ENGINE_DIR |
a local shuffle_engine checkout to use instead of downloading | empty |
ENGINE_REF |
git tag, branch or commit to download | main |
The generated project contains CMakeLists.txt, CMakePresets.json,
src/main.cpp (a small working demo), README.md and .gitignore. These
files are CC0: they belong to you. The framework itself stays under its own
licence (Apache-2.0).
After cmake --install, the same generator is available inside the installed
package: <prefix>/lib/cmake/ShuffleEngine/ShuffleEngineNewProject.cmake.
Three ways to bring shuffle_engine in
Section titled “Three ways to bring shuffle_engine in”The generated CMakeLists.txt tries them in this order.
flowchart LR
a{"SHUFFLE_ENGINE_DIR set?"} -- yes --> s["add_subdirectory<br/>(local checkout)"]
a -- no --> f{"find_package<br/>(ShuffleEngine)?"}
f -- found --> p["installed package"]
f -- not found --> g["FetchContent<br/>from GitHub at SHUFFLE_ENGINE_REF"]
- Local checkout:
add_subdirectory (<path> shuffle_engine). Best while developing the framework and the app together. - Installed package: build shuffle_engine, then
cmake --install <build> --prefix <dir>; in the app,find_package (ShuffleEngine CONFIG REQUIRED [COMPONENTS timecode ...])withCMAKE_PREFIX_PATH=<dir>. - Download:
FetchContent_Declare (shuffle_engine GIT_REPOSITORY ... GIT_TAG ...)thenFetchContent_MakeAvailable (shuffle_engine).
Used as a subproject, shuffle_engine builds only its libraries: tests, examples, install rules and the adapters that download libraries (codecs, plugin hosting, libremidi) are switched off unless it is the top-level project.
Inside a JUCE project
Section titled “Inside a JUCE project”A project that already has JUCE adds shuffle_engine after it. When
juce::juce_core exists at that point, JUCE already gives the platform, the
sockets and the audio devices, so the three JUCE-free adapters that are
otherwise on by default, platform, net_sockets and miniaudio, default
to OFF: nothing is downloaded or built for them. To have one anyway (to move
a port away from JUCE, for example), turn it on before adding the engine:
add_subdirectory (JUCE) # the project's own JUCE 9set (SHUFFLE_ENGINE_WITH_MINIAUDIO ON CACHE BOOL "") # only if you want itadd_subdirectory (../shuffle_engine shuffle_engine)SHUFFLE_ENGINE_WITH_NET_SOCKETS also builds net_websocket (the UI
bridge over WebSocket and HTTP): a JUCE app that serves its web interface
to browsers turns it on. Projects without JUCE, satellites included, keep
all three on as before.
shuffle_engine_find_juce() (called by shuffle_juce and by
shuffle_engine_add_app with a JUCE backend) uses the project’s JUCE and
checks its version once per configure, however many modules call it:
anything before JUCE 9 stops configure with the version found and how to
fix it.
The functions
Section titled “The functions”shuffle_engine_add_app
Section titled “shuffle_engine_add_app”shuffle_engine_add_app (MyShow BACKEND tracktion # core | juce | tracktion (default: core) GUI # windowed app; juce/tracktion only SOURCES src/main.cpp src/MainWindow.cpp USES timecode # shuffle_engine modules PRODUCT_NAME "My Show" # optional COMPANY_NAME "My Band" # optional VERSION 1.0.0) # optional, defaults to the project versioncore: a plain C++20 executable. No JUCE, no Tracktion: builds anywhere a C++20 compiler does.juce: a JUCE 9 console app, or a GUI app withGUI. JUCE is found throughJUCE_HOME(CMake or environment variable) or downloaded at the pinned version.tracktion: likejuce, plus Tracktion Engine throughTRACKTION_HOMEor a download at the pinned commit.
Backend apps get sensible defaults (no web browser, no curl, no splash screen,
no modal loops). Add further JUCE modules with target_link_libraries.
BACKEND juce and BACKEND tracktion give the application JUCE (and
Tracktion Engine); shuffle_engine itself builds no JUCE code. The framework’s
JUCE and Tracktion adapter modules (juce_platform, juce_midi,
juce_audio, juce_plugins, juce_webui, te_devices, te_engine) come
from the shuffle_juce
satellite (satellites.md). Add it after shuffle_engine, then
name its modules in USES like any other:
add_subdirectory (../shuffle_engine shuffle_engine) # or FetchContent / find_packageadd_subdirectory (../shuffle_juce shuffle_juce) # or FetchContent_Declare (shuffle_juce GIT_REPOSITORY https://github.com/ShuffleFramework/shuffle_juce.git ...)
shuffle_engine_add_app (MyShow BACKEND juce SOURCES src/main.cpp USES setlist engine juce_platform juce_audio)shuffle_juce finds the shuffle_engine already added by the parent project,
so both use the same build. An app that USES juce_webui is built with the
JUCE web browser component (WebKitGTK on Linux, WebView2 on Windows when
shuffle_engine_find_webview2 finds its SDK). The AI task modules
(ai_tasks, ai_audiocpp) come from
shuffle_ai the same way.
shuffle_engine_use
Section titled “shuffle_engine_use”add_executable (Tool tool.cpp)shuffle_engine_use (Tool timecode)Links modules to a target you created yourself. An unknown module name stops the configure step with the list of where modules live.
Other public helpers
Section titled “Other public helpers”cmake/ShuffleEngineApp.cmake and cmake/ShuffleEngineDeps.cmake are
public: they are installed with the package and available after
add_subdirectory, FetchContent or find_package. Besides the two
functions above they offer what satellites and larger builds need:
| Function | What it does |
|---|---|
shuffle_engine_apply_warnings (<target>) |
the framework’s warning flags (/W4 /permissive- on MSVC, -Wall -Wextra -Wpedantic -Wshadow -Wconversion elsewhere), then shuffle_engine_apply_rt_checks |
shuffle_engine_apply_rt_checks (<target>) |
with SHUFFLE_ENGINE_RT_CHECKS=ON and Clang 20 or later (not clang-cl), makes the compiler’s checks of SHUFFLE_RT functions errors; nothing otherwise |
shuffle_engine_find_juce() |
the project’s own JUCE when juce::juce_core already exists, otherwise JUCE 9 from JUCE_HOME (CMake or environment variable) or a download at the pinned version; either way a version before 9 stops configure with the version found and the fix |
shuffle_engine_find_tracktion() |
Tracktion Engine from TRACKTION_HOME or a download at the pinned commit |
shuffle_engine_find_webview2 (<out>) |
TRUE in <out> on Windows when the WebView2 SDK package is where JUCE looks for it |
shuffle_engine_fetch_catch2() |
Catch2 at the pinned version, with its CMake scripts on the caller’s module path (include (Catch), catch_discover_tests) |
shuffle_engine_fetch_codecs(), _fetch_miniaudio(), _fetch_plugin_sdks(), _fetch_libremidi() |
the third-party libraries of the adapters, pinned and checked against their SHA-256; the engine calls them when the matching SHUFFLE_ENGINE_WITH_* option is on |
cmake/ShuffleEngine.cmake (shuffle_engine_add_core_library,
shuffle_engine_add_core_tests) builds the framework itself and is not
public (decision 0020).
Version variables
Section titled “Version variables”Whichever way the engine is brought in (add_subdirectory, FetchContent or
find_package), these are set as cache entries, so the whole build sees
them:
| Variable | Example |
|---|---|
SHUFFLE_ENGINE_VERSION |
0.1.0 |
SHUFFLE_ENGINE_VERSION_MAJOR, _MINOR, _PATCH |
0, 1, 0 |
SHUFFLE_ENGINE_VERSION_PRERELEASE |
empty on a release, dev, rc.1 |
SHUFFLE_ENGINE_VERSION_STRING |
0.1.0, 0.2.0-dev |
SHUFFLE_ENGINE_API_LEVEL |
1; grows with every minor or major version |
find_package (ShuffleEngine 0.1 CONFIG REQUIRED) also checks the version
(the same minor version before 1.0), and C++ code reads it from
shuffle/base/Version.h.
Build options
Section titled “Build options”The options an application or a satellite usually sets on shuffle_engine:
| Option | Default | What it does |
|---|---|---|
SHUFFLE_ENGINE_BUILD_TESTS |
ON at top level | builds the test runners |
SHUFFLE_ENGINE_BUILD_EXAMPLES |
ON at top level | builds and runs the examples |
SHUFFLE_ENGINE_BUILD_CONTRACTS |
as SHUFFLE_ENGINE_BUILD_TESTS |
builds the shuffle::<core>_contracts targets (the cores’ contract suites, header-only Catch2) without the engine’s tests, for adapters tested in another repository, such as a satellite (ports.md) |
SHUFFLE_ENGINE_INSTALL |
ON at top level | generates install rules (find_package support) |
SHUFFLE_ENGINE_WITH_PLATFORM, _WITH_NET_SOCKETS, _WITH_MINIAUDIO |
ON, except inside a project that already has JUCE (above); _WITH_NET_SOCKETS OFF on WebAssembly |
build the platform, sockets and audio device adapters that need no JUCE (choose backends) |
SHUFFLE_ENGINE_WITH_LIBREMIDI, _WITH_CODECS, _WITH_PLUGIN_HOST |
ON at top level (codecs not on WebAssembly, plugin hosting on desktops only) | build the adapters that download a library |
shuffle_engine_fetch_catch2() (in cmake/ShuffleEngineDeps.cmake, public)
brings Catch2 at the pinned version and puts its CMake scripts on the
caller’s module path, so a satellite’s test runner can
include (Catch) and call catch_discover_tests.
Pinned versions
Section titled “Pinned versions”| Dependency | Version | Override |
|---|---|---|
| JUCE | 9.0.3 | -DJUCE_HOME=<checkout> or environment JUCE_HOME |
| Tracktion Engine | develop at 5ee811e |
-DTRACKTION_HOME=<checkout> or environment TRACKTION_HOME |
The pins live in cmake/ShuffleEngineDeps.cmake and are found with
shuffle_engine_find_juce and shuffle_engine_find_tracktion; shuffle_juce
uses the same pins, so an application and the adapters always agree on the
JUCE and Tracktion versions.
Verified
Section titled “Verified”Three tests (ctest -L packaging) check this page end to end with the
build’s own compiler and flags:
packaging:new-projectbuilds a project generated from scratch against the checkout and runs it;packaging:subprojectconfigures two projects that add the checkout after a stand-in JUCE: JUCE 8 is refused with its version, JUCE 9 is accepted and the JUCE-free adapters are not added;packaging:installrunscmake --installinto an empty prefix, then configurescmake/install-test, an application that sees only that prefix:find_package (ShuffleEngine <version> CONFIG REQUIRED COMPONENTS <every built module>), the version variables, every helper function above, every example ofexamples/built withshuffle_engine_add_appagainst the imported targets, andshuffle_engine_fetch_catch2withinclude (Catch); it then runs the version check and an example.
The juce and tracktion backends have been built and run with JUCE 9.0.3
and Tracktion 5ee811e.
© 2026 Umberto Sorbo. The software is licensed under the Apache License, Version 2.0, and provided “as is”, without warranties or conditions of any kind; see the disclaimer.
SHUFFLE Framework and the SHUFFLE Framework logo are trademarks of Umberto Sorbo; the licence grants no rights to them (trademarks). Other names belong to their owners. Fonts: IBM Plex Sans and JetBrains Mono, SIL Open Font License 1.1.
Contact: shuffleframework@gmail.com · Instagram @shuffleframework. Security problems: write to the same address with “Security” in the subject, not in a public issue.