Tutorial 127: Choose Platform, Renderer, and Audio Independently
Core idea: this snapshot has four different axes — target operating system, host platform implementation, graphics renderer, and audio implementation — plus one switch that decides whether SDL is configured at all (CNA_ENABLE_SDL). “Backend” is too ambiguous to stand in for any of them.
The three CMake selections (and one switch)
| Variable | Implemented values | Default |
|---|---|---|
CNA_PLATFORM | SDL3, HEADLESS, TERMINAL — three, and TERMINAL is offered only off Windows | SDL3 on every OS |
CNA_GRAPHICS_RENDERER | One of 14 public identities | OS-dependent: Emscripten WEBGL2, Linux OPENGLES3, everything else SDL_RENDERER |
CNA_AUDIO_PLATFORM | SDL3, NULL, ALSA (Linux targets only) | SDL3 on every OS |
CNA_ENABLE_SDL (switch) | AUTO, ON, OFF (also TRUE/1 and FALSE/0/NO) | AUTO |
CNA_PLATFORM owns window, events, input, timing and host services. The renderer produces pixels. CNA_AUDIO_PLATFORM chooses the audio-device integration boundary. CNA_ENABLE_SDL decides whether the vendored SDL3 sub-build runs: with AUTO or ON SDL is configured as it always was; with OFF it is not fetched, built, found or linked, and any selection that genuinely needs it is refused by name. The compiler/toolchain still decides Linux, Windows, macOS, Emscripten, Android or iOS separately. Platform and audio values are case-sensitive; CNA_ENABLE_SDL is normalised.
SDL3 is the one windowing implementation. It reaches Windows, X11, Wayland, macOS, iOS, Android and the browser through SDL’s own video drivers (SDL_VIDEODRIVER picks one explicitly), and a renderer still receives the native HWND, Display*/Window or wl_display*/wl_surface* through the window’s native handle; Windows, X11 and Wayland has the details. HEADLESS and TERMINAL have no graphical window. There is no CNA_PLATFORM environment variable: one implementation is the compiled default, and the always-compiled Headless (and, off Windows, Terminal) can additionally be created by name at run time through PlatformFactory.
The three audio choices do not offer the same XNA feature set. SOUND_ENABLED is defined for SDL3 and ALSA. SDL3 uses SDL3_mixer; ALSA uses CNA’s own mixer and no SDL audio. NULL provides a real low-level IAudioDevice implementation, but that build omits the high-level mixer engine, so SoundEffect playback, MediaPlayer, XACT audibility and Microphone are not available. Choose NULL for silent CI, servers and device-boundary work, not as a drop-in production playback replacement. The Audio reference has the full matrix.
Combinations CMake refuses
The axes are independent, with hard exclusions. Every refusal is a configure-time FATAL_ERROR that names the reason; nothing silently falls back to SDL3.
| Selection | Why it is refused |
|---|---|
CNA_PLATFORM=TERMINAL with any renderer except SOFTWARE, HEADLESS, STUB | A terminal has no graphical native window a GPU API could bind to; it presents finished CPU frames. |
CNA_ENABLE_SDL=OFF with platform SDL3, audio SDL3, or renderer SDL_RENDERER/SDL_GPU/FNA3D (also inside CNA_GRAPHICS_RENDERERS) | “This configuration genuinely requires SDL”; the message lists which selections do. Because the platform and audio defaults are both SDL3, an SDL-free build must set both explicitly. |
The window-system names WIN32, X11 and WAYLAND as a platform value | Not platform implementations: the message points to -DCNA_PLATFORM=SDL3, which reaches those window systems through SDL’s video drivers. Never an alias. |
TERMINAL on Windows, SDL12, EMSCRIPTEN | Reserved identifiers, “NOT implemented”. (Emscripten as a target OS is real and served by SDL3.) |
CNA_AUDIO_PLATFORM=ALSA on a non-Linux target; OPENAL; WASAPI | ALSA is Linux-only; the other two are reserved names. |
| Any unknown value, or a wrong case | “Not a known platform” / “not a known audio platform”, listing the available and reserved sets. |
A renderer name outside the 14 public identities is refused by the same kind of configure error; see Renderers for the list, and Platform Support for which renderers each target OS offers.
Useful configurations
Default desktop host and audio, explicit renderer
cmake -S ../cna -B build-desktop \
-DCNA_PLATFORM=SDL3 \
-DCNA_GRAPHICS_RENDERER=OPENGLES3 \
-DCNA_AUDIO_PLATFORM=SDL3
No display and no high-level sound engine
cmake -S ../cna -B build-headless \
-DCNA_PLATFORM=HEADLESS \
-DCNA_GRAPHICS_RENDERER=HEADLESS \
-DCNA_AUDIO_PLATFORM=NULL
This is useful for game-logic CI and servers. A headless platform does not secretly force null audio: choose SDL3 (or ALSA) audio if the process should still play sound.
POSIX terminal presentation
cmake -S ../cna -B build-terminal \
-DCNA_PLATFORM=TERMINAL \
-DCNA_GRAPHICS_RENDERER=SOFTWARE \
-DCNA_AUDIO_PLATFORM=NULL
TERMINAL is POSIX-only and accepts exactly three CPU/no-output renderers: SOFTWARE, HEADLESS and STUB. It is not an implemented Windows-console mode. See Tutorial 139.
No SDL at all: a windowless build
cmake -S ../cna -B build-nosdl \
-DCNA_ENABLE_SDL=OFF \
-DCNA_PLATFORM=HEADLESS \
-DCNA_AUDIO_PLATFORM=ALSA \
-DCNA_GRAPHICS_RENDERER=HEADLESS
This is the configuration CNA’s SDL-free CI job builds; it then proves that the test executables and a demo link no SDL and load libasound at run time rather than linking it. An SDL-free build has no window: use HEADLESS, or TERMINAL with SOFTWARE, as the platform. Use -DCNA_AUDIO_PLATFORM=NULL instead if the machine has no ALSA headers. Tutorial 138 walks through it; the audio half is Tutorial 137.
A specific window system through SDL3
SDL_VIDEODRIVER=wayland ./build-desktop/my_game # or x11, or windows on Windows
The window system is chosen at run time, not at configure time: SDL picks one for the session, and SDL_VIDEODRIVER forces it. CNA’s platform CI runs the SDL3 platform suite on a private Xvfb and on a private headless Weston. See Tutorial 135, Tutorial 136 and Windows, X11 and Wayland.
SDL3 window, native audio
cmake -S ../cna -B build-alsa \
-DCNA_PLATFORM=SDL3 \
-DCNA_AUDIO_PLATFORM=ALSA
Legal: the window stays SDL3 while sound goes through ALSA and CNA’s own mixer. Configure needs the ALSA headers (libasound2-dev). This exact pairing is not exercised by CI.
Where there is no SDL-free audio
On Windows and macOS the only audio choices are SDL3 and NULL, and CNA_ENABLE_SDL=OFF refuses the first. An SDL-free Windows build is windowless (HEADLESS) and has silent NULL audio; OPENAL and WASAPI are reserved names, not implementations.
Reserved names are not support claims
SDL12 and EMSCRIPTEN are reserved platform identifiers (and TERMINAL is reserved on Windows); OPENAL and WASAPI are reserved audio identifiers. This snapshot rejects all of them at configure time. Emscripten as a target OS/toolchain is real, but it is not a CNA_PLATFORM=EMSCRIPTEN implementation.
Verify the configured axes
cmake -LA -N build-headless | grep -E 'CNA_(PLATFORM|GRAPHICS_RENDERER|AUDIO_PLATFORM|ENABLE_SDL)'
ctest --test-dir build-headless -N
The generated test inventory changes with all of these selections and with feature options. Report the values beside test results; a number without its configuration is not reproducible. The configure log also prints CNA: Using <NAME> platform implementation and CNA: Using <NAME> audio platform implementation.
Next steps
- Platform support reference
- Windows, X11 and Wayland
- Audio reference
- Complete build options
- Tutorial 126: Multi-renderer builds
- Tutorial 138: Building without SDL
- Tutorial 137: Native Linux audio with ALSA
Deep dives on this topic
Long-form pages that explain the exact semantics, invariants and evidence behind this subject.
- The cross-platform contract: axes, composition and evidence per route — How target OS, platform implementation, renderer set, audio implementation and the XNA surface compose in CNA, what IPlatform owns, and why each platform claim is an evidence vector.