Guard the add_test shadow on being top-level again

CMake chains command overrides one level deep: a second override rebinds
_add_test to the first and the builtin becomes unreachable to everyone. So two
projects in one tree cannot both shadow add_test, and akbasic has to shadow it
first for libakerror and libakstdlib -- which left its own registrations
recursing to CMake's depth limit.

The unconditional shadow arrived with the vendored-dependency fix in 18399f2.
That half stays; only the guard comes back.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 13:11:51 -04:00
parent 76c6240280
commit 5dfa49482c
3 changed files with 102 additions and 29 deletions

35
TODO.md
View File

@@ -1278,6 +1278,41 @@ Every size below is measured, not estimated.
`amdgpu_dri.so`; running it headless produces none, and headless is what the
suites are written for anyway.
### Found while embedding libakgl in a consumer
40. ~~**Shadowing `add_test()` unconditionally broke every embedding consumer.**~~ **Fixed in
the same release it was introduced in**, and worth keeping because the CMake behaviour
behind it is not obvious and will catch the next person.
18399f2 moved the vendored-dependency block out from behind
`if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)` — which was the point of that
commit — and took the `add_test()`/`set_tests_properties()` override out with it. The
override's own comment claimed "an embedding consumer's `add_test()` still reaches CTest".
It does not, and cannot.
**CMake chains command overrides exactly one level deep.** Overriding `add_test` makes the
builtin available as `_add_test`; overriding it a *second* time rebinds `_add_test` to the
*first* override and the builtin becomes unreachable to everybody, permanently — there is
no `__add_test`. Verified directly rather than inferred from the documentation:
```cmake
function(add_test) _add_test(${ARGV}) endfunction() # _add_test -> builtin
function(add_test) _add_test(${ARGV}) endfunction() # _add_test -> the first override
if(COMMAND __add_test) ... endif() # absent
```
So two projects in one tree cannot both shadow it. `akbasic` shadows it first — it has to,
for `libakerror` and `libakstdlib`, which register their tests unconditionally — and its own
registrations then recursed until CMake stopped at "Maximum recursion depth of 1000
exceeded". A consumer had no way to work around it: once the builtin is gone it is gone for
that project too.
**Fix:** the override is guarded on being top-level again, exactly as it was before 18399f2
and exactly as `libakstdlib` guards its own. The vendored-dependency block stays
unconditional, which is what that commit was actually for. An embedded `libakgl` leaves
`add_test` alone and lets its consumer suppress what it does not want — machinery the
consumer has to have anyway.
## Build notes
The vendored SDL satellite libraries are built into per-project subdirectories