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>
5.2 KiB
Building libakerror
The ordinary build is an out-of-tree CMake build, described in the README. This file covers what the build generates for you, what it links against, and the configure options that change either of those.
Configure options
| Option | Default | What it does |
|---|---|---|
AKERR_THREADS |
auto |
Threading backend: auto, pthread, or none. auto takes POSIX threads and fails the configure if it cannot find them. See Building single threaded. Must be none when AKERR_USE_STDLIB is OFF — the pthread backend calls into libc, and the configure fails otherwise. |
AKERR_USE_STDLIB |
ON |
Link against the C standard library. See Dependencies for what you must supply instead when this is OFF. |
AKERR_RUNTIME_HEADER |
(empty) | Mandatory when AKERR_USE_STDLIB is OFF. Header providing exit, memset, snprintf, strcmp, strlen and strncpy; the generated header #errors at compile time if it is unset. Defaults to a thin, libc-backed convenience header (cmake/akerr_default_runtime.h) so this repository's own OFF build and test suite work without a real freestanding runtime — a genuinely freestanding consumer should override it with their own header. |
AKERR_MAX_ERROR_FNAME_LENGTH |
4096 |
Bytes reserved for the fname/function fields of akerr_ErrorContext. Defaults to PATH_MAX on Linux/glibc, which keeps sizeof(akerr_ErrorContext) and the soname unchanged; changing it is an ABI break. |
AKERR_LAST_ERRNO_VALUE_FALLBACK |
133 |
AKERR_LAST_ERRNO_VALUE to stamp when AKERR_USE_STDLIB is OFF, since that configuration cannot shell out to errno --list. Defaults to 133 (Linux's EHWPOISON). |
AKERR_STATUS_NAME_SLOTS |
4096 |
Slots in the status-name table; 75% of it is usable. |
AKERR_MAX_RESERVED_STATUS_RANGES |
64 |
How many status ranges may be reserved in one process. |
AKERR_SANITIZE |
(empty) | Sanitizer list applied to the library and the tests, e.g. thread or address,undefined. |
AKERR_COVERAGE |
OFF |
Instrument the library with gcov counters. |
Behavior change (2.0.2): pool exhaustion inside ENSURE_ERROR_READY (every
context-producing macro goes through it) used to call exit(1) directly. It
now calls akerr_exit(AKERR_EXIT_STATUS_UNREPRESENTABLE), so a process that
runs out of pool slots exits 125 instead of 1. See
UPGRADING.md.
The two capacity options are applied PRIVATE: the tables live entirely in
src/error.c, so raising them never changes anything a consumer can see. See
UPGRADING.md for what happens when you exhaust them.
Templating and autogenerated code
The build process relies upon scripts/generrno.sh which performs the following:
- When
AKERR_USE_STDLIBisON: executeserrno --listand gathers up the output. When it isOFF, this is skipped entirely (errno --listneeds moreutils and<errno.h>, neither freestanding-safe) andAKERR_LAST_ERRNO_VALUEis taken from theAKERR_LAST_ERRNO_VALUE_FALLBACKcache variable instead. - Templates
include/akerror.tmpl.hintoinclude/akerror.hto setAKERR_LAST_ERRNO_VALUE,AKERR_THREAD_SAFE, andAKERR_MAX_ERROR_FNAME_LENGTH. - Generates
src/errno.c, which contains a function called byakerr_initthat initializes all of the status names for the previously defined values oferrno. UnderAKERR_USE_STDLIB=OFFthis file is a stub, and CMake does not compile it into the library at all —akerr_init_errno()is never called in that configuration.
Neither generated output is meant to be edited. Change the template or the generator.
Dependencies
This library depends upon stdlib, and upon POSIX threads unless it is built
with -DAKERR_THREADS=none (see Thread safety). If you
don't want to link against stdlib, build with -DAKERR_USE_STDLIB=OFF (which
requires -DAKERR_THREADS=none — see the options table above) and supply a
header, via the AKERR_RUNTIME_HEADER cache variable, that provides:
memsetfunctionstrncpyfunctionstrlenfunctionstrcmpfunctionsnprintffunctionexitfunctionbooltypeNULLtypesize_ttypeINT_MAXconstant
<stdbool.h> and <stddef.h> — which give you bool/NULL/size_t — are
included unconditionally by the public header regardless of
AKERR_USE_STDLIB, since both are freestanding-safe. AKERR_RUNTIME_HEADER is
mandatory in this configuration: the generated header #errors at compile
time if it is unset.
... then you can compile it thusly:
cmake -S . -B build -DAKERR_USE_STDLIB=OFF -DAKERR_THREADS=none \
-DAKERR_RUNTIME_HEADER=/path/to/your/runtime.h
cmake --build build
cmake --install build
If you omit -DAKERR_RUNTIME_HEADER, the build falls back to a convenience
header backed by the host's own libc (see the options table above), so the
OFF configuration still builds and its test suite still runs on an ordinary
hosted machine — useful for exercising the freestanding code paths without a
real freestanding runtime, but not what an actually freestanding consumer
wants. Supply your own header to get the real thing.