Repository map

CNA snapshot 009d40f5  ·  Development › Repository & Ownership  ·  source links pinned to 009d40f5

✓

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. File counts were computed from the Git tree of the pinned commit and link edges were read from each module's CMakeLists.txt; the tests named exist and are registered in CMake, but nothing was configured, built or executed for this page.

CNA is a module-oriented monorepo. Production code lives under modules/, build policy under cmake/, shared fixtures and cross-module suites under tests/, and generators, audits, launchers and harness sources under tools/ and scripts/. This page is the map of that layout at snapshot 009d40f5: what each directory holds, how a module directory is shaped, which headers are public, Internal or private, what is generated, where the vendor boundaries run and which tests belong to whom. Read it before opening a source file you did not write; the lookup "which part of CNA owns this behaviour?" is a separate page, Source ownership.

ℹ

How the three layout pages divide the work. This page is the map: directories, module shape, header classes, generated files, vendor boundaries, test ownership. Source ownership answers "who owns this behaviour" by symbol and subsystem. The physical module dependency map draws the link edges between the module targets. File and header counts below were computed from the Git tree of the pinned commit; nothing was built or executed for this page. The user-level view of the same layout is Architecture: module layout and Architecture: directory structure.

Top-level map

Every row is a directory (or file group) at the repository root, with the number of files Git tracks in it at this snapshot. The right-hand column says when you would edit there. Counts describe tree shape, not importance.

PathWhat it holds at this snapshotModify when…
modules/
4,798 files
23 directories: 22 declared framework modules plus renderers/ (21 implementation families and the two shared helper directories common/d3d and common/mojoshader). Public and Internal headers, implementations, module-owned tests, examples and benchmarks, and each module's own CMakeLists.txt.Changing CNA behaviour or API. This is where nearly every production change lands.
cmake/
196 files
Platform, audio, SDL-availability and renderer selection and the renderer registry; third-party setup (ThirdParty*.cmake, native X11 and Wayland detection); build policy (BuildPerformance, SharedRuntimeLibrary, SharpRuntimeConsumption, ApplePlatform); test registration (UnitTests, TestHelpers, TestDisplayPolicy, Harnesses, DirectXParityTests, XnaPipelineParityGates); script-mode gates under Tests/; toolchain files for mingw-w64 and iOS; two templates; and 122 files under patches/.Adding a backend, option or target, or changing how the configuration is composed. See CMake architecture.
tests/
2,340 files
Data and cross-module material, not the unit tests of any one module: assets/ (1,139 files, mostly glTF, XNA 4.0 and XNB fixtures), gltf-l7/ (578: rendered-pixel golden images and reports for four renderers), reference/xna40/ (566: the recorded Content Pipeline oracle data), fixtures/ (compiled-effect and Direct2D fixtures that tests replay), interop/, support/ (a header-only compiled-effect conformance suite), modules/ (15 minimal-link module probes), apple/ (the Apple smoke application), and two C++ sources at the root, HarnessAssertionPolicy.cpp and OracleCorpusTests.cpp.A contract spans several modules, a fixture or reference asset changes, or a module's link closure must be pinned. See Where tests live.
tools/
448 files
Sources of CNA's own command-line tools and harnesses (the cna-content front end under tools/content, the glTF and CNB converters), the oracle and reference tooling (xna-pipeline-oracle, xna-oracle, xna-sample-sweep, fna-reference, cna-reference), platform launchers and audits (tools/platform: 64 files including run_gpu_tests_private.sh, x11_test_server.sh, wayland_test_server.sh and the SDL containment audits), the C API generators (tools/c-api), the shader-package generator and the build-performance scripts (tools/build).Automating or auditing a repository invariant; changing a tool's own behaviour.
scripts/
65 files
Repository gates that CTest and CI run (check_renderer_identities.py, check_renderer_combinations.py, check_module_link_closure.py, check_test_display_isolation.py, the CNAEXT checks), corpus and oracle runners, the Wine, DXVK and vkd3d wrappers, the browser-test drivers and scripts/ci/clone_siblings.sh.A gate's rule changes, or a new invariant deserves a script.
docs/
240 files
Design notes and contracts: docs/physical-modules.md, per-renderer notes, the platform notes, the C API documents under docs/c-api, ADRs under docs/adr, recorded reports.A documented contract changes with the implementation. Treat a document as evidence of intent and check it against the code: for example the physical-modules note says the top-level examples/ holds exactly one thing, but the tree also has a loose examples/xvfb_screenshot_demo.cpp that is not a top-level target: only the EasyGL and SDL_Renderer example CMake files compile it, as ad hoc test targets.
.github/workflows/
20 files
The CI workflows: 28 jobs over Linux, macOS, iOS, Windows (MSVC and MinGW under Wine) and a headless browser.Validation coverage or environment changes. See what CI covers.
third_party/, vendor/Dependency boundary: four submodules and four in-tree vendored libraries under third_party/, and the googletest submodule under vendor/.Only deliberate dependency maintenance. See Third-party and vendor boundaries.
examples/
18 files
The cross-renderer golden-image corpus examples/golden/, loaded at run time through repository-root-relative paths, plus the loose file mentioned above. Module examples live with their module, not here.A golden image is regenerated. Do not add new examples here: a module-specific example belongs in that module's examples/.
spikes/
95 files
26 existence-gate probe directories, one per question a new backend or platform had to answer before real code was written (for example the terminal, Wayland, Win32, WebGPU and several real-XNA behaviour probes).Recording a new probe. They are evidence for a decision, not production code.
Planning, audit and history treesplans/ (109 files; the plan identifiers quoted in CMake comments, such as GL4-0016 or SMG-0039, refer to them), plan/, audit/ (2,493 files, mostly per-source-file audit records that mirror the tree), remediation/, modularization/ (142 files: the physical-move maps and tools such as check_include_reachability.py), integration/, misc/, and root notes such as NEXT.md, AUDIT.md, TODO.md and known_bugs.md.Recording intent or history. None of it is a build input; use it to learn why a rule exists, then confirm what executes in the source.
Root filesCMakeLists.txt, CMakePresets.json, .gitmodules, Doxyfile, README.md, the contributor rules CLAUDE.md and AGENTS.md, CHANGELOG.md, and main.cpp, a hello-world stub that no CMake file references.Root policy, presets, version identity.
⚠

There is no top-level include/ or src/. Consumer-visible headers live under each module's own include/, and implementations under its src/. A production translation unit outside every declared module fails the configure, and so does a root-level src/ or include/ directory reappearing ("legacy global tree reappeared"): see modules/CMakeLists.txt. A search that starts by looking for a shared include root will find nothing; start from the owning module.

Physical module shape

modules/<name>/
├── CMakeLists.txt       target and dependency declaration; collects its own sources
├── include/             public and cross-module headers, spelled as consumers include them
│   ├── Microsoft/...    XNA-shaped API (Microsoft/Xna/Framework/..., Microsoft/Devices, Microsoft/Phone)
│   └── CNA/...          CNA-owned surface; CNA/Internal/... holds cross-module internal contracts
├── src/                 implementation and module-private headers
│   ├── Xna/             XNA API implementation
│   ├── Internal/        CNA::Internal engine parts
│   └── CnaExt/          CNAEXT extension surfaces (single-area modules stay flat)
├── tests/               GoogleTest sources mirroring the namespace path
├── examples/            demos and example programs, registered by the module's own CMake
└── benchmarks/          only diagnostics and inspector have one

The include tree mirrors the namespace-facing path, so #include "Microsoft/Xna/Framework/Graphics/Texture2D.hpp" resolves from modules/graphics/include and the spelling is identical wherever a consumer sits. A module's src/ uses the area convention Xna/, Internal/, CnaExt/ (see modules/graphics/CMakeLists.txt for the globs); the platform module instead gives every implementation its own directory (Sdl3/, Sdl2/, Win32/, X11/, Wayland/, Headless/, Terminal/) beside Common/ and the pieces only the Unix desktop backends share (Xkb/, Freedesktop/, Posix/, Linux/), and the audio module separates Platform/ (devices) from Backend/ (mixers). The CNA umbrella composes module targets as an INTERFACE library; it does not compile into one giant library, and cmake --build <dir> --target CNA is not a buildable target (the umbrella and its link closure).

  • How a module becomes a target. modules/CMakeLists.txt defines cna_add_module(target alias sources...): a STATIC library cna_<name> with the alias CNA::<Alias>, linked PUBLIC to cna_build_config and publishing that module's own include/ as its PUBLIC include root. Sources are collected with file(GLOB … CONFIGURE_DEPENDS) from the module's own src/ (the graphics core globs its Xna, Internal and CnaExt areas, a renderer family globs only its own src/*.cpp, not recursively), so adding a .cpp there needs no CMake edit. The one module that lists its sources by hand is c-api.
  • Naming exceptions. gamer-services, net and video-ffmpeg call add_library directly (CNA_GamerServices, CNA_Net, cna_video_ffmpeg); core also defines the header-only cna_core_headers (CNA::CoreHeaders) that math, storage and phone link instead of the archive; content-pipeline is cna_content_pipeline with the alias CNA::ContentPipelineBuild; c-api is cna_c_api, a shared library (static under Emscripten); each renderer family is cna_renderer_<family> with - replaced by _.
  • One documented ownership exception. The GDI renderer compiles eight software-module CPU-2D translation units into its own archive; their physical owner stays renderers/software. Every other file's directory is its CMake owner.
  • Renderer families need not have every subdirectory. Fifteen of the 21 families have a tests/ directory (and so do both shared helpers); freedirect, gdi, headless, portablegl, sdl-renderer and stub keep their tests as example programs under examples/.

The 23 directories and their targets

The direct CNA link edges below were read from each module's CMakeLists.txt (PUBLIC unless marked); sharp-runtime components and third-party libraries are left out. "Umbrella" means the target is one of the parts of the CNA INTERFACE library in modules/CMakeLists.txt. The three intentional static-archive cycles (graphics and input, audio and media, graphics and the selected renderer) are why some edges are PRIVATE.

DirectoryTarget (alias)UmbrellaOwnsDirect CNA link edges
corecna_core (CNA::Core), cna_core_headersyesBase types, logging and exceptions, TargetPlatform, the renderer identity enum and GraphicsRendererSelection, the CNAEXT marker macronone
mathcna_mathyesVectors, matrices, quaternions, colours, bounding volumes, curvescna_core_headers
diagnosticscna_diagnosticsyesCounters, zones and frame history, compiled to nothing when CNA_DIAGNOSTICS=OFFnone
platformcna_platformyesIPlatform and its implementations; the module that links the native windowing and host libraries (privately on desktop; audio and the SDL-by-identity or SDL-upstream renderer families link SDL for their own backends)cna_core_headers
graphicscna_graphics_core (CNA::GraphicsCore)yesXNA graphics API, GraphicsDevice, renderer interfaces, descriptors and the generated registrycna_math, cna_core, cna_diagnostics, cna_platform; PRIVATE cna_input and every selected renderer
inputcna_inputyesKeyboard, mouse, gamepad, touch and gesturescna_graphics_core, cna_math, cna_core, cna_platform
audiocna_audioyesXNA audio and XACT, the audio devices and mixerscna_core, cna_diagnostics, cna_math; PRIVATE cna_platform, cna_media, cna_input
mediacna_mediayesMediaPlayer, MediaLibrary, the Video surface (link-complete without FFmpeg)cna_audio, cna_graphics_core; PRIVATE cna_input, and cna_video_ffmpeg when FFmpeg is enabled
video-ffmpegcna_video_ffmpeg (CNA::VideoFfmpeg)noThe optional FFmpeg backend; entered only when FFmpeg was foundcna_build_config; linked into cna_media only
contentcna_contentyesContentManager, XNB and CNB readers and writers, the canonical pipeline API under CNA/Content/Pipelinecna_graphics_core, cna_audio, cna_media, cna_math, cna_core
content-pipelinecna_content_pipeline (CNA::ContentPipelineBuild)noBuild-time-only components: the FreeType .spritefont route, FFmpeg importers, FBX and .x readers, the external effect-compiler service, the XNA Content.Pipeline facadecna_content; linked by cna_content_compiler and the content-pipeline test targets, never by the umbrella
storagecna_storageyesStorageDevice, StorageContainer and path containmentcna_core_headers
runtimecna_runtimeyesGame, GameWindow, GraphicsDeviceManager, components, the project graphics profilecna_graphics_core, cna_input, cna_content, cna_audio, cna_media, cna_core, cna_diagnostics, cna_math, cna_platform
devicescna_devicesyesThe XNA-compatible Microsoft::Devices sensors and vibrationcna_runtime, cna_graphics_core, cna_core, cna_math
devices-extcna_devices_extyesCNA device extensions: camera, clipboard, dialogs, tray, power, locale, URL launchercna_runtime, cna_graphics_core, cna_core, cna_math, cna_platform; never the XNA device base
phonecna_phonenoThe Microsoft::Phone application shellcna_runtime, cna_core_headers
graphics-extcna_graphics_extyesThe CNAEXT engine layercna_graphics_core
designcna_designno (opt-in)Framework.Design type converterscna_math
inspectorcna_inspector and the cna-inspector executablenoInspector agent, bridge and browser UI; defined only with CNA_BUILD_INSPECTORcna_diagnostics, cna_core_headers
gamer-servicesCNA_GamerServices (CNA::GamerServices)noGamerServices, Guide, Avatar, local persistence; entered only with CNA_ENABLE_NETcna_runtime, cna_storage
netCNA_Net (CNA::Net)noMicrosoft::Xna::Framework::Net over ENet; entered only with CNA_ENABLE_NETCNA_GamerServices, enet
c-apicna_c_api (CNA::CApi)noThe experimental C ABI (0.29.0; public headers held to a C99 consumer floor, CNA's own C sources built as C17); entered only with CNA_BUILD_C_APIPRIVATE cna_core, cna_platform, cna_runtime, cna_graphics_ext, cna_storage, cna_content, cna_media, cna_devices, cna_devices_ext, CNA_Net, CNA_GamerServices
rendererscna_renderer_<family> for each of 21 familiesthe selected family or setBackend translation of resources, draws, presentation and synchronisation behind IGraphicsRendererPRIVATE reverse edges to cna_graphics_core, cna_core, cna_math

Rows for graphics and renderers hide the interesting part: the graphics core links every selected family privately (the factory edge) and each family links the graphics core back (the reverse edges), which is why static link order is a declared invariant rather than an accident. Both halves are traced in the CMake architecture chapter. The generated module index lists the same directories with header, source and test-file counts and entry-point headers; its "test files" column counts every file under tests/, not the 904 C++ test sources discussed below.

Public, Internal and private headers

"Public" is a tree-shape word at this snapshot, not an export mechanism. The C++ framework has no install() rules, every module publishes its whole include/ directory PUBLIC, and nothing stops a target that links a module from including a header under CNA/Internal. The classes below are conventions enforced by review and by the gates in What keeps this map true.

ClassWhereMeaning and example
XNA-shaped public APIinclude/Microsoft/…The names and shapes of XNA 4.0 and the Windows Phone shell. Example: GraphicsDevice.hpp.
CNA-owned public surfaceinclude/CNA/… outside Internal/Facilities and CNAEXT extensions that are not XNA: GraphicsRendererSelection.hpp, RendererCapabilityProfile.hpp, and the engine layer under graphics-ext. Every declaration that is not part of XNA 4.0 is tagged CNAEXT through CNAHelper.hpp.
Cross-module internal contractsinclude/CNA/Internal/…Contracts between modules that are not for consumers: IGraphicsRenderer.hpp and the descriptor and registry headers beside it, and each family's own CNA/Internal/Renderers/<Family>/ root. They live in an include root, so "Internal" is a naming and review convention, not a visibility barrier.
Module-private headerssrc/…Headers next to the implementation. No module adds another module's src/ as an include root, with two deliberate exceptions: every renderer target adds modules/platform/src PRIVATE (the SDL-backed families on the platform SDL audit's allow-list reach the one edge Sdl3RendererInterop.hpp), and the test build adds modules/audio/src so an implementation test can see a private audio device.
C ABI headersmodules/c-api/include/CNA/C/*.h61 plain-C headers with their own version (ABI 0.29.0, experimental) and their own build gates. See C API and bindings architecture.
Generated headersbuild treeCNA/Version.hpp is rendered into <build>/generated/include and added to core's include roots; see Generated and checked-in generated files.

The generated public header index lists 808 non-Internal headers under include/CNA and include/Microsoft in 21 modules; it says nothing about which of them are supported API.

Subsystem families

Group modules by the question they answer and the boundary a change crosses, not by directory name. Each row is a family of modules that usually change together; the last column states the ownership fact a reviewer should hold in mind. For the per-object lifetime rules behind these statements see Ownership and lifetime master map and What a human maintainer inherits.

FamilyModulesCalls and ownership
OrchestrationruntimeGame coordinates the platform, services, components and frame callbacks; it owns the platform it installs and the GraphicsDevice value member (Runtime module internals).
Host boundaryplatform, input, audioPlatform implementations emit events and provide narrow services; nothing outside platform links a platform library. Input state is process-wide. Audio devices and mixers are selected by their own axis (Platform architecture).
Renderinggraphics, graphics-ext, renderers/*GraphicsDevice owns public resource tracking; the selected renderer translates commands. graphics-ext is the CNAEXT layer above the same device (Graphics architecture).
Assetscontent, content-pipeline, mediaRuntime load and cache live in content together with the canonical pipeline engine and the XNB and CNB writers; content-pipeline holds only what must never ship in a game. Neither the pipeline module nor FreeType is in a game's link closure (Content architecture).
Interopc-apiThe experimental C ABI (public headers held to a C99 consumer floor) converts handles and errors across the C++ boundary; a C++ change can become ABI, lifetime and compatibility work. Opt-in through CNA_BUILD_C_API, which requires CNA_ENABLE_NET=ON.
Foundationscore, math, storage, diagnosticsShared value types, identities and services; keep upward dependencies out. math and storage link only the header-only cna_core_headers.
Device and phone compatibilitydevices, devices-ext, phoneSensors, device extensions and the Windows Phone shell sit above runtime; the extension module never depends on the XNA device base.
Optional services and toolingnet, gamer-services, video-ffmpeg, design, inspectorEach is entered or linked only when asked for (CNA_ENABLE_NET, CNA_ENABLE_VIDEO, CNA_BUILD_INSPECTOR) or named on a link line. A default build says nothing about them.

How to find the owner

  1. Find the public symbol's declaration with a search under the module include/ directories, for example rg -n "class SoundEffect\b" modules/*/include. The directory you land in is the candidate owner.
  2. Find the out-of-line definition, the constructor and every place the state is mutated in that module's src/. A static XNA API (Keyboard::GetState, StorageDevice) may reach an ambient platform rather than a context you can see.
  3. Trace factory and registry creation instead of assuming the directory is selected. For a renderer that means the identity map in cmake/RendererRegistry.cmake, the family's *RendererDescriptor.cpp and the generated CnaRendererRegistry.generated.cpp; for a platform, PlatformFactory; for audio, the compiled-in device and mixer.
  4. Search the focused tests in the owning module's tests/ first, then the conformance and integration tests that name the symbol, then the renderer-family example programs.
  5. Read the module's CMakeLists.txt before crossing a boundary: which targets it links, whether the link is PUBLIC or PRIVATE, and whether the module is entered conditionally.
  6. Confirm the answer against Source ownership, the module dependency map and the generated module index and public header index, which give source-pinned entry points.

Generated and checked-in generated files

Two different things are called "generated". Some files are produced into the build tree during configure or build and never committed; others are committed but must stay derivable from their sources, and a gate fails when they drift. Before committing a change to either kind, find the generating rule and reproduce the output from clean input.

FileProduced byCommitted?Guard
<build>/generated/CnaRendererRegistry.generated.cppcmake/RendererRegistry.cmake from cmake/templates/CnaRendererRegistry.generated.cpp.in, compiled into cna_graphics_corenothe descriptor gate and RendererIdentityRegistry
<build>/generated/include/CNA/Version.hppcmake/Version.cmake from the version set in the root CMakeLists.txtnosingle source of the version string
<build>/generated/cna_shared_library.cppcmake/SharedRuntimeLibrary.cmake (a one-line stub so libcna.so has a source)noonly with CNA_SHARED_LIBRARY
<build>/generated/wayland-protocols/wayland-scanner through cmake/PlatformWayland.cmakenoonly for CNA_PLATFORM=WAYLAND
the compiled-effects stock-effect header for EasyGLa custom command in modules/renderers/easygl/CMakeLists.txtnoonly with CNA_EASYGL_COMPILED_EFFECTS
.sdl-prebuilt-<key>/ in the source treethe configure-time SDL sub-builds (the SDL prebuilt)no (git-ignored)a build manifest stamp
spirv_shaders.hpp for Vulkan and SDL_gpucompile_shaders.py beside each file (modules/renderers/vulkan/src/shaders/spirv_shaders.hpp)yes, marked "do not edit by hand"the SpirvPayloadValidation gate in a configuration that includes VULKAN, where spirv-val is installed
*ShaderPackage.generated.hpp (engine layer and examples)tools/shader_package/generate_shader_package.pyyesthe *ShaderPackageReproducibility tests re-derive a package with --check and skip (77) without shaderc; reproducibility tests are registered for most of the 20 shader packages in the tree but not all (none was found for the shadow-caster or modern-resource-interop packages)
the C ABI baseline, compatibility matrix, coverage inventory and limitationsthe generators under tools/c-apiyesfive C API workflows and the CApi* CTest gates
the content-pipeline parity reporttools/xna-pipeline-oracle/parity_report.pyyesthe XnaPipeline* gates in cmake/XnaPipelineParityGates.cmake
the glTF conformance corpus (tests/assets/gltf fixtures, manifests and vertex/index goldens)scripts/regenerate-gltf-goldens.shyes--check and --determinism in the glTF sanitizer workflow
rendered glTF goldensscripts/gltf-l7-corpus.py --update-goldensyes; the script requires --report-out with it and a second run that agrees byte for byterun below an X server (normally xvfb-run -a)

Third-party and vendor boundaries

Four mechanisms bring outside code into a CNA build, and each has a different rule for how you touch it. The general rule: third_party/ and vendor/ are external. CNA's build policy (warnings, sanitizers, debug-information and linker options) is attached only to targets whose source directory lies inside the repository and outside those two trees, so a change there is dependency maintenance, not a CNA edit.

KindWhatHow it enters the build
Git submodules (five gitlinks)third_party/SDL (pinned at cbe3fbe9), third_party/SDL_image (fcb9d0b1), third_party/SDL_mixer (3075d3ed), third_party/draco (1.5.7, 87867400), vendor/googletest (7e2c425d)git submodule update --init, non-recursive. SDL, SDL_image and SDL_mixer are built at configure time into a persistent prebuilt directory; Draco is a subdirectory unless CNA_ENABLE_DRACO=OFF or a system package is chosen; googletest is added while CNA_BUILD_TESTS=ON. A missing submodule stops the configure with a named message. With CNA_ENABLE_SDL=OFF the SDL submodules are never touched.
Vendored in the treethird_party/enet, third_party/stb, third_party/dr_libs, third_party/cgltfCompiled or included directly (ENet only with CNA_ENABLE_NET). The module CMake files reach the vendored single headers through CNA_SOURCE_DIR rather than CMAKE_SOURCE_DIR, so a consumer that adds CNA as a subdirectory still finds them.
Sibling repositories../sharp-runtime (every build, its next branch), ../easy-gl with ../meta-gl (the five GL identities), ../free-direct with ../free-api (FREEDIRECT only)Separate checkouts entered with add_subdirectory(../<repo>); CMake will not fetch them. sharp-runtime's location is the CNA_SHARP_RUNTIME_ROOT cache path. See the Building CNA sibling checkouts.
Fetched at configure timeFNA3D with MojoShader (pinned tag, 3240147), wgpu-native (v29.0.1.1), PortableGL (63a55db7), SDL_shadercross (1ff05bec) with SPIRV-Cross, and SDL2 (2.30.11) for CNA_PLATFORM=SDL2Only when the renderer, option or platform that needs them is selected. FNA3D's MojoShader also receives a series of local patches from cmake/patches (117 MojoShader patch files against one pinned revision), applied automatically and idempotently; SDL and SDL_shadercross have their own small series. Details in CMake architecture: third-party dependencies.

Where tests live and who owns them

Test ownership follows source ownership. A module's unit tests live in that module's tests/, mirroring the namespace path, and are compiled into a per-module object group; renderer-family behaviour is exercised mostly by example programs in the family's examples/; only genuinely cross-module material sits in the top-level tests/. The counts follow the table; how the sources are assembled into executables is described on Test architecture.

LocationOwnsRuns as
modules/<name>/tests/Focused GoogleTest sources for that moduleOne object group, linked into the aggregate CnaTests and into that module's focused executable
modules/renderers/<family>/tests/ and modules/renderers/common/*/tests/Renderer-policy suites that need no device (capabilities, descriptors, state mapping)The renderers group, CnaRendererTests
modules/<name>/examples/, modules/renderers/<family>/examples/Demos and the standalone pixel and smoke programs (879 *_test.cpp programs, outside the 904 and 12,610 figures)Separate executables, each registered through cna_register_renderer_test or add_test in the module's own CMake
modules/c-api/tests/The C API's consumer tests: mostly C files with their own main(), plus seven C++ filesTheir own executables and CApi_* CTest entries; deliberately not part of CnaTests
top-level tests/*.cppHarnessAssertionPolicy.cpp, OracleCorpusTests.cppThe integration group, CnaIntegrationTests
tests/modules/Fifteen minimal-link probes, one per module aliasStandalone executables with a paired link-closure gate
tests/assets, tests/reference, tests/gltf-l7, tests/fixturesFixtures and recorded reference data, addressed by repository-root-relative literal pathsRead by tests; discovered CnaTests cases run with the repository root as their working directory

The 904 C++ test source files counted by the site method (every .cpp under a tests/ or test/ directory, vendored code excluded) are distributed as follows, recomputed by path from the Git tree at this snapshot. The figure is a source inventory, not an executable case count and not a pass result.

OwnerFilesOwnerFiles
content170audio38
graphics161net18
graphics-ext92gamer-services14
platform85devices-ext10
renderer families and helpers (17 directories)69core9
input47c-api (seven C++ files)7
content-pipeline47design, phone (2 each)4
media30diagnostics, inspector, storage (1 each)3
devices27top-level tests/ (2 sources, 15 probes, 1 Apple smoke app)18
math27one test-display fixture under cmake/Tests1
runtime27

What keeps this map true

Most of the layout is enforced mechanically, so a map that disagrees with the tree is the map's fault. These are the gates to run or read when you move a file, add a module, or add a dependency edge.

  • Source-partition validator in modules/CMakeLists.txt: every .cpp or .mm under modules/ must sit in a declared module's src/, tests/, examples/ or benchmarks/ tree (lists _cna_framework_modules and _cna_renderer_modules); a legacy root src/ or include/ fails. Moving a file between directories is a build-ownership change, not a rename.
  • Minimal-link probes in cmake/Tests/ModuleProbes.cmake: fifteen tiny consumers of one module alias each, paired with ModuleLinkClosure_* tests that run scripts/check_module_link_closure.py over the generated link line and fail when a forbidden archive or library appears. The HEADLESS configuration additionally proves that renderer-neutral graphics needs no native graphics SDK.
  • Identity and discipline scripts: scripts/check_renderer_identities.py holds the CMake identity list, the registry map, the C++ enumeration and the C ABI header to one canonical table; scripts/check_renderer_target_discipline.py and scripts/check_runtime_renderer_discipline.py keep families from reading global scalars and keep renderer-specific decisions behind descriptors.
  • Include reachability: modularization/tools/check_include_reachability.py checks that every "CNA/..." or "Microsoft/..." include in a module translation unit resolves through a module graph written into the script itself. At this snapshot that graph is out of date (it lists 14 of the 22 declared framework modules; platform, diagnostics, content-pipeline, phone, c-api, design, inspector and video-ffmpeg are absent) and no CMake rule, test or workflow runs the script, so it is a manual aid rather than a gate that keeps this map true.
  • Configure-time SDL audits (the platform ratchet, the non-production SDL audit and the hot-path lint) keep SDL inside the platform module; see CMake architecture: gates that run at configure time.
ℹ

The physical-modules note docs/physical-modules.md is a useful summary but is not a substitute for the CMake files it summarises: for example its dependency table omits the input, diagnostics and platform edges of cna_runtime that the module's own CMakeLists.txt declares. When the two disagree, the CMake file is what executes.

The same subsystem is explained at four altitudes. These are the neighbouring pages at each one.