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>
92 lines
5.2 KiB
Markdown
92 lines
5.2 KiB
Markdown
# Building libakerror
|
|
|
|
The ordinary build is an out-of-tree CMake build, described in
|
|
[the README](../README.md#installation). 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](thread-safety.md#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](#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 `#error`s 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](../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](../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:
|
|
|
|
1. When `AKERR_USE_STDLIB` is `ON`: executes `errno --list` and gathers up the
|
|
output. When it is `OFF`, this is skipped entirely (`errno --list` needs
|
|
moreutils and `<errno.h>`, neither freestanding-safe) and
|
|
`AKERR_LAST_ERRNO_VALUE` is taken from the `AKERR_LAST_ERRNO_VALUE_FALLBACK`
|
|
cache variable instead.
|
|
1. Templates `include/akerror.tmpl.h` into `include/akerror.h` to set
|
|
`AKERR_LAST_ERRNO_VALUE`, `AKERR_THREAD_SAFE`, and
|
|
`AKERR_MAX_ERROR_FNAME_LENGTH`.
|
|
2. Generates `src/errno.c`, which contains a function called by `akerr_init`
|
|
that initializes all of the status names for the previously defined values
|
|
of `errno`. Under `AKERR_USE_STDLIB=OFF` this 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](thread-safety.md)). 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:
|
|
|
|
- `memset` function
|
|
- `strncpy` function
|
|
- `strlen` function
|
|
- `strcmp` function
|
|
- `snprintf` function
|
|
- `exit` function
|
|
- `bool` type
|
|
- `NULL` type
|
|
- `size_t` type
|
|
- `INT_MAX` constant
|
|
|
|
`<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 `#error`s 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.
|