Der Einzeldatei-Modus (CppFileRunConfiguration) war der zaeheste Teil: er uebersetzt ohne -I und -std und sieht wie ein Projektfehler aus. Ausserdem als beobachtete Tatsache statt Theorie: CLions 'Reset Cache and Reload Project' hat die CMakeCache.txt in build/debug geloescht, weil die angelegten Preset-Profile dorthin zeigen -- auch deaktiviert. ctest lief danach weiter, nur cmake --build brach ab. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
playground
Ein kleiner PDA — Kontakte, Taschenrechner, Notizen, Dateiexplorer — als Übungsprojekt für die Bau- und Projektstruktur, die dahintersteht.
Aufgeteilt nach P1204R0 „Canonical Project Structure" in zwei eigenständige Projekte:
playground/ Superprojekt, kein eigener Quellcode
├── libpda/ die Bibliothek -> libpda.a
│ ├── libpda/
│ │ ├── textfile.h/.c C: Datei-I/O und Feld-Escaping
│ │ ├── calculator.hpp/.cpp Ausdrucksparser (Recursive Descent)
│ │ ├── contact.hpp/.cpp Kontaktverwaltung mit Persistenz
│ │ ├── editor.hpp/.cpp zeilenorientierter Textpuffer
│ │ ├── explorer.hpp/.cpp Verzeichnisnavigation
│ │ ├── *.test.c/.cpp Unit-Tests, direkt neben dem Modul
│ │ └── details/ Implementation Details
│ └── tests/basics/ Integrationstest, nur öffentliche API
├── pda/ die Anwendung -> bin/pda
│ ├── pda/shell.hpp/.cpp Kommandoverarbeitung, ohne Ein-/Ausgabe
│ ├── pda/main.cpp REPL und Stapelbetrieb
│ └── tests/session/ Integrationstest einer ganzen Sitzung
├── examples/consumer/ fremdes Projekt, benutzt find_package(pda)
├── cmake/ ProjectDefaults, Warnings, Sanitizers, Config-Vorlage
├── third_party/ vendortes Unity + doctest, nie editieren
├── tools/check-install.sh prüft die Export-Kette Ende-zu-Ende
└── docs/ CMAKE.md, CONVENTIONS.md, ADRs
Warum getrennte Projekte: P1204R0 verlangt es, und der praktische Grund ist, dass die Bibliothek ohne die Anwendung baubar, testbar und installierbar sein muss — sonst ist sie keine Bibliothek, sondern ein Unterverzeichnis.
Bauen
cmake --preset debug
cmake --build --preset debug
ctest --preset debug
./build/debug/bin/pda
Presets: debug, release, asan-ubsan, apple-clang, homebrew-gcc,
linux-gcc.
Benutzen
Interaktiv:
$ pda
pda 0.1.0 -- 'help' zeigt die Kommandos, 'quit' beendet.
playground> contact add "Anna Schmidt" 0151 anna@example.org meine Schwester
'Anna Schmidt' angelegt (1 Kontakte)
playground> calc (2+3)*4 - 10/2
15
playground> note add Anna anrufen
Zeile 1 angelegt
playground> contact save kontakte.tsv
1 Kontakte nach kontakte.tsv geschrieben
Im Stapelbetrieb — ein Kommando, dann Ende:
pda calc "2^10" # 1024
pda contact list
Der Exit-Code ist 1, wenn das Kommando scheitert. Fehler gehen nach stderr.
Als Bibliothek benutzen
cmake -S libpda -B build/lib -DCMAKE_INSTALL_PREFIX=/pfad
cmake --build build/lib && cmake --install build/lib
Dann im eigenen Projekt:
find_package(pda 0.1 REQUIRED)
target_link_libraries(mein_programm PRIVATE pda::pda)
#include <libpda/calculator.hpp>
const auto value = pda::evaluate("(1 + 2) * 3 ^ 2");
if (value) std::println("{}", *value);
Ein vollständiges Beispiel steht in examples/consumer/;
tools/check-install.sh baut es gegen eine frisch installierte Bibliothek und
ist damit der Test für den Export-Mechanismus.
Dokumentation
- docs/CMAKE.md — CMake an diesem Projekt erklärt:
Target-Modell,
PUBLIC/PRIVATE/INTERFACE, Generator-Ausdrücke, install/export, Symbolsichtbarkeit, „wann mache ich was?" - docs/CONVENTIONS.md — Stil- und Strukturregeln
- docs/adr/ — Architekturentscheidungen mit Begründung
Stand
71 Tests (Unity für C, doctest für C++, zwei Integrationstreiber ohne Framework). Grün unter Homebrew-clang 22, Apple clang und GCC 16, jeweils statisch und als Shared Library, mit und ohne ASan/UBSan.