Update the dependency table to libakstdlib and libakgl 0.2.0

Both are at 0.2.0 with libakstdlib.so.0.2 and libakgl.so.0.2 sonames. Records
that they have to be bumped as a pair -- libakgl 0.2.0 consumes the libakstdlib
0.2.0 API, so a tree pinning libakstdlib at 0.1.0 while adding libakgl by
add_subdirectory() compiles 0.2.0-era code against 0.1.0 headers and fails.

Also rewrites the paragraph that told an agent to read libakstdlib's TODO.md
section 2.1 before touching akstdlib.h. That release fixed all six confirmed
defects, folded the four known-failing tests back in and left
AKSL_KNOWN_FAILING_TESTS empty, so the warning now points at a list that is
empty and the bans it implied would send somebody around a workaround for
functions that work. The one caveat that survives -- aksl_strhash_djb2 still
sign-extends char -- is named, along with the section explaining why the symbol
tables cannot reach it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-31 09:55:47 -04:00
parent 0df0a95600
commit c70f8e7727

View File

@@ -81,13 +81,20 @@ that repo is next touched. See the error-code section below for a live collision
| Submodule | Version | soname | ABI rule | Version API | | Submodule | Version | soname | ABI rule | Version API |
|---|---|---|---|---| |---|---|---|---|---|
| `deps/libakerror` | 1.0.0 | `libakerror.so.1` | major only | **none** — no version macro, no `ConfigVersion` file | | `deps/libakerror` | 1.0.0 | `libakerror.so.1` | major only | **none** — no version macro, no `ConfigVersion` file |
| `deps/libakstdlib` | 0.1.0 | `libakstdlib.so.0.1` | **`MAJOR.MINOR` while major is 0** | `AKSL_VERSION_*`, `aksl_version()`, `AKSL_VERSION_CHECK()` | | `deps/libakstdlib` | 0.2.0 | `libakstdlib.so.0.2` | **`MAJOR.MINOR` while major is 0** | `AKSL_VERSION_*`, `aksl_version()`, `AKSL_VERSION_CHECK()` |
| `deps/libakgl` | 0.1.0 | `libakgl.so.0.1` | **`MAJOR.MINOR` while major is 0** | `AKGL_VERSION*`, `akgl_version()`, `AKGL_VERSION_AT_LEAST()` | | `deps/libakgl` | 0.2.0 | `libakgl.so.0.2` | **`MAJOR.MINOR` while major is 0** | `AKGL_VERSION*`, `akgl_version()`, `AKGL_VERSION_AT_LEAST()` |
For both 0.x libraries the soname carries `MAJOR.MINOR` deliberately: 0.1 and 0.2 are *different* For both 0.x libraries the soname carries `MAJOR.MINOR` deliberately: 0.1 and 0.2 are *different*
ABIs, and both become major-only at 1.0. Do not read `0.1 → 0.2` as a compatible bump. ABIs, and both become major-only at 1.0. Do not read `0.1 → 0.2` as a compatible bump — and both
libraries have now actually made that jump, so anything built against the 0.1 headers must be
rebuilt rather than relinked.
`libakstdlib` 0.1.0 added a version API worth using. `akstdlib.h` now pulls in **The two moved together and had to.** `libakgl` 0.2.0 consumes the `libakstdlib` 0.2.0 API, so a
tree that pins `libakstdlib` at 0.1.0 and adds `libakgl` by `add_subdirectory()` compiles
0.2.0-era code against 0.1.0 headers and fails on `aksl_fwrite`, `aksl_fread` and
`aksl_realpath`. Bump them as a pair.
`libakstdlib` 0.1.0 added a version API worth using, and it still applies at 0.2.0. `akstdlib.h` now pulls in
`<akstdlib_version.h>`, which is **generated into the build tree** by CMake and installed beside `<akstdlib_version.h>`, which is **generated into the build tree** by CMake and installed beside
`akstdlib.h` — so link `akstdlib::akstdlib` and let the target carry its include directories; hand-adding `akstdlib.h` — so link `akstdlib::akstdlib` and let the target carry its include directories; hand-adding
`deps/libakstdlib/include` to an include path gets you a missing-header error. It defines `deps/libakstdlib/include` to an include path gets you a missing-header error. It defines
@@ -100,7 +107,7 @@ notices. It is a macro on purpose: it must expand at your call site to capture y
`libakgl` 0.1.0 followed the same pattern one commit later, for the same reason: it had `AKGL_VERSION` `libakgl` 0.1.0 followed the same pattern one commit later, for the same reason: it had `AKGL_VERSION`
hand-maintained in `game.h` and no `VERSION` on `project()` at all, so `akgl.pc` shipped an empty hand-maintained in `game.h` and no `VERSION` on `project()` at all, so `akgl.pc` shipped an empty
`Version:` and the `.so` had no soname. Now `project(akgl VERSION 0.1.0)` is the single source and `Version:` and the `.so` had no soname. Now `project(akgl VERSION 0.2.0)` is the single source and
drives the generated `include/akgl/version.h` — which is `.gitignore`d, because `include/` precedes the drives the generated `include/akgl/version.h` — which is `.gitignore`d, because `include/` precedes the
build tree on the include path and a stray copy there would shadow the generated one and pin every build tree on the include path and a stray copy there would shadow the generated one and pin every
consumer. It publishes `AKGL_VERSION_AT_LEAST(major, minor, patch)`, the compile-time test consumer. It publishes `AKGL_VERSION_AT_LEAST(major, minor, patch)`, the compile-time test
@@ -268,11 +275,17 @@ defect-free. When a known-failing test starts passing, CTest reports "unexpected
cue to move it into `AKSL_TESTS` along with the fix. `libakerror` has the same split cue to move it into `AKSL_TESTS` along with the fix. `libakerror` has the same split
(`AKERR_TESTS` / `AKERR_WILL_FAIL_TESTS`). (`AKERR_TESTS` / `AKERR_WILL_FAIL_TESTS`).
That split is not academic for `libakstdlib`: `deps/libakstdlib/TODO.md` §2.1 lists six **confirmed** That split *used* to be load-bearing for `libakstdlib`, and no longer is: 0.2.0 fixed all six of the
defects, four with a known-failing test apiece. Several are in functions this port would otherwise confirmed defects its `TODO.md` §2.1 listed, folded the four known-failing tests back into the
reach for by default — the `aksl_ato*` family cannot report a conversion failure at all, and the suites for the things they test, and left `AKSL_KNOWN_FAILING_TESTS` empty. The `aksl_ato*` family
linked-list functions truncate. **Read §2.1 before calling anything in `akstdlib.h` for the first now raises `AKERR_VALUE` on no digits or trailing junk and `ERANGE` on overflow, the linked-list
time**; `TODO.md` §1.9 in this repo records which calls are cleared for use here and which are not. functions no longer truncate, `AKERR_ITERATOR_BREAK` stops a tree traversal, and `aksl_realpath` no
longer reads uninitialised memory.
`TODO.md` §1.9 in this repo is still the place to check before reaching into `akstdlib.h`, but it
is now a record of what changed rather than a list of bans. One caveat survives the upgrade:
`aksl_strhash_djb2` still sign-extends `char`, so a high-bit byte hashes differently from the
`unsigned char` answer — see §1.3, which explains why the symbol tables cannot reach it.
The branch-coverage gate there was re-ratcheted 45 → 40 after the 1.0.0 bump, because the new The branch-coverage gate there was re-ratcheted 45 → 40 after the 1.0.0 bump, because the new
`PREPARE_ERROR`/`FAIL_*` macros expand to more branches per call site — that is a denominator change, `PREPARE_ERROR`/`FAIL_*` macros expand to more branches per call site — that is a denominator change,
not a regression, and the same effect will show up in this repo's numbers. not a regression, and the same effect will show up in this repo's numbers.
@@ -349,7 +362,7 @@ are used, so a later addition does not need a second reservation:
| `"akbasic"` | 512 767 | ours; `AKBASIC_ERR_BASE` is 512 | | `"akbasic"` | 512 767 | ours; `AKBASIC_ERR_BASE` is 512 |
**Every owner reserves at init, and each does it in its own initializer.** `akerr_init()` claims **Every owner reserves at init, and each does it in its own initializer.** `akerr_init()` claims
0255 for itself. `akgl_error_init()` (`deps/libakgl/src/error.c`, new in libakgl 0.1.0) claims 0255 for itself. `akgl_error_init()` (`deps/libakgl/src/error.c`) claims
`AKGL_ERR_BASE` = `AKERR_FIRST_CONSUMER_STATUS` = 256 through `AKGL_ERR_LIMIT - 1` = 260 and names all `AKGL_ERR_BASE` = `AKERR_FIRST_CONSUMER_STATUS` = 256 through `AKGL_ERR_LIMIT - 1` = 260 and names all
five codes. `libakstdlib` claims nothing. `akbasic_init()` claims 512767. five codes. `libakstdlib` claims nothing. `akbasic_init()` claims 512767.