The CNA ecosystem: siblings, references and consumers

CNA snapshot 009d40f5  ·  Deep Dives › Foundations & compatibility  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit. 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. Sibling statements were read in each sibling repository at the revision named in the table (sharp-runtime 41b918c9, easy-gl deda7a42, meta-gl 20c8b2dc, free-direct 934f72ff, free-api 53d7a312, xna4-spec fedc17aa, cna-samples 4da98a0, cna-examples ea33c9a2); they are evidence for those revisions, not for CNA 009d40f5. Counts quoted from sibling READMEs are those projects' own records.

CNA is not one repository. It builds against sibling libraries that are separate checkouts, it is audited against references it does not link, and it is exercised by consumer repositories that pin their own CNA revisions. This page maps those relationships as they stand for CNA snapshot 009d40f5: which repository provides what, when CMake needs it, where each sibling draws its own boundary, and which revision a statement about a sibling refers to. It is the orientation page for anyone setting up a build or deciding which repository a problem belongs to.

The dependency graph

 REFERENCES (read or executed, never linked)
   Microsoft XNA 4.0 XML docs + DLL metadata ---- representation census ------+
   FNA source tree and FNA.dll ------------- behaviour, value diffs ----------+
   genuine XNA 4.0 under Wine + DXVK ------- 39-scene pixel oracle -----------+
   xna4-spec XML (searchable inventory; no CNA tool reads it) . . . . . . . . :
                                                                              v
 SIBLINGS (separate checkouts next to cna/)                        +------------------+
   sharp-runtime (branch next) ========== every build ===========> |       CNA        |
   meta-gl ===> easy-gl - - - - - - five GL identities - - - - - > |  snapshot        |
   free-api ===> free-direct - - - - FREEDIRECT only   - - - - - > |  009d40f5        |
                                                                   +------------------+
                                                                              |
 CONSUMERS (pin their own CNA revision)                                       v
   cna-samples (Ms-PL)   cna-examples (MIT)   cna-template   games, apps, language bindings

 ===> required     - - > only when the matching renderer is selected     ---> evidence input
Figure. CNA at the centre of its ecosystem. At the top, four references feed CNA's verification without being linked: Microsoft's XNA 4.0 XML documentation and DLL metadata feed the representation census, FNA feeds day-to-day behaviour and value diffs, the genuine XNA runtime under Wine and DXVK feeds the pixel oracle, and xna4-spec (dotted) is only a searchable inventory. On the left, sibling libraries feed the build: sharp-runtime is required by every build (double arrow), while meta-gl feeds easy-gl for the five GL identities and free-api feeds free-direct for FREEDIRECT only (each is a build dependency of the sibling it feeds, drawn as a double arrow; the dashed arrows into CNA are the renderer-conditional edges). Below, consumer repositories depend on CNA and pin their own revision. The graph is not an inventory of every repository in the organisations involved.
RepositoryRoleWhen CNA needs itRevision read for this page
sharp-runtimeC++23 implementation of a practical subset of .NET System.*Every build; branch next41b918c9 (2026-09-20)
easy-glToolkit-independent C++ wrapper over OpenGL and OpenGL ES (its README says C++20; its CMake requires cxx_std_23, PUBLIC)Only for OPENGLES2, OPENGLES3, OPENGL33, WEBGL1, WEBGL2deda7a42 (2026-08-22)
meta-glLow-level, type-safe C++23 layer for OpenGL ES 2.0 to 3.2 and desktop GL 3.3+; the foundation of easy-glTransitively, through easy-gl20c8b2dc (2026-09-03)
free-directNarrow, game-driven DirectDraw, DirectSound and DirectPlay subset over SDL3Only for FREEDIRECT934f72ff (2026-07-18)
free-apiMinimal subset of the Win32 API of roughly 1998, over SDL3Transitively, through free-direct53d7a312 (2026-07-18)
xna4-specMachine-readable XML transcription of the XNA 4.0 documentationNever; a reference for human auditsfedc17aa (2026-09-13)
cna-samplesC++ ports of the XNA Game Studio 4.0 sample collectionConsumer4da98a0 (2026-09-20)
cna-examplesOne application that catalogues live demonstrations of every CNA areaConsumerea33c9a2 (2026-09-13)

None of these is vendored into CNA or included as a Git submodule, and CNA's CMake declares no pin or lock file for any of them (only some CI workflows check out an older sharp-runtime commit, see CNA-BUG-199): the revisions in the last column are the ones read for this page, not versions CNA promises to work with. Each sibling is a separately buildable, separately tested project. sharp-runtime in particular presents itself as a foundation for frameworks such as CNA, with CNA as its downstream consumer; sharp-runtime and easy-gl could each serve a project unrelated to XNA.

How the build finds its siblings

The graph above is what CMake does at configure time. The root CMakeLists.txt checks CNA_SHARP_RUNTIME_ROOT (default ../sharp-runtime) before anything else is built and stops with a message that names the missing checkout, says that git submodule update --init will not fetch it, and prints a copy-pasteable git clone fix, rather than failing later with a missing header. cmake/RendererSelection.cmake applies the same pattern to ../easy-gl (only when a GL identity is selected, added once even when several GL identities share a multi-renderer build, and with a reminder that easy-gl needs its own ../meta-gl; unlike the other two messages it names the develop branch but prints no git clone command) and to ../free-direct (only for FREEDIRECT). A plain SDL_RENDERER or VULKAN configure therefore never looks for easy-gl or free-direct. The clone URLs in the sharp-runtime and free-direct messages still name the older openeggbert organisation; for the repositories that moved to libcna, GitHub redirects them.

The free-direct chain is three levels deep: free-direct's own CMake adds ../free-api, and both resolve SDL3::SDL3, SDL3_image and SDL3_mixer from the targets CNA has already created from its vendored SDL, which is why the whole chain shares one SDL3 build and CNA passes no extra SDL flag. The same comment in RendererSelection.cmake names two other consumers of free-direct, the free-eggbert and planetblupi game ports, so the chain is reused infrastructure rather than machinery built only for one renderer. Branches, clone commands and the configure messages to grep for are on Building CNA: sibling checkouts and Debugging: configure failures.

sharp-runtime: the .NET vocabulary, once

A C++ reimplementation of XNA can either invent ad-hoc substitutes for byte, TimeSpan, events, IDisposable and Object.GetType() inside each ported file, or build the .NET-shaped foundation once as its own project. CNA's instruction file (CLAUDE.md) chooses the second: anything CNA needs from .NET (an alias, a class, an interface, an exception type) is added to sharp-runtime first, with the correct final name and namespace and only as much as CNA needs, and is never inlined into CNA headers as a raw C++ type.

At 41b918c9 sharp-runtime describes itself as a practical subset of System.* for native ports "without attempting to implement a CLR, JIT, garbage collector, or the complete .NET platform". Its scope has grown well past a minimal floor: its README lists collections, text, regular expressions, JSON, XML, streams, compression, networking and HTTP, tasks and channels, numerics and non-encryption cryptography, organised as independently selectable CMake components: the generated docs/ComponentCatalog.md at the same revision lists 47 registered components over 44 physical modules, plus the All aggregate (the README's own figure, 41, is out of date). CNA consumes a narrow closure of them through cmake/SharpRuntimeConsumption.cmake, which also detects whether the checkout is the modular or the older monolithic shape. Its porting status is tracked per .NET type in a SQLite database, plan.sqlite3, which is committed at that revision even though the repository's ignore rules also match it; the database lists 16,207 types, of which 1,087 are ported, 140 ignore and 14,980 ignored, with no rows left in an undecided state. Tutorial 89 walks through the library from a game's point of view.

easy-gl and meta-gl: OpenGL without a windowing opinion

The EasyGL family (five public identities sharing one CNA implementation factory) sits on easy-gl, whose defining choice is what it refuses to own. At deda7a42 its README says the host application owns window creation, GL context creation and activation, event processing, swap and present, and supplies a GetProcAddress callback; easy-gl owns everything below that: shaders and programs, buffers, vertex arrays, textures, framebuffers, draw calls and capability detection. Calling code gates features that exist only on desktop GL away from GL ES through easygl::Device::supports(Feature) and require(Feature). easy-gl itself adds ../meta-gl and links meta-gl::meta-gl, the typed function-loading layer beneath it, which likewise creates no window or context.

easy-gl's README calls its own scope a compact, evolving slice exercised by a hello-triangle-sdl example and two smoke-test targets (easy-gl-smoke-tests, easy-gl-resource-smoke-tests), although its tests/CMakeLists.txt registers four test executables (adding easy-gl-context-lifecycle-tests and easy-gl-webgl-tests); CNA's EasyGL renderer has grown far beyond that slice on top of it. In CNA the GL context comes from the selected platform (SDL3, SDL2, X11, Wayland or Win32), which is how one easy-gl serves every host. See EasyGL internals and Tutorial 90.

free-direct and free-api: deliberately narrow

Where easy-gl is general-purpose, free-direct is the opposite kind of project. At 934f72ff its README (MIT licence, C++20) scopes it to a narrow, game-driven subset of 2D-era DirectX, enough to run specific legacy games such as Speedy Blupi without their original operating-system dependencies, and states its non-goals as plainly as its goals: no full DirectX compatibility, no hardware-accurate emulation, no Direct3D pipeline, and no expansion of APIs the target games do not call. DirectDraw is the implementation focus; DirectSound plays static PCM buffers through SDL3; DirectPlay has real session, player and message state over a default in-process loopback transport, with an optional ENet transport (FREE_DIRECT_ENABLE_ENET) for real UDP hosting and LAN discovery. It is FreeDirect-to-FreeDirect only and never compatible with Microsoft's DirectPlay wire protocol.

Its tests are split by transport on purpose: the default ctest run exercises the loopback transport's synchronous semantics, and the ENet tests are selected with the enet label; the README warns that running the unfiltered suite against an ENet-enabled build fails one loopback-oriented DirectPlay test by design, not as a regression. free-api, beneath it, is an experimental minimal Win32 API subset on SDL3. In CNA the pair backs only the 2D-only FREEDIRECT renderer (see 2D-only renderers).

xna4-spec and the representation census

A reimplementation drifts in two ways: between what its documents claim and what its code does, and between what it believes the original API was and what the original actually specified. xna4-spec was built against the second failure. At fedc17aa it holds 544 XML type files in 19 namespace directories (its README's summary line says 550 types, which the index file does not bear out), converted from Microsoft's XNA 4.0 reference pages, with members and their original descriptions; its stated purpose includes "auditing C++ reimplementations of XNA 4.0".

CNA's code, CMake and workflows do not reference xna4-spec at this snapshot. The census that produces 331/331 types and 3,627/3,627 members, tools/audit_xna_runtime_surface.py, reads Microsoft's own XML documentation and DLL metadata instead, and a transcription made from web pages is a weaker source than those. Use xna4-spec as a searchable offline inventory, with normalisation and an independent check before trusting a single row. The alpha.1 release notes quote a different, older measurement, 227 of 245 public FNA types present, whose denominator came from FNA's type list rather than from any Microsoft reference; it is a historical presence snapshot and not comparable with the census.

Two kinds of consumer proof

Two repositories exist to give CNA real code to run, and they answer different questions.

cna-samples ports Microsoft's XNA Game Studio 4.0 sample collection to C++ and is licensed Ms-PL to match its Microsoft-derived origin. Its question is does CNA run real, historical XNA code? At 4da98a0 its plan inventories 153 upstream sample directories, of which 87 are marked complete (a native run plus a real-browser WebGL2 run), 40 are published playable, 49 await owner decisions, 14 are documented non-ports, two have complete native ports and WebGL2 bundles whose real-browser gate is still pending, and one (the Racing Game) is tracked separately. Those are catalogue statuses for CNA's next branch on that date, not results for this snapshot; the older explanation that samples were blocked by HLSL effects no longer holds (see Is it actually usable?).

cna-examples is original, MIT-licensed work (deliberately not a port of Microsoft material, so it can carry a permissive licence). Inspired by the JavaFX Ensemble sample browser, it is one cross-platform application in which a reader picks an area, then a category, then a demo. Its question is can every CNA area be shown working inside one program? At ea33c9a2 its README reports 13 areas, 79 categories and 249 demo screens, each calling real Microsoft::Xna::Framework or CNA::* APIs, rendered on both OPENGLES3 and SDL_RENDERER (the 3D area is gated off on the 2D-only renderer). Both repositories are evidence for the CNA revision they were built against.

Other repositories around CNA

Many more repositories surround CNA: a starter project (cna-template, whose lock file pins an older CNA), cna-extended (a C++ port of MonoGame.Extended on CNA), cna-lab (home of the CNA Craft port), the language bindings (cna-cs, cna-java, cna-ts, cna-python, cna-rust, cna-swift, cna-go, cna-ruby) that target an older C ABI, and games built on the stack, from the free-direct consumers named above to mobile-eggbert, a C++ port of the 2013 Windows Phone Speedy Blupi on an early CNA revision. They are useful integration evidence, but each is evidence only for its own pinned revision and host, never for this snapshot by default. The site's showcase and demos list the public ones with their revisions.

The same subject is explained at several altitudes. These are the neighbouring pages at each one.