Repository navigation
docs(skills): lean, targeted builds in /pr-review and /pr-land - #6215
Conversation
…inciple VIII. Both skills told the agent to build the PR head, and the obvious way to do that builds the default `all` target: several hundred test executables, most linking a large slice of the app, each with its own debug info. A two-PR review left ~170 GB of build trees behind to run about twenty tests. Both now build `AetherSDR` plus the tests the diff selects (added/modified, named in the body, or compiling a touched file per tests/tests.cmake), run ctest with a matching -R filter, and keep a full-tree build for CMake or link-contract changes. The pr-review merge-base comparison builds the same targets. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The review/land build recipe now configures AETHER_SHARED_CORE=ON (the sanitizer lane's link mode) and -g1 debug info on Linux/macOS. Measured on main with Qt 6.12: AetherSDR plus three tests is a 1.3 GB tree instead of 84 GB for the full RelWithDebInfo build; the app binary drops from 832 MB to 144 MB and radio_setup_label_theme_token_test from 397 MB to 18 MB. The three tests pass. The skill names the caveats: the app links the core dynamically, which is not the shipped shape, and WDSP-direct tests need a static build. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Issue fit
No linked issue, and none is required: GOVERNANCE.md:115 lists "Documentation additions and corrections" under What does NOT require an RFC, and this changes only skill prose. Reviewed against the PR's own stated intent — replace the implicit full-tree all build in /pr-review and /pr-land with a lean, named-target build — and it delivers exactly that. The body's measurement table is unusually good for a docs PR; most of what I checked below was checking it, not the prose.
One note on the body: the "Caveats, stated in the skill" bullet about WDSP is wrong in the same way the skill text is (finding 1), so the error is in both places and the body bullet needs the same correction.
Scope
| File | What it changes | Claimed by title/body? | Verdict |
|---|---|---|---|
.claude/skills/pr-review/SKILL.md |
Adds the "Build only what you run" block (457-489); rewords the merge-base rule at 500-502 to build the same targets rather than a clean full tree | Yes — body describes both | In scope |
.claude/skills/pr-land/SKILL.md |
Replaces the full-tree cmake --build build --parallel at 442-452 with the lean configure + named targets, cross-referencing /pr-review step 7 |
Yes — body's "/pr-land step 5" section |
In scope |
Everything in the diff is explained by the stated intent. No source, CMake, CI, or test file is touched — I confirmed the body's "No change to CMakeLists.txt, tests/tests.cmake, CI or release builds" claim against the file list, and it holds. No new public surface, no CHANGELOG.md entry (correct), no deleted guard. The - lines remove only the two superseded build commands.
Blockers
None.
Nits
1. .claude/skills/pr-review/SKILL.md:475-476 — the WDSP caveat inverts its source and prescribes a needless full reconfigure.
A test that calls WDSP directly does not
link against the shared core by design; reconfigure static for that one.
The comment this paraphrases (CMakeLists.txt:156-160) says something different, and gives a different remedy:
A test that calls WDSP directly while linking only aethercore links against
the static core and fails here; go through core/dsp/WdspChannel.h.
Two problems. "Does not link against the shared core by design" reads as a graceful fallback; the mechanism described in CMake is a link failure — WDSP is a PRIVATE dependency (CMakeLists.txt:1616) built with hidden visibility, so its symbols stop at the shared-library boundary. And the sanctioned fix is to route through WdspChannel.h, not to reconfigure the tree static — which costs the full rebuild this PR exists to avoid.
In practice the case does not arise today: both tests that reach WDSP directly already link it explicitly — tests/tests.cmake:1570 (wdsp_allocation_scope_test PRIVATE aether_wdsp Threads::Threads) and :1575 (rtl_receive_pipeline_test PRIVATE aethercore aether_wdsp Qt6::Core). And .github/workflows/sanitizers.yml builds the whole tree (cmake --build build --parallel, line 162) with shared_core: "ON" in both matrix rows (lines 42, 75), with no exclusion for either test. So the entire tree, those two included, builds shared in CI today. Suggested replacement:
finding could depend on link mode. A test that reaches into WDSP while linking
only `aethercore` fails to link under a shared core: WDSP is a PRIVATE
dependency built with hidden visibility, so its symbols stop at the library
boundary. Both such tests in the tree already link `aether_wdsp` explicitly
(`tests/tests.cmake:1570`, `:1575`); on a new one, go through
`core/dsp/WdspChannel.h` or link `aether_wdsp` rather than reconfiguring static.
2. .claude/skills/pr-review/SKILL.md:466 — the anchored -R assumes test name == target name, which is true 568 times out of 569.
ctest --test-dir build -R '^(test_a|test_b)$' --output-on-failure
The recipe reuses one token for both --target and the anchored -R. Across tests/tests.cmake that holds for every registration but one: add_test(NAME settings_browser_dialog COMMAND settings_browser_dialog_test) — building settings_browser_dialog_test and filtering ^settings_browser_dialog_test$ matches nothing. Worth half a sentence that names usually equal targets and that ctest --test-dir build -N resolves it when -R comes back empty, since an empty filter looks like a pass.
3. BUILD-OPTIONS.md:152 and CMakeLists.txt:151 still scope AETHER_SHARED_CORE to "Sanitizer CI only." The option's help string reads "Build libaethercore as a shared library (sanitizer CI only)" and the options table says "Sanitizer CI only, never for releases." This PR makes it the standard local review configuration, which I think is fine — a review build is not a release, and the skill discloses the link-mode caveat honestly. But the option's own documentation now understates where it is used; a line in the BUILD-OPTIONS.md row mentioning local review builds would keep the two in sync. Non-blocking, and arguably a maintainer's call on whether to broaden the sanctioned use in writing.
4. .claude/skills/pr-review/SKILL.md:471-474 — a dangling "then" after the Windows aside. "Both are for Linux and macOS: on Windows, drop the shared core … and the GCC/Clang flags. The app then loads the core as a shared library, which is not how it ships." The antecedent is the shared-core configure two sentences back, but following the Windows sentence it can read as the Windows outcome — which is the opposite of true. Moving the Windows sentence after the link-mode caveat fixes it.
What I tried to break
- "step 7" cross-reference in
/pr-land:444— held. The new block sits atpr-review/SKILL.md:457-489, inside## 7. Code-quality audit(427) and before## 8(511). A stale section number was my first guess here and it is correct. - Invented or wrong compiler flags — held, and this is the strongest thing in the PR. The flag pair is verbatim what CI already uses:
"-DCMAKE_C_FLAGS_RELWITHDEBINFO=-O2 -g1 -DNDEBUG"/CXXappear identically atci.yml:270-271andfull-suite.yml:103-104.RelWithDebInfois canon's own build type (AGENTS.md:189,BUILD-OPTIONS.md:20), so the added-DNDEBUGis not a new hazard — I went looking for tests whose assertions it would silently disable and the exposure is pre-existing to canon, not introduced here. - Multi-target
--target A B C— held. That form needs CMake ≥ 3.15;CMakeLists.txt:1pinscmake_minimum_required(VERSION 3.25), so the central command cannot fail on a floor install. - Windows claim and target name — held.
CMakeLists.txt:153-155ismessage(FATAL_ERROR "AETHER_SHARED_CORE is not supported on Windows"), so "it is a configure error" is exact;add_executable(AetherSDRexists atCMakeLists.txt:1636. - A stale sibling build recipe left behind — held. Grepping both skills for
cmake --build,cmake -S,cmake -Bandctestreturns only the lines this PR added or rewrote; no third place still tells the agent to buildall. - Scale claims — the "several hundred test executables" figure checks out (569
add_testregistrations over 535 unique executables, 651add_executablecalls intests.cmake), and the body's own 397 MB → 18 MB measurement does support "roughly twentyfold." I could not re-run the measurements: I am headless with no build, so the GB figures, the 219 s cold build, and thelddresult are taken on the body's word and not reproduced. - CI — all required checks green on
b2aafd9, includingStatic checksandSanitizer option configures(static-checks.yml:144-153configuresAETHER_SHARED_CORE=ONand asserts alibaethercore.sorule, which is the probe most relevant to this recipe).Analyze (python)iscancelled, not failed. No socket test is added or removed by this PR.
Every finding above is reasoned from reading the checkout at /tmp/aetherclaude/pr-6215 and the CI configuration — none is a runtime observation.
Recommendation
Approve with nits. The recipe is sound, and the two claims I most expected to be wrong — the cross-reference and the flag set — both check out against CI's own configuration rather than against the author's assertion. Finding 1 is the one worth fixing before merge: it is a docs PR whose job is to be followed literally, and that sentence sends a reviewer into a full static reconfigure for a case that no longer exists in the tree. The replacement text is above; findings 2-4 can ride along or be skipped. Thanks for the measurement table — it made this reviewable.
🤖 aethersdr-agent · cost: $4.9302 · model: claude-opus-5
ten9876
left a comment
There was a problem hiding this comment.
Reviewed b2aafd9 against its stated documentation intent; there is no closing issue. Documentation corrections need no RFC under GOVERNANCE.md. Recommendation: Approve with nits, subject to the usual CODEOWNERS/check requirements. No blockers.
| Scope | Change | Claimed? | Verdict |
|---|---|---|---|
.claude/skills/pr-review/SKILL.md |
Lean shared-core configuration, named targets and matching base comparison | Yes | In scope |
.claude/skills/pr-land/SKILL.md |
Uses that recipe for remediation verification | Yes | In scope |
The two commits contain only these skill edits. No runtime, release, CI, test registration, autonomy, or CHANGELOG change is bundled.
Nits
-
.claude/skills/pr-review/SKILL.md:475— the WDSP caveat sends reviewers into an unnecessary static reconfigure.wdsp_allocation_scope_testalready linksaether_wdspdirectly, andrtl_receive_pipeline_testlinks bothaethercoreandaether_wdsp. The failure described in CMake is specifically direct WDSP calls while linking only sharedaethercore; existing direct-call tests already handle it. Replace the sentence with: “Direct WDSP calls cannot rely on shared aethercore exporting its private WDSP dependency. Existing direct-call tests link aether_wdsp explicitly; prefer the WdspChannel seam for a new engine test.” This confirms the earlier bot's substantive caveat finding. -
.claude/skills/pr-review/SKILL.md:466and.claude/skills/pr-land/SKILL.md:446— distinguish executable targets from registered CTest names and fail on an empty filter.settings_browser_dialog_testis the target, butsettings_browser_dialogis its CTest name. I ran the recipe's anchored target-name filter: it printed “No tests were found!!!” and exited 0. Suggested commands:
cmake --build build --parallel --target settings_browser_dialog_test
ctest --test-dir build -R '^settings_browser_dialog$' --no-tests=error --output-on-failureState that the filter uses add_test(NAME ...), which may differ from the build target, and add --no-tests=error to both recipes. This is a robustness nit rather than a workflow-policy violation: canon's mandatory flag rule applies to workflow invocations.
Verification / attacks survived
- Configured the exact head with shared core and the stated
-O2 -g1 -DNDEBUGC/C++ flags; built the three socket-free targets named in the body's measurement:radio_setup_label_theme_token_test,sim_backend_test, andframeless_resizer_test. All three passed with the desktop theme plugin disabled for this sandbox.lddconfirms all three load the same scratchlibaethercore.so. - Checked the Windows configure refusal, CMake's multi-target support, actual core/WDSP link rules, the
/pr-landstep reference and the matching flag recipe in CI. No socket-owning test is introduced or modified. No app or live-radio session was needed for these documentation claims. - This is a focused build, not the full tree or the author's AetherSDR-plus-tests benchmark; I have not reproduced the 84 GB, twentyfold, cold-build timing, or ccache measurements. ASR and RADE were disabled in my local build; those options do not validate their own paths here.
- Required CI build/macOS/Windows/static checks passed on this head. Their runs were created at 21:03 UTC; current main's tip
173c0d485was committed at 21:22:46 UTC, so those greens cover an older integration. The CodeQL Python job was cancelled and its workflow reports failure; this is not an observed source defect in this docs-only diff. - An invocable automated code-review skill was unavailable; manual review and independent checks above were used. The relevant bot claims were checked against the actual head.
Posted as COMMENT because the authenticated reviewer is also this PR's author; GitHub does not permit self-approval.
ten9876
left a comment
There was a problem hiding this comment.
Reviewed b2aafd9 as a pair with #6217 (head 7154f88). Both were merged onto current main 173c0d485, in both orders, and an affected subset was built. Recommendation: approve with nits. No blockers. I'm posting this as COMMENT because the reviewing account is the author.
Issue fit: there is no linked issue, and none is needed: GOVERNANCE.md exempts documentation corrections from the RFC process. The PR does what it says. Both skills now use a lean, shared-core build of named targets instead of all.
Scope
| File | Change | Claimed? | Verdict |
|---|---|---|---|
.claude/skills/pr-review/SKILL.md |
"Build only what you run" block; merge-base rule builds the same targets | Yes | In scope |
.claude/skills/pr-land/SKILL.md |
Step 5 uses the same lean recipe | Yes | In scope |
Everything in the diff is explained by the body. There is no CMake, CI, test or CHANGELOG change.
Pair findings (new; neither earlier review could see these)
1. .claude/skills/pr-review/SKILL.md:479-481 (and pr-land/SKILL.md:447-448): once #6217 lands, the test-selection grep misses the logging consumers. It already misses the settings consumers.
The rule is "the ones whose tests/tests.cmake block compiles a file the PR touches (grep -n 'Touched.cpp' tests/tests.cmake)". These are non-comment hits for the source path, counted on each tree:
| File | main | main + #6217 |
|---|---|---|
LogManager.cpp |
63 | 1 (the add_library(aether_test_log_manager OBJECT …) line) |
AsyncLogWriter.cpp |
65 | 1 |
AppSettings.cpp |
0 (behind ${AETHER_SETTINGS_SOURCES}) |
0 |
Take a PR that touches LogManager.cpp. A reviewer who follows this text literally after #6217 builds none of its 63 consumers. Separately, build.ninja shows that 270 of 626 executables link aethercore, so no grep of tests.cmake sees any consumer of a file compiled into the core. That limit already exists without this PR, but the skill should say so. Suggested replacement for the sentence:
Pick the tests from the diff: the ones the PR adds or modifies, the ones its
body names, and the ones whose `tests/tests.cmake` block compiles a file the
PR touches (`grep -n 'Touched.cpp' tests/tests.cmake`). When the hit is an
`OBJECT` library or a `set(..._SOURCES` list rather than a test, grep again
for that target or variable name. A file compiled into `aethercore` reaches
every test that links it, so no grep finds them all; pick the ones that
exercise the touched code.
Severity is a nit on this PR alone, and the one to fix if #6217 lands.
2. Non-blocking: after #6217, the explicit -g1 flags in the recipe (SKILL.md:461-463) do nothing on GCC/Clang. I confirmed this with a fresh configure of the merged tree and no flags: the cache holds CMAKE_CXX_FLAGS_RELWITHDEBINFO=-O2 -g1 -DNDEBUG. They are harmless, and keeping them keeps the recipe correct on a checkout without #6217. Mentioned only so nobody reads them as load-bearing.
Nits from the earlier reviews, still open at this head (not re-argued)
SKILL.md:475-476: the WDSP sentence still prescribes a static reconfigure. Both direct-WDSP tests already linkaether_wdsp; route new ones throughWdspChannel.h.SKILL.md:466,pr-land/SKILL.md:446:-Rmatches theadd_test(NAME …)name, not the target name (settings_browser_dialog_test→settings_browser_dialog). Add--no-tests=error, because an empty filter exits 0.SKILL.md:472-474: after the Windows sentence, "The app then loads the core as a shared library" reads as if it describes Windows.CMakeLists.txt:151andBUILD-OPTIONS.md:172still describeAETHER_SHARED_COREas "sanitizer CI only". This PR makes it the standard review configuration.
What I tried to break
- Pair merge:
main + #6217 + #6215andmain + #6215 + #6217both merge cleanly and give an identical tree. The twopr-review/SKILL.mdhunks (the step 5 CMake-contract line and the step 7 block) do not overlap, so landing order doesn't matter. - The recipe on the merged tree: I configured exactly as written (shared core,
-g1, plus local mold, ccache and Qt 6.12; ASR and RADE off). I then builtsplit_qsy_settings_test log_manager_filter_rules_test async_log_writer_test theme_manager_test transmit_model_test sim_backend_test. That took 42 s, and the build dir is 428 MB.ctest -R '^(…)$' --no-tests=error: 6/6 passed.ldd build/sim_backend_testresolveslibaethercore.sofrom the build tree. The largest of these test binaries is 10 MB. - A shared core next to #6217's object libraries: from
build.ninja, 77 executables link the new object libraries, and 0 of them also linklibaethercore/libaetherdesktop_support. So 6215's recipe does not create the second-AppSettings-singleton case that #6217's comment warns about. - Not reproduced: the 84 GB full-tree figure and the 219 s / 41 s timings. I did not build
all. - CI: the earliest run on this head was created at 21:02:58Z, before main's tip
173c0d485(21:22:46Z). The green therefore describes an older merge. My clean merge onto current main stands in for it on this docs-only diff.Analyze (python)is cancelled, not failed. - Bridge: not applicable. There is nothing to drive in a skills-text change.
- Test selection follows an OBJECT library or a _SOURCES list to its consumers. After #6217 the logging sources appear once in tests.cmake, and the settings sources were already behind a variable. - Both ctest recipes add --no-tests=error and note that -R matches the add_test name, not the target name. - The WDSP caveat matches CMakeLists.txt: link aether_wdsp or go through WdspChannel.h instead of reconfiguring static. - The link-mode caveat now comes before the Windows sentence. - -g1 is described in BUILD-OPTIONS.md's words and stays explicit, so the recipe does not depend on the build-type default. - AETHER_SHARED_CORE's help string, comment and BUILD-OPTIONS.md row now cover local review builds, not only the sanitizer lane. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ciple VIII. One binary can be registered under several names: deepfist_cw_model_test five times on main, and #6208 adds rtl_capture_worker_slow_device_test on rtl_capture_worker_test's binary. A filter built from the target name runs only one of them, and --no-tests=error cannot notice, because something matched. The selection step now takes the names from `grep -n 'COMMAND <target>' tests/tests.cmake`. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
b5d3c92 to
1fe7804
Compare
…o -g1 (#6214) (#6217) Part of #6214 (settings and logging; the widgets half is left open, see the end). ## Root cause The light tests deliberately avoid linking `aethercore`, so they compile the app sources they need themselves. Three of those sources were listed in dozens of test targets: | Source | Test targets compiling it | |---|---:| | `${AETHER_SETTINGS_SOURCES}` (5 files: `AppSettings`, `SettingsDatabase`, `SettingsPaths`, `SettingsBootstrap`, `SettingsSanitizer`) | 75 | | `src/core/AsyncLogWriter.cpp` | 65 | | `src/core/LogManager.cpp` | 63 | CMake compiles a listed source once per target, and each test's own flags and include dirs differ, so ccache could not merge the copies. That came to about 500 compiles of the same seven files on every full-tree build. ## Fix - **Compile once:** each source is now an OBJECT library compiled once: `aether_test_settings`, `aether_test_log_manager` and `aether_test_async_log_writer` (`tests/tests.cmake`, "Shared objects" at the top). - **One-for-one swap:** every use became a matching `$<TARGET_OBJECTS:...>` line, so each test links exactly the objects it linked before. Nothing else in the 77 blocks changed. - **OBJECT, not STATIC:** this keeps the same semantics as listing the source. Every object is linked, so nothing that matters only through a static initializer can be dropped. It's the same reasoning as the existing `aether_test_wisdom_isolation`. - **Light tests only:** a test linking `aethercore`/`aetherdesktop_support` must not take these. Next to `libaethercore.so` (`AETHER_SHARED_CORE`) that would be a second `AppSettings` singleton. None of the 77 does; I checked every `target_link_libraries` in the file. - **Guard:** a configure check fails if a test compiles one of these from source again. Otherwise a block copied from an older test would quietly bring the recompiles back. - **Docs:** `tests/README.md` and the CMake-contract line in `.claude/skills/pr-review/SKILL.md` describe the new form. That skill file is also touched by #6215, in a different hunk; whichever lands second may need a trivial rebase. ## Evidence Linux, GCC, Qt 6.12.0, static core. `main` at `03dcff47c` and this branch were configured identically in sibling worktrees. Compile-job counts come from `ninja -t commands`, and timings are clean builds with `CCACHE_DISABLE=1`. Primary measurement, at CI's `build` flags: `RelWithDebInfo` with `-O2 -g1 -DNDEBUG` (`ci.yml:263-271`): | | `main` | this PR | |---|---:|---:| | Compile jobs, full tree | 3806 | **3322** (−484) | | Compile jobs, the 77 affected targets | 1015 | **524** (−48%) | | Clean uncached build of those 77 targets | 151 s | **89 s** (−41%) | | Build dir after that build | 0.86 GB | 0.72 GB | At plain `RelWithDebInfo` (full `-g`) the job counts are the same; the build went from 192 s to 116 s (−40%), and the build dir from 3.05 to 2.34 GB. - **Tests:** all 70 tests registered from the 77 affected targets pass on both `main` and this branch at full `-g`, and on this branch again at `-g1` (`ctest -R … --no-tests=error`). The other 7 targets are tools with no registered test. - **Guard mutation:** I swapped one `$<TARGET_OBJECTS:aether_test_log_manager>` back to `src/core/LogManager.cpp`. Configure failed at `tests/tests.cmake:106` with the guard's message. After restoring the file (sha256 identical), configure passed. - **Checks:** `check_test_registration.py --strict`, `check_ci_test_gate.py` and `check_build_options.py` pass. - **Sanitizer configure:** configure passes with `-DAETHERSDR_SANITIZER=address,undefined -DAETHER_SHARED_CORE=ON`. **Not verified locally; CI covers it:** - The Windows and macOS compile of the OBJECT form. AUTOMOC on `LogManager.h` now runs once in the object library instead of per test. - The sanitizer lane *running* these targets. I only configured that lane. The agent automation bridge doesn't apply here: this is a build change with no runtime behaviour to drive. ## Also: RelWithDebInfo defaults to `-g1` on GCC/Clang (`CMakeLists.txt`, after the build-type default) `RelWithDebInfo` is the default build type, and CMake's `-g` gives every binary full DWARF. Measured on `main`: - the `AetherSDR` binary is 832 MB, about 680 MB of it debug info; - 232 test binaries are over 100 MB each; - the clean build of the 77 affected targets is 3.05 GB at `-g` and 0.86 GB at `-g1`. `-g1` keeps line tables and function names, so backtraces and core dumps still symbolize; locals and types need a `Debug` build. CI's Linux `build` leg and `full-suite.yml` already pass `-g1` explicitly. I left those lines alone; they now restate the default. Scope of the change: - **What it replaces:** only CMake's untouched default (`-O2 -g -DNDEBUG`) for GCC/Clang (AppleClang included), and only when `CFLAGS`/`CXXFLAGS` set no debug level. The TSan lane injects `-g3` through `CXXFLAGS`, and `RelWithDebInfo`'s flags come after it on the command line, so a blanket `-g1` would have overridden it. - **What still wins:** an explicit `-DCMAKE_<LANG>_FLAGS_RELWITHDEBINFO`. - **Existing build trees:** a tree configured before this change cached CMake's default `-O2 -g -DNDEBUG`. This change moves it to `-g1` on the next reconfigure, so it rebuilds once after pulling, mostly missing ccache. That is expected, not a regression. - **Whitespace:** the debug-level check accepts a space or a tab before `-g` (`(^|[ \t])-g`), so `CXXFLAGS="-Wall<TAB>-g3"` is left alone too. - **Reconfiguring with a debug level:** the value is cached, so an internal `_AETHER_<LANG>_RWD_G1` records that the project wrote it. If a later reconfigure adds a `-g` to `CMAKE_<LANG>_FLAGS`, CMake's `-O2 -g -DNDEBUG` comes back instead of the cached `-g1` overriding it; drop the `-g` and `-g1` returns. A RelWithDebInfo value anyone else set is never touched. - **What it never touches:** - MSVC flags: the Windows installer's `RelWithDebInfo` is `/Zi`, which never matches. - `Release`, which the Linux AppImage and macOS DMG builds use. - One local path does change: `packaging/macos/build-installer.sh` (the manual `.pkg` script, which no workflow runs) configures `RelWithDebInfo`, so it now builds at `-g1` under AppleClang. - **`BUILD-OPTIONS.md`** gets a "Build type and debug info" section on getting full debug info. Spell it `-g2`, because a value identical to CMake's default can't be told apart from no choice. Configure-only checks, each in a fresh build dir: | Case | `CMAKE_CXX_FLAGS_RELWITHDEBINFO` | |---|---| | Fresh, no options | `-O2 -g1 -DNDEBUG`, and the compile line for `AppSettings.cpp` carries `-O2 -g1` | | No build type given | `-O2 -g1 -DNDEBUG` | | Reconfigure of that tree | stays `-O2 -g1 -DNDEBUG` | | Same tree reconfigured with `-DCMAKE_CXX_FLAGS=-g3` | `-O2 -g -DNDEBUG` (CMake's default restored; compile line `-g3 -g`, as before this PR) | | …then with the flags cleared | `-O2 -g1 -DNDEBUG` again | | Explicit `RelWithDebInfo` value (`-g1` or `-g2`), then `-g3` | unchanged: the value is the user's | | `CFLAGS=-g3 CXXFLAGS=-g3` (TSan shape) | `-O2 -g -DNDEBUG` (untouched) | | Explicit `-O2 -g2 -DNDEBUG` | `-O2 -g2 -DNDEBUG` (wins) | | `CFLAGS`/`CXXFLAGS` = `-Wall<TAB>-g3` | `-O2 -g -DNDEBUG` (untouched) | | `main`-configured tree, reconfigured with this branch | `-O2 -g -DNDEBUG` → `-O2 -g1 -DNDEBUG` | `check_build_options.py --strict` and its self-test pass. FORCE cache sets are outside its catalog, which is why the doc section is prose rather than a table row. ## Not in this PR #6214 also proposed a widgets library (`DragValuePopup` ×40, `FramelessResizer` ×29, `FramelessWindowTitleBar` ×23, `PersistentDialog` ×19). Those tests link differing mixes of `aetherdesktop_support` and Qt modules, so they need the per-target audit this PR did for settings and logging. I left them for a follow-up rather than guessing. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…rinciple VIII. Every check in the test is an assert(), and the calls it exercises sit inside them. RelWithDebInfo and Release define NDEBUG (CMake's default RelWithDebInfo flags, CI's build and TSan lanes, and the lean review build), so there the test compiled to an empty main and passed whatever the registry did. #undef NDEBUG before <assert.h>, which re-reads it on each inclusion. Built at -O2 -g1 -DNDEBUG, with the first assertion inverted on purpose: before: 100% tests passed (the inverted check never ran) after: 0% tests passed, 1 failed; unmodified: 100% passed It is the only test that includes <assert.h> without handling NDEBUG. Found by the automated code-review pass on #6215's recipe. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
/pr-reviewand/pr-landboth tell the agent to build the PR head. The obvious way to do that builds the defaultalltarget, which is the whole tree. This PR changes both skills to configure a lean build and build only the targets the review actually runs.Why: what a full build costs
Measured while reviewing #6195 and #6198. Each head was built on Linux (GCC, Qt 6.12.0,
RelWithDebInfo, static core: the default configuration):all)AetherSDR.debug_*sections and ~137 MB code and dataradio_setup_*_test~397 MB each,weather_radar_loading_test408 MBThe review itself ran about twenty of those tests.
Two causes:
aethercoreabsorbs a full static copy. TheAETHER_SHARED_COREcomment inCMakeLists.txtalready records this ("~200 MB in a Debug ASan build … shared, they average ~13 MB"); the sanitizer lane switched to a shared core for exactly this reason.-gunder RelWithDebInfo makes debug info about 5× the size of the code. That ratio repeats across every binary.What changes
/pr-reviewstep 7, new "Build only what you run" paragraph:tests/tests.cmakeblock compiles a file the PR touches.AETHER_SHARED_COREis a configure error on Windows, and-g1is a GCC/Clang flag.aether_wdspexplicitly or goes throughWdspChannel.h; no static reconfigure is needed.-Rmatches theadd_test(NAME …)name, which can differ from the target name, so both recipes pass--no-tests=error. A filter that matches nothing fails instead of passing silently.deepfist_cw_model_testfive times; test: green the sanitizer lane — scale TIMEOUTs under sanitizers; feed rtl_capture_worker_test in lockstep. Principle VIII. #6208 addsrtl_capture_worker_slow_device_testonrtl_capture_worker_test). A filter built from the target name runs only one, and--no-tests=errorcan't notice, so the names come fromgrep -n 'COMMAND <target>' tests/tests.cmake.OBJECTlibrary or…_SOURCESlist to its consumers. After build: compile shared test sources once, and default RelWithDebInfo to -g1 (#6214) #6217 the logging sources appear once intests.cmake, and files compiled intoaethercorereach every test that links it.ctestreports unbuilt tests as "Not Run". That means the-Rfilter is missing, not that a test failed./pr-landstep 5: the oldcmake --build build --parallel(full tree) becomes the same lean configuration and named targets. The selection also includes the tests covering the findings being fixed.Evidence for the lean recipe
Same machine and toolchain, on
mainat this branch's base. BuiltAetherSDRplusradio_setup_label_theme_token_test,sim_backend_testandframeless_resizer_test:AetherSDRlibaethercore.so, shared by all targets)radio_setup_label_theme_token_testldd build/AetherSDRresolveslibaethercore.sofrom the build tree, so the shared core really is the one in use.ctest -R '^(radio_setup_label_theme_token_test|sim_backend_test|frameless_resizer_test)$': 100% of 3 passed.For reference, a second worktree at the same commit, building the same targets, took 41 s with a 99.4% ccache hit rate (1094/1101). That needs a local ccache setting (
base_dirset andhash_dir=false, so absolute worktree paths don't split the cache key). It is a per-machine choice, so it is not in the skill text.Also: a test that tested nothing under
-DNDEBUGtests/digital_voice_mode_registry_test.cdoes all of its checking inside plainassert(), with the calls under test inside them. RelWithDebInfo and Release defineNDEBUG, so there it compiled to an emptymainand passed whatever the registry did. That covers CMake's default RelWithDebInfo flags, CI's build and TSan lanes, and this PR's recipe; only the Debug (ASan) lane ever ran it.#undef NDEBUGbefore<assert.h>fixes it, since<assert.h>re-readsNDEBUGon each inclusion. Built at-O2 -g1 -DNDEBUG, with the first assertion inverted on purpose:It is the only test that includes
<assert.h>without handlingNDEBUG. The automated code-review pass found it while checking this PR's recipe, and it is folded in here by maintainer decision.Not in this PR
DragValuePopup.cpp×40 and others) remain open in build(tests): factor the app sources tests.cmake recompiles per target into shared test libraries #6214.CMakeLists.txtandBUILD-OPTIONS.mdchange onlyAETHER_SHARED_CORE's help string, comment and table row: it now names local review builds as well as the sanitizer lane.tests/tests.cmake, CI and release builds are untouched, and shipping builds keep the static core.🤖 Generated with Claude Code