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
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.txtmakes three decisions before the per-family loop, whileCNA_GRAPHICS_RENDERERstill names the default:- common/d3d is entered only when the default is DIRECTX11 or DIRECTX12. Both families link
cna_renderer_d3dcommonPUBLIC 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 theD3Dsources and a -lcna_renderer_d3dcommonthe 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_SOURCESandcna_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 andCNA_RENDERER_TARGETSname it. RendererCombinations.cmakerefuses 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 ormacOS-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
modules/renderers/CMakeLists.txt— the pre-loop add_subdirectory conditions for common/d3d, software and metal, and the family loopmodules/renderers/directx11/CMakeLists.txt— target_link_libraries(... PUBLIC cna_renderer_d3dcommon)modules/renderers/software/CMakeLists.txt— the GDI branch that publishes CNA_GDI_SOFTWARE_SOURCESmodules/renderers/metal/CMakeLists.txt— renderer target created only when the default is METALcmake/RendererCombinations.cmake— cna_validate_renderer_combination and _cna_renderer_platformmodules/renderers/directx12/CMakeLists.txt— links cna_renderer_d3dcommon PUBLICmodules/renderers/common/d3d/CMakeLists.txt— defines cna_renderer_d3dcommonmodules/renderers/gdi/CMakeLists.txt— cna_add_renderer(CNA_GDI_SOFTWARE_SOURCES) and cna_renderer_software_headers
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.
Related pages
The same subject is explained at several altitudes. These are the neighbouring pages at each one.
- User guide
- Runtime renderer selection: combinations
- Architecture
- Module graph: renderer composition
- Known issues
- Bug index