From bcca97a84878a4ba050274b969536a2946920ddb Mon Sep 17 00:00:00 2001 From: MarekZegare4 Date: Mon, 29 Jun 2026 18:20:47 +0200 Subject: [PATCH] docs(companion): document the screen-fragment single-TU contract The ui-new/*.h screens are header fragments compiled only as part of UITask.cpp, in include order. Two implicit rules a contributor can trip on: include order (a static inline helper / shared scratch is visible only to later fragments) and single-TU-only (some fragments define external-linkage symbols at file scope, e.g. NearbyScreen::FILTER_LABELS, so reusing one from a second .cpp is a duplicate-symbol link error). Spell both out in a contract comment at the inclusion block, and raise the single-TU note to a callout in the framework guide. Comments only. Co-Authored-By: Claude Opus 4.8 --- docs/design/solo_ui_framework.md | 7 +++++++ examples/companion_radio/ui-new/UITask.cpp | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/docs/design/solo_ui_framework.md b/docs/design/solo_ui_framework.md index 41c8c3d2..a684e019 100644 --- a/docs/design/solo_ui_framework.md +++ b/docs/design/solo_ui_framework.md @@ -14,6 +14,13 @@ into one translation unit (`ui-new/UITask.cpp`) — so a `static inline` helper an earlier header is visible to later ones. Header-include order in `UITask.cpp` therefore matters; new screens go near the others. +> **Single-TU only.** These fragments compile *only* as part of `UITask.cpp`. +> Some define external-linkage symbols at file scope (e.g. +> `NearbyScreen::FILTER_LABELS`), so including a fragment from a second `.cpp` +> is a duplicate-symbol link error. Anything genuinely shared across TUs must +> live in a real header (`icons.h`, `GeoUtils.h`, `DisplayDriver.h`), not a +> screen fragment. + --- ## 1. The screen model diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 7ad34643..ac666167 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -116,6 +116,17 @@ public: static const int QUICK_MSGS_MAX = 10; +// ── Screen fragments — included into THIS translation unit only ─────────────── +// These headers are not standalone: they are compiled solely as part of +// UITask.cpp, in the order below. Two consequences a new screen must respect: +// • Order matters. A `static inline` helper (drawList, msgReplyBody, geo::…) +// or a shared scratch buffer (FullscreenMsgView's s_wrap_*) is only visible +// to fragments included *after* the one that defines it. Add new screens +// after their dependencies. +// • Single-TU only. Some fragments define external-linkage symbols at file +// scope (e.g. NearbyScreen::FILTER_LABELS), so including any of them from a +// second .cpp is a duplicate-symbol link error. Keep them UITask-internal; +// anything genuinely shareable belongs in a real header (icons.h, GeoUtils.h). #include "FullscreenMsgView.h" #include "SensorPlaceholders.h" #include "SettingsScreen.h"