Getting started as a maintainer
Evidence basis: source-verified at the pinned commit; tests exist (not executed for this page). Claims on this page were checked by reading the CNA source at commit 009d40f5; unless a sentence says otherwise, nothing here was built or executed. Preset names, targets and paths were read from CMakePresets.json and the CMake files at 009d40f5; no configure, build or test was run for this page.
The fastest way to become useful on CNA is to reach one working feedback loop on a known source snapshot, then read the code in dependency order instead of alphabetically. This page gives that loop (a display-free unit build), a reading order with the header paths that actually exist at the snapshot, and the rules that save the most time. It complements the user-facing Building CNA and Contribute pages, which cover toolchains, sibling repositories and the full option set. The commands below were read from CMakePresets.json and the CMake files at snapshot 009d40f5; none was executed for this page.
Confirm the source revision
These pages describe CNA commit 009d40f5dd085c4e674d3479675fac84b12b3e0a on branch next (24 September 2026). It is a post-alpha.1 development snapshot: the product version string is still 0.1.0-alpha.1. Two facts about clones matter before any recipe is trusted.
- Clone
next, not the default branch. GitHub's default branch oflibcna/cnaisdevelop, which is thev0.1.0-alpha.1tag commit. Usegit clone -b next https://github.com/libcna/cna.git, or check out the commit above. sharp-runtimemust be itsnextbranch too. Itsmainanddeveloplack theResourcesandXml.Serializationcomponents thatSharpRuntimeConsumption.cmakeasks for. CNA's own CI encodes the same rule:clone_siblings.shtakes the first of the pushed, source or target branch that a sibling has, thennext, thendevelop, because pinningdevelopmade every CI configure ofnextfail.easy-glandmeta-gluse their default branch.
Then compare your checkout with the snapshot. The first command asks whether the snapshot is in your history at all; the others show how far you have moved, and where:
git -C cna rev-parse HEAD
git -C cna merge-base --is-ancestor 009d40f5dd085c4e674d3479675fac84b12b3e0a HEAD && echo "snapshot is in your history"
git -C cna rev-list --count 009d40f5dd085c4e674d3479675fac84b12b3e0a..HEAD
git -C cna log --oneline 009d40f5dd085c4e674d3479675fac84b12b3e0a..HEAD -- modules/runtime
If your checkout differs, treat every path and symbol on these pages as a navigation hint and verify behaviour in your own tree: re-read the implementation before relying on an ordering, ownership or test-name statement, and read the diff of any file a page cites. The pages are pinned on purpose. The libcna.com repository records the snapshot in a one-line file, cnahead, and moves it only together with the prose and the generated references that depend on it; see Maintaining these pages for the procedure and the pin policy. CNA's checkout normally moves faster than the pin.
Establish a fast loop
The focused core unit preset avoids window and GPU requirements and is the safest first proof that compilers, CMake and the repository are usable:
# from the CNA repository root, with ../sharp-runtime (branch next) and the submodules in place
cmake --preset unit
cmake --build --preset unit-core --parallel
./cmake-build-unit/CnaCoreTests
./cmake-build-unit/CnaCoreTests --gtest_filter='LoggerTest.*'
ctest --test-dir cmake-build-unit -N
What those names mean at the snapshot, all from CMakePresets.json:
unitis a Ninja configure preset that selects Debug, theSTUBrenderer andCNA_BUILD_TESTS=ON, and turns examples, the C API, networking, FFmpeg video and Draco off. Its binary directory iscmake-build-unitunder the source tree (ignored by CNA's.gitignore). Every preset that inherits the hiddenbase-ninjapreset also turnsCNA_USE_CCACHEandCNA_EXPORT_COMPILE_COMMANDSon.unit-coreis a build preset bound to theunitconfigure preset; it builds the single targetCnaCoreTests.UnitTests.cmakeadds that executable at the root of the build, and nothing sets an output directory, which is why the binary iscmake-build-unit/CnaCoreTests. It is anEXCLUDE_FROM_ALLiteration target, not an extra CTest registration.- The presets define no test presets. Run the binary directly (from the repository root, where CNA's own CTest registrations set their working directory) or use
ctest --test-dir cmake-build-unit;-Nlists what the configured tree actually registers.
The neighbours of unit-core, and what a green run of each does and does not establish:
| Build preset | Target | Use it for | Does not tell you |
|---|---|---|---|
unit-core | CnaCoreTests | Core module tests (Logger, version, target platform, default window title). | Anything about windows, renderers, audio output or input hosts. |
unit-math | CnaMathTests | Math value types and their packed layouts. | Public ABI layout beyond what the tests assert. |
unit-content | CnaContentTests | Content readers, the CNB and XNB paths, ContentManager. | GPU translation of loaded resources: the renderer is STUB. |
unit-graphics | CnaGraphicsTests | Neutral graphics logic: state, resources, device validation. | Native rendering; cases that need a renderer capability the STUB lacks skip. |
unit | CnaTests | The aggregate GoogleTest corpus for this configuration. | Other renderer, platform and audio combinations. |
Two further pairs exist for iteration rather than validation: dev and dev-fast-debug configure a STUB Debug tree with tests off and build the cna_tool_cnb_info target (the second uses CNA_DEBUG_INFO=LINE_TABLES to shrink debug information), and unit-core-math-unity and unit-content-pch are opt-in build-time experiments that batch or precompile part of the unit tree. The desktop presets that do open windows (tests, cnaext, the three devices-* sanitizer presets) are covered on What to test after changing X.
What the first configure needs, beyond the sibling above: the vendor/googletest submodule (tests are on), and the SDL submodules, because the default platform is SDL3 and the vendored SDL3, SDL3_image and SDL3_mixer are built at configure time into a persistent .sdl-prebuilt-<os>-<arch> directory inside the source tree. Expect the first configure to take a while; later configures and clean build directories reuse that cache. The unit preset needs neither easy-gl nor meta-gl, because the renderer is STUB (they are required by the five GL-profile identities, including the Linux default). The details are in Building CNA, sibling repositories and CMake presets.
What “green” means here. A passing unit-core run shows that the toolchain, CMake configure (including its platform-boundary, hot-path, descriptor and source-partition gates, which need Python 3 and are skipped without it), the siblings and the core tests work together. It says nothing about rendering: the STUB renderer draws nothing. Choose the next check from the change, not from the file extension; the route is on What to test after changing X and the change map.
Read in this order
Start from ownership boundaries. The order below follows the dependency direction: what a module is, then the object that orchestrates a frame, then the host and renderer contracts it drives, then the three build axes that decide which implementations exist.
docs/physical-modules.md: what a physical module is, its CMake target and dependency edges, and how the partition validator keeps ownership total. The generated Module index shows the same modules from the tree.Game.hppthenGame.cpp: the orchestration boundary. The member-order comment in the header explains why the platform is declared first; in the source read the constructor,Tick,PollEventsandDispose. The traces are startup, one frame and shutdown.IPlatform.hpp, thenPlatformFactory.hppwithPlatformFactory.cpp: host services, the narrow service interfaces it hands out, and how an implementation name becomes an object. The backends are indexed on Platform backends.GraphicsDevice.hppthenGraphicsDevice.cpp, alongside the renderer contractIGraphicsRenderer.hpp: the renderer-facing resource owner, and the interface every renderer family implements. The tour is GraphicsDevice internals.PlatformSelection.cmake,RendererSelection.cmakeandAudioPlatformSelection.cmake: the three independent build axes, with the generated Selection axes index as the table of values. ReadRendererIdentities.cmakefor the identity list andRendererCombinations.cmakefor the refusals.UnitTests.cmake: how the test groups, focused executables and CTest registrations are assembled. It explains why an absent suite inctest -Nis information.- The focused subsystem page and its tests, before touching the implementation: Internals lists them, and First 10, 50 and 100 hours sequences the study.
Paths that look right and are wrong. The public header of Game is under modules/runtime/include/Microsoft/Xna/Framework/, not under a CNA/ include root, and IPlatform.hpp is under modules/platform/include/CNA/Platform/, not under a CNA/Internal/Platform/ directory. Likewise GraphicsDevice.hpp is in the XNA-shaped Microsoft/Xna/Framework/Graphics/ tree, not in a CNA/Graphics/ directory of the graphics module; no header exists at any of those three wrong locations at this snapshot. The rule that explains the layout: a module's include/ root reproduces the public namespace path, so XNA-shaped types sit under Microsoft/Xna/Framework/, CNA extensions and platform contracts under CNA/, and renderer contracts under CNA/Internal/Renderers/Common/.
Rules that save time
CNAis anINTERFACEumbrella, not a binary build target.modules/CMakeLists.txtdeclares it withadd_library(CNA INTERFACE); it has no sources of its own, socmake --build <dir> --target CNAdoes not work. Build a preset, a focused module target (CnaMathTests,CnaGraphicsTestsand the others listed in the Test target index) or one example or test by its own name.- Do not run window or GPU tests on your live desktop. CNA's own repository instructions make this mandatory:
CNA_TEST_DISPLAYis empty by default so a test inherits the launcher's display, and naming the live display needs-DCNA_TEST_DISPLAY=:0 -DCNA_TEST_ALLOW_LIVE_DISPLAY=ON(TestDisplayPolicy.cmake). Userun_gpu_tests_private.sh, which starts a private headless Weston and a private Xwayland; the private-display and native-host caveats are on What to test after changing X. - Do not infer completeness from a backend directory. A directory under
modules/renderers/proves that source exists. Whether an identity is offered, selected, wired into a target, covered by a conformance test and actually implemented are five separate questions: registry identity (RendererRegistry.cmake), selection logic, target wiring, tests and the current implementation.modules/renderers/common/is not even a renderer; it holds shared helpers. - Current source is authoritative when older prose and code disagree, including CNA's own Markdown. Repository notes are dated records:
NEXT.mdsays near its top that entries dated before the 2026-09-17 renderer curation describe renderer sets CNA no longer has, and the instruction files can lag the CMake (see Conventions). Trust the selection files, the presets and the tests over any description of them. - Reuse stable build directories and let ccache work. CNA's instructions ask for stable in-repo
cmake-build-<variant>/directories so rebuilds are incremental, never a scratch or temporary directory, andCNA_USE_CCACHE(on by default) with-DCMAKE_CXX_COMPILER_LAUNCHER=ccacheif a fresh configure reports the launcher missing. Build parallelism is not capped (--parallel); the constraint that remains is memory, because sanitizer and template-heavy translation units can each want several gigabytes, so lower the job count for the target that starts swapping rather than for the whole build. Build only the sanitizer variant a task needs: the binaries are large.
Where to go next
With the loop working, choose by what you have to do. To understand the whole system, follow the Human Takeover route. To change something now, start from the change map, respect the architectural invariants and the conventions, and pick tests with What to test after changing X. To chase a failure, use the debugging cookbook. The day-to-day loop (bug, feature, public API, renderer, platform, tests, self-review) is on Working on CNA.
Related pages
The same subsystem is explained at four altitudes. These are the neighbouring pages at each one.
- User guide
- Getting started (user guide) · Building CNA: presets · Contribute
- Architecture
- Architecture overview
- Maintainer workflow
- Human Takeover · Change map · Maintenance and pin policy
- Tests and validation
- What to test after changing X
- Reference
- Module index · Selection axes index