CNA-BUG-190: modules/renderers/CMakeLists.txt enters common/d3d, the GDI software sources and the Metal renderer target only when the default identity matches, so a multi-renderer set that lists DIRECTX11, DIRECTX12, GDI or METAL without the matching default passes the combination rules and then cannot build

CNA snapshot 009d40f5  ·  Known Issues › Current bugs  ·  source links pinned to 009d40f5

✓

Evidence basis: source-verified at the pinned commit; inferred from the source (the behaviour was not run); 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. Nothing on this page was executed unless the Evidence section says so.

Three helper directories are entered by testing the default identity instead of set membership, yet the combination rules accept sets such as HEADLESS;DIRECTX11 (or DIRECTX9;DIRECTX11), whose DIRECTX11 family then links an undefined cna_renderer_d3dcommon. A DIRECTX11 or DIRECTX12 default does enter common/d3d for both, so the D3D condition bites only when the default is neither.

Identifier
CNA-BUG-190
Category
Bug
Subsystem
Build & CI
Status
Open
Verified against
CNA 009d40f5 (009d40f5dd085c4e674d3479675fac84b12b3e0a)
Severity
Low (a triage suggestion, not a project priority)
Evidence basis
Inferred (strong): follows from the code, but the behaviour was not run
Tests touching this area
Yes: see Current tests
Affected contract
CNA_GRAPHICS_RENDERERS multi-renderer mode and cna_validate_renderer_combination (cmake/RendererCombinations.cmake): incompatible sets are rejected at configure time with a reason, never left to surface as a build error

Expected behaviour

docs/runtime-renderer-selection.md (Renderer combinations): "Incompatible combinations are rejected at configure time with a reason, never left to surface as a link error." A set that cna_validate_renderer_combination accepts should configure and build.

Actual behaviour at TARGET

  • CMakeLists.txt makes three decisions before the per-family loop, while CNA_GRAPHICS_RENDERER still names the default:
  • common/d3d is entered only when the default is DIRECTX11 or DIRECTX12. Both families link cna_renderer_d3dcommon PUBLIC and their public headers include CNA/Internal/Renderers/D3DCommon/.... With DIRECTX11 or DIRECTX12 listed and a default that is neither (HEADLESS, DIRECTX9, GDI, ...), no such target exists, so CMake treats the name as a plain library: no include directory for the D3D sources and a -lcna_renderer_d3dcommon the linker cannot resolve. A set whose default is DIRECTX11 or DIRECTX12 (for example DIRECTX11;DIRECTX12) does enter common/d3d and is not hit by this condition.
  • software is entered for GDI only when GDI is the default; it is what publishes CNA_GDI_SOFTWARE_SOURCES and cna_renderer_software_headers, so a non-default GDI gets an archive without its CPU-2D sources and an undefined header target.
  • metal is entered once, before the loop (the loop skips it), and creates the renderer archive only inside if(CNA_GRAPHICS_RENDERER STREQUAL "METAL"); a non-default METAL has no archive although the generated registry and CNA_RENDERER_TARGETS name it.
  • RendererCombinations.cmake refuses only PORTABLEGL with a real-GL renderer, GDI with SOFTWARE, and pairs from two different platform partitions; a platform-neutral identity (HEADLESS, SOFTWARE, STUB, SDL_RENDERER, VULKAN, ...) with a Windows-only or macOS-only one passes, and so do two Windows identities such as DIRECTX9;DIRECTX11. Because each helper is keyed to its own default, the only Windows sets that avoid all three conditions are those whose members need no helper other than the one the default enters (for example DIRECTX11;DIRECTX12, or DIRECTX9;DIRECT2D).

Source locations

Evidence

Checked by reading at 009d40f5; not executed - no Windows or macOS multi-renderer tree was configured, so whether the first failure is at generate, compile or link time is inferred, not observed. None of CNA's multi-renderer presets, CI sets or verified combinations contains such a pair. The site's renderer-selection and module-graph pages already state the mechanism as a reading.

Independently reported as CNA-BUG-187 (folded into this entry by the adversarial audit): Before its per-family loop the file adds common/d3d, and the GDI configuration of software, only when the default renderer matches, so a Windows multi-renderer build with DIRECTX11, DIRECTX12 or GDI as a non-default member lacks the targets it links.

Focused reproduction

Illustrative; not run (needs a Windows cross toolchain).

cmake -S . -B build -G Ninja \
  -DCMAKE_TOOLCHAIN_FILE=$PWD/cmake/toolchains/mingw-w64.cmake \
  -DCNA_GRAPHICS_RENDERER=HEADLESS -DCNA_GRAPHICS_RENDERERS="HEADLESS;DIRECTX11"
cmake --build build
# expected: the DIRECTX11 sources cannot find CNA/Internal/Renderers/D3DCommon/*.hpp

Current tests

cmake/Tests/RendererDefaultCase.cmake pins the default-must-be-a-member rule and scripts/check_renderer_combinations.py keeps the rule table in step with the documentation; neither configures a set with a non-default Windows or macOS member.

Regression test

Test set membership (IN_LIST CNA_RENDERER_IDENTITIES) for the three helpers, and add a configure-only cell for HEADLESS;DIRECTX11 and DIRECTX9;DIRECTX11 to a Windows lane (or refuse such sets in cna_validate_renderer_combination if they are not meant to be supported).

Blast radius

Multi-renderer builds that list DIRECTX11, DIRECTX12, GDI or METAL other than as the default. Single-renderer builds and every set in CNA's verified-combinations table are unaffected.

Workaround

Make the Windows or macOS identity the default (CNA_GRAPHICS_RENDERER); with two of them, only one can be the default, so such a set cannot be built today.

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

Known issues
Bug index