Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
# 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 |
| ------ | ------- | ------------ |
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
| `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. |
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
| `AKERR_USE_STDLIB` | `ON` | Link against the C standard library. See [Dependencies ](#dependencies ) for what you must supply instead when this is `OFF` . |
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
| `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` ). |
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
| `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. |
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
**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 ).
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
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:
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
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.
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
Neither generated output is meant to be edited. Change the template or the generator.
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
## Dependencies
This library depends upon `stdlib` , and upon POSIX threads unless it is built
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
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:
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
- `memset` function
- `strncpy` function
- `strlen` function
- `strcmp` function
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
- `snprintf` function
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
- `exit` function
- `bool` type
- `NULL` type
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
- `size_t` type
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
- `INT_MAX` constant
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
`<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.
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
... then you can compile it thusly:
```
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
cmake -S . -B build -DAKERR_USE_STDLIB=OFF -DAKERR_THREADS=none \
-DAKERR_RUNTIME_HEADER=/path/to/your/runtime.h
Split the README reference material into docs/
The README was 794 lines: the summary, the design rationale, the whole macro
reference, the threading contract, the build internals and the exit-status
specification in one file. It is now 178 lines -- summary, installation,
quickstart, and an index -- and the reference material lives in docs/, one file
per topic: architecture, usage, status-codes, uncaught-errors, exit-status,
thread-safety, building.
The prose moved as written. Inbound references followed it: UPGRADING.md,
TODO.md, include/akerror.tmpl.h and tests/err_threads_handoff.c now name the
docs/ file that owns the text they cite, and AGENTS.md says where new
documentation goes so the README does not grow back.
Five factual errors fixed in the moved text:
- Both NULL-pointer examples inverted their test. FAIL_ZERO_* fails when the
expression is zero, so `(somePointer == NULL)` failed on a *valid* pointer.
They now read `(somePointer != NULL)`.
- AKERROR_NOIGNORE, four times including the #define, is AKERR_NOIGNORE.
- FINISH_NORExbTURN is FINISH_NORETURN.
- "functiions" is "functions".
- The architecture link pointed at include/akerror.h, which is generated and
not in the tree; it points at include/akerror.tmpl.h.
The quickstart is new text. It compiles under -Wall -Wextra -Werror and was run
through all three of its paths: handled usage error exits 0, unhandled IO error
prints a trace and exits with the status, success exits 0.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Andrew Kesterson <andrew@aklabs.net>
2026-08-01 16:56:07 -04:00
cmake --build build
cmake --install build
```
Fix the AKERR_USE_STDLIB=OFF build (issue #12)
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>
2026-08-05 10:29:39 -04:00
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.