Fix the AKERR_USE_STDLIB=OFF build (issue #12)
All checks were successful
All checks were successful
The freestanding build (-DAKERR_USE_STDLIB=OFF) did not compile at all: bool, PATH_MAX and NULL were used unconditionally in the public header but only included under the stdlib branch, and the CMake option was pasted straight into a preprocessor definition, so a non-numeric cache spelling (-DAKERR_USE_STDLIB=ON) silently evaluated to 0. - Normalize AKERR_USE_STDLIB to a plain 1/0 in CMake before stamping it, and use a consistent '#if AKERR_USE_STDLIB' everywhere it is tested. - Include <stdbool.h>/<stddef.h> unconditionally (freestanding-safe); keep <stdlib.h>/<string.h>/<stdio.h> behind AKERR_USE_STDLIB; move <limits.h> out of the public header into src/error.c, its only user. - Define the freestanding runtime contract: AKERR_RUNTIME_HEADER must name a header providing exit, memset, snprintf, strcmp, strlen and strncpy when AKERR_USE_STDLIB is OFF, or the header #errors naming them. Add cmake/akerr_default_runtime.h, a libc-backed convenience default so this repo's own OFF build and tests work out of the box. - Route ENSURE_ERROR_READY's pool-exhaustion path through akerr_exit() instead of a direct exit(1). Deliberate behavior change: that exit code moves from 1 to AKERR_EXIT_STATUS_UNREPRESENTABLE (125), the same sentinel every other unrepresentable status already uses. Documented in docs/building.md and UPGRADING.md. Not an ABI break. - Retire PATH_MAX: AKERR_MAX_ERROR_FNAME_LENGTH is now stamped by scripts/generrno.sh from a new AKERR_MAX_ERROR_FNAME_LENGTH cache variable, defaulting to 4096 (PATH_MAX on Linux/glibc) so sizeof(akerr_ErrorContext) and the soname are unchanged. Rewrite the now-stale PATH_MAX justification in src/lock.h's feature-test-macro comment. - Fail the configure with a FATAL_ERROR, not a warning, when AKERR_USE_STDLIB=OFF and AKERR_THREADS would resolve to pthread, naming -DAKERR_THREADS=none as the fix. - Keep the generated errno table (errno.c) out of the OFF build; skip the 'errno --list' shellout in scripts/generrno.sh under OFF and stamp AKERR_LAST_ERRNO_VALUE from a new fallback cache variable (default 133, Linux's EHWPOISON) instead. - Update docs/building.md: drop the known-defect paragraph, fix sprintf -> snprintf, add size_t, drop PATH_MAX, and document the new options and the exit-code change. - Guard tests/err_errno.c's registered-name assertion behind AKERR_USE_STDLIB: akerr_init_errno() is not called when it is OFF. - Add a CI job that configures/builds/tests AKERR_USE_STDLIB=OFF with AKERR_THREADS=none, plus a compile-only -nostdinc -ffreestanding check of tests/freestanding_fixture.c against the generated header. Bump the project version to 2.0.2 (no ABI break: soname and struct layout are unchanged). Verified locally: OFF+none configures and builds clean with all tests passing; ON and the plain default build both build and pass their full test suites (37/37); OFF with the default/auto thread backend fails configure with a message naming -DAKERR_THREADS=none; sizeof(akerr_ErrorContext) is unchanged (37296 bytes, fname/function still 4096 each) versus the pre-change tree. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
35
UPGRADING.md
35
UPGRADING.md
@@ -1,3 +1,38 @@
|
||||
# Bug fix: the AKERR_USE_STDLIB=OFF build, and a pool-exhaustion exit code (2.0.2)
|
||||
|
||||
`-DAKERR_USE_STDLIB=OFF` did not compile at all ([issue #12](https://source.starfort.tech/andrew/libakerror/issues/12)):
|
||||
`bool`, `PATH_MAX` and `NULL` were used unconditionally in the public header
|
||||
but only included under the stdlib branch, and the CMake option itself was
|
||||
pasted straight into a preprocessor definition, so a boolean spelling like
|
||||
`ON` silently evaluated to 0 in `#if AKERR_USE_STDLIB == 1`. Both are fixed:
|
||||
`<stdbool.h>` and `<stddef.h>` are now included unconditionally (they are
|
||||
freestanding-safe), and the CMake option is normalized to a plain `1`/`0`
|
||||
before being stamped into the header.
|
||||
|
||||
`AKERR_USE_STDLIB=OFF` now has a mandatory, explicit contract:
|
||||
`AKERR_RUNTIME_HEADER` must name a header providing `exit`, `memset`,
|
||||
`snprintf`, `strcmp`, `strlen` and `strncpy` — the header `#error`s at compile
|
||||
time naming those six symbols if it is unset. `AKERR_THREADS` must resolve to
|
||||
`none`; the configure now fails outright (not a warning) if it would resolve
|
||||
to `pthread`, since the pthread backend calls into libc. See
|
||||
[docs/building.md](docs/building.md#dependencies).
|
||||
|
||||
`PATH_MAX`, used to size the `fname`/`function` fields of `akerr_ErrorContext`,
|
||||
is retired in favor of a new `AKERR_MAX_ERROR_FNAME_LENGTH` build option. Its
|
||||
default (4096) matches `PATH_MAX` on Linux/glibc, so `sizeof(akerr_ErrorContext)`
|
||||
and the soname are unchanged unless you deliberately override it — **no ABI
|
||||
break**.
|
||||
|
||||
**Behavior change, not an ABI break:** `ENSURE_ERROR_READY`'s pool-exhaustion
|
||||
path — reached when every slot in `AKERR_ARRAY_ERROR` is checked out and
|
||||
something still tries to raise — used to call `exit(1)` directly. It now calls
|
||||
`akerr_exit(AKERR_EXIT_STATUS_UNREPRESENTABLE)`, the same terminal path every
|
||||
other exit out of the library's status space goes through, so **the exit code
|
||||
for that case changes from 1 to 125**. If you were checking `$?` for exactly
|
||||
`1` to detect pool exhaustion specifically, check for 125 instead (and note
|
||||
125 is shared with every other status an exit code cannot carry — see the note
|
||||
on `AKERR_EXIT_STATUS_UNREPRESENTABLE` in the header).
|
||||
|
||||
# Bug fix: unhandled-error exit status (2.0.1)
|
||||
|
||||
An unhandled error could kill the process and still report success.
|
||||
|
||||
Reference in New Issue
Block a user