db41258d16
Ersetzt das Geruest (counter/notebook) durch ein echtes Beispiel und teilt es in zwei eigenstaendige Projekte, wie P1204R0 es fuer Bibliothek plus Programm verlangt. libpda: textfile (C, Datei-I/O und Feld-Escaping), calculator (Recursive-Descent-Parser mit std::expected), contact, editor, explorer. Exportiert pda::pda ueber install(EXPORT) und ist per find_package(pda) benutzbar. pda: Shell ohne Ein-/Ausgabe (execute() gibt Text zurueck, deshalb ohne Terminal testbar), REPL und Stapelbetrieb in main.cpp. examples/consumer und tools/check-install.sh pruefen die Export-Kette Ende-zu-Ende: installieren, dann ein fremdes Projekt dagegen bauen. docs/CMAKE.md erklaert das Target-Modell, PUBLIC/PRIVATE/INTERFACE, Generator-Ausdruecke, install/export und Symbolsichtbarkeit an diesem Projekt. 71 Tests gruen unter Homebrew-clang 22, Apple clang und GCC 16, statisch und shared, mit und ohne ASan/UBSan. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
68 lines
2.8 KiB
Markdown
68 lines
2.8 KiB
Markdown
# ADR 0002 — Aufteilung in libpda und pda
|
|
|
|
- Status: akzeptiert
|
|
- Datum: 2026-08-30
|
|
|
|
## Kontext
|
|
|
|
Das Projekt soll einen kleinen PDA umsetzen (Kontakte, Rechner, Notizen,
|
|
Dateiexplorer) und dabei ausdrücklich als **Bibliothek** benutzbar sein — man
|
|
soll damit eigene Sachen bauen können.
|
|
|
|
P1204R0 sagt dazu: „If a project consists of a library and an executable, then
|
|
they should be split into separate projects."
|
|
|
|
Die naheliegende Alternative wäre ein Projekt mit einem `pda_core`-Target und
|
|
einer Executable daneben — so machen es `mydb` und `cxx_scaffold_cli`.
|
|
|
|
## Entscheidung
|
|
|
|
Zwei eigenständige Projekte unter einem Superprojekt:
|
|
|
|
- `libpda/` mit eigenem `project(libpda)`, exportiert `pda::pda`
|
|
- `pda/` mit eigenem `project(pda)`, linkt `pda::pda`
|
|
|
|
Beide sind einzeln konfigurierbar. `pda/CMakeLists.txt` benutzt im
|
|
Alleinbetrieb `find_package(pda REQUIRED)`.
|
|
|
|
## Konsequenzen
|
|
|
|
Die Bibliothek ist nachweislich unabhängig: `cmake -S libpda -B build/nur-lib`
|
|
baut und testet sie ohne die Anwendung (47 der 71 Tests).
|
|
|
|
Die Anwendung ist damit gleichzeitig der Integrationstest für den
|
|
Export-Mechanismus. Was sie im Alleinbetrieb tut, tut auch jedes fremde
|
|
Projekt.
|
|
|
|
`examples/consumer/` und `tools/check-install.sh` machen das explizit: das
|
|
Skript installiert `libpda` in ein temporäres Präfix und baut ein fremdes
|
|
Programm dagegen. Genau diese Kette fängt den häufigsten Verteilungsfehler —
|
|
ein `target_include_directories` ohne `BUILD_INTERFACE`/`INSTALL_INTERFACE`
|
|
zeigt beim Benutzer ins Leere und fällt im eigenen Build nie auf.
|
|
|
|
Der Preis ist eine Ebene mehr im Pfad (`libpda/libpda/contact.hpp`) und der
|
|
`PROJECT_IS_TOP_LEVEL`-Block in beiden Teilprojekten. Beides ist der Preis
|
|
dafür, dass „Bibliothek" hier nicht nur ein Wort ist.
|
|
|
|
## Nebenentscheidungen
|
|
|
|
**Ein Namespace für beide Projekte** (`namespace pda`), unterschieden über den
|
|
Include-Pfad — so wie `libhello`/`hello` in P1204R0. Das `lib`-Präfix steht im
|
|
Projekt- und Verzeichnisnamen, nicht im Namespace.
|
|
|
|
**Die C-Schicht ist echt, nicht dekorativ.** `textfile.c` macht Datei-I/O und
|
|
Feld-Escaping — die Stelle, an der Besitzverhältnisse und rohe Puffer
|
|
sichtbar sind. Alles darüber ist C++ und verpackt das in RAII. Die Naht ist in
|
|
`contact.cpp` zu sehen: `unique_ptr` mit eigenem Deleter um die `char*`, die
|
|
`textfile_escape` liefert.
|
|
|
|
**`std::expected` statt Exceptions** für Benutzerfehler (Tippfehler im
|
|
Ausdruck, fehlende Datei). Ein Parser-Fehler ist der Normalfall dieser
|
|
Funktionen, kein Ausnahmezustand. Exceptions bleiben für das, was wirklich
|
|
nicht vorgesehen ist.
|
|
|
|
**Die Shell kennt keine Ein-/Ausgabe.** `Shell::execute()` bekommt eine Zeile
|
|
und gibt Text zurück; wer ihn anzeigt, ist ihre Sache nicht. Deshalb braucht
|
|
kein einziger der Shell-Tests ein Terminal, und eine GUI ließe sich ohne
|
|
Änderung an `shell.cpp` davorsetzen.
|