Für die reine Bau-Anleitung siehe Installation & Build. Diese Seite richtet sich an alle, die selbst an NUIStudio weiterentwickeln möchten.
Jedes Quellmodul unter src/ hat ein eigenes Test-Ziel unter tests/, mit demselben thematischen Zuschnitt:
| Quellmodul | Testziel | Braucht GPU? |
|---|---|---|
Core |
NuiCoreTests |
Nein |
Nui/Parser |
NuiParserTests |
Nein |
Nui/Serializer |
NuiSerializerTests |
Nein |
Nui/Text |
NuiTextTests |
Nein — reine Layout-/Parsing-Mathematik |
Renderer/DX12 |
RendererResourceTests |
Ja (WARP) |
Renderer/Text |
RendererTextTests |
Ja (WARP) |
Editor/Canvas |
EditorCanvasTests |
Ja (WARP) |
Undo |
UndoRedoTests |
Nein |
| — | EditorShellIntegrationTests |
Ja (WARP) — kompletter Öffnen/Bearbeiten/Speichern-Zyklus |
Jedes GPU-abhängige Testziel initialisiert sein GraphicsDevice mit einem Software-Fallback-Gerät statt einer echten Grafikkarte:
GraphicsDevice device;
REQUIRE(device.Initialize(/*forceWarp=*/true));
Dadurch läuft die komplette Testsuite deterministisch auf jeder Windows-Maschine und in jeder CI-Umgebung — ganz ohne echte GPU, ohne Treiber-Abhängigkeit, ohne Unterschiede zwischen Entwicklungsmaschinen. Für Module, die zusätzlich echte Bild- oder Font-Dateien brauchen (z. B. RendererResourceTests, RendererTextTests), werden diese synthetisch zur Testlaufzeit erzeugt (z. B. eine winzige, garantiert gültige TGA-Datei über DirectXTex) oder aus einer echten, auf jedem Windows-System vorhandenen Systemdatei kopiert (z. B. C:\Windows\Fonts\arial.ttf für Font-Lade-Tests) — nie aus dem externen, nicht mitgelieferten Spiel-Asset-Korpus. Das hält die Testsuite vollständig eigenständig lauffähig.
Wichtige Einschränkung, ehrlich benannt: WARP-Tests bestätigen, dass eine Rendering-Pipeline fehlerfrei durchläuft (keine D3D12-Validierungsfehler, plausible Geometrie/Draw-Call-Zahlen) — sie prüfen nicht pixelgenau, ob das Ergebnis auch tatsächlich wie beabsichtigt aussieht. Echte visuelle Bildtreue bleibt ein manueller Prüfschritt, unterstützt durch NuiBatchValidate und die Render-Dump-Diagnose.
Die Struktur ist immer dieselbe, egal ob reines CPU-Modul oder GPU-nahes Modul:
src/<Bereich>/<Modulname>/
├── CMakeLists.txt
├── include/nui/<namensraum>/<Header>.h
└── src/<Implementierung>.cpp
CMakeLists.txt folgt immer demselben Muster:
add_library(<zielname> STATIC
include/nui/<namensraum>/<Header>.h
src/<Implementierung>.cpp
)
target_include_directories(<zielname> PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
)
target_link_libraries(<zielname> PUBLIC
nui_core
# weitere, nur wirklich benötigte Abhängigkeiten
)
nuistudio_apply_warnings(<zielname>)
set_target_properties(<zielname> PROPERTIES FOLDER "NUIStudio")
Neu hinzugefügt werden muss das Modul außerdem in src/CMakeLists.txt (per add_subdirectory(...), vor jedem Modul, das davon abhängt — die Reihenfolge folgt strikt der Abhängigkeitsrichtung) und, falls ein Testziel existiert, in tests/CMakeLists.txt.
Diese Konventionen ziehen sich konsequent durch den gesamten Quellcode und sollten bei jedem Beitrag eingehalten werden:
KUIControl.cpp:902-910) — nicht "das Original macht vermutlich..."..clang-tidy im Projekt-Wurzelverzeichnis konfiguriert einen bewusst schmalen Check-Satz (bugprone-*, ausgewählte cppcoreguidelines-*, clang-analyzer-cplusplus.NewDelete*, performance-*, modernize-use-override) statt der vollen cppcoreguidelines-/clang-analyzer--Sets — dieses Projekt nutzt an vielen Stellen bewusst rohe D3D12-Handles (D3D12_CPU_DESCRIPTOR_HANDLE u. ä., einfache Structs statt besitzender Zeiger) und COM-ComPtr-Referenzzählung, die generische Ownership-Heuristiken sonst massenhaft falsch-positiv melden würden. Gescopt auf echte Lebenszeit-/Ownership-Fehlerklassen, ohne dieses Rauschen.
Da die Standard-Presets den Visual-Studio-Generator nutzen (kein compile_commands.json), braucht ein lokaler Durchlauf eine separate Ninja-Konfiguration:
cmake -S . -B build/clang-tidy -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake --build build/clang-tidy # einmal komplett bauen — clang-tidy braucht die generierten Abhängigkeits-Dateien
clang-tidy -p build/clang-tidy --extra-arg=-Wno-unused-command-line-argument --extra-arg=-D_XM_NO_INTRINSICS_ <datei.cpp>
Die beiden --extra-arg-Flags sind reine Werkzeug-Kompatibilität, keine Verhaltensänderung: /MP kennt der clang-cl-Treiber nicht (von /WX sonst fälschlich zum Fehler eskaliert), und DirectXMath.h versucht unter Clang auf <cpuid.h> zuzugreifen — ein Unix-typischer Header, den dieser Windows-LLVM-Toolchain-Pfad nicht mitbringt; _XM_NO_INTRINSICS_ umgeht nur diesen einen Include-Zweig, betrifft aber nie den echten MSVC-Build (cl.exe nimmt diesen Zweig ohnehin nie).
Letzter vollständiger Durchlauf über alle 58 src/**/*.cpp-Dateien: genau ein echter Fund — WinHttpHandle (Update-Modul) deklarierte einen Destruktor und gelöschte Kopieroperationen, aber keine expliziten Move-Operationen (cppcoreguidelines-special-member-functions). Behoben durch explizit gelöschte Move-Konstruktor/-Zuweisung (die Klasse wird ausschließlich als lokaler RAII-Guard verwendet, nie verschoben — das macht nur explizit, was durch die bereits gelöschten Kopieroperationen ohnehin schon galt). Jede andere gemeldete Warnung lag in Drittanbieter-Headern (ImGui, DirectXTex, Catch2, …) und wurde durch HeaderFilterRegex: 'src/.*' korrekt unterdrückt.