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:
@@ -1,12 +1,42 @@
|
||||
#ifndef _AKERR_H_
|
||||
#define _AKERR_H_
|
||||
|
||||
#if (defined(AKERR_USE_STDLIB) && AKERR_USE_STDLIB == 1) || (!defined(AKERR_USE_STDLIB))
|
||||
#include <stdlib.h>
|
||||
/*
|
||||
* A consumer compiling this header directly (not through the CMake package,
|
||||
* which always stamps a numeric AKERR_USE_STDLIB=0/1 -- see CMakeLists.txt)
|
||||
* gets the hosted default.
|
||||
*/
|
||||
#ifndef AKERR_USE_STDLIB
|
||||
#define AKERR_USE_STDLIB 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* <stdbool.h> and <stddef.h> are freestanding-safe (C99/C11 4p6): they define
|
||||
* only bool/true/false and NULL/size_t, nothing that requires an operating
|
||||
* system underneath. Include them unconditionally so both configurations get
|
||||
* those types. Everything that actually talks to a hosted environment --
|
||||
* stdlib.h, string.h, stdio.h -- stays behind AKERR_USE_STDLIB.
|
||||
*/
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if AKERR_USE_STDLIB
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#else
|
||||
/*
|
||||
* Freestanding runtime contract. AKERR_USE_STDLIB=OFF still needs exit,
|
||||
* memset, snprintf, strcmp, strlen and strncpy (see the FAIL/ENSURE_ERROR_READY
|
||||
* macros and src/error.c below) -- this library does not implement its own
|
||||
* copies of them. Define AKERR_RUNTIME_HEADER to a header that provides all
|
||||
* six before including this one.
|
||||
*/
|
||||
#ifdef AKERR_RUNTIME_HEADER
|
||||
#include AKERR_RUNTIME_HEADER
|
||||
#else
|
||||
#error "AKERR_USE_STDLIB is OFF: define AKERR_RUNTIME_HEADER to a header providing exit, memset, snprintf, strcmp, strlen and strncpy"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -52,7 +82,15 @@
|
||||
#define AKERR_MAX_ERROR_CONTEXT_STRING_LENGTH 12384
|
||||
|
||||
#define AKERR_MAX_ERROR_NAME_LENGTH 64
|
||||
#define AKERR_MAX_ERROR_FNAME_LENGTH PATH_MAX
|
||||
/*
|
||||
* scripts/generrno.sh stamps this in from the AKERR_MAX_ERROR_FNAME_LENGTH
|
||||
* CMake cache variable, the same way it stamps AKERR_THREAD_SAFE and
|
||||
* AKERR_LAST_ERRNO_VALUE. It used to be PATH_MAX, which is not available in a
|
||||
* freestanding build; the default here (4096) matches PATH_MAX on Linux/glibc
|
||||
* so sizeof(akerr_ErrorContext) and the soname are unchanged unless you
|
||||
* deliberately override it.
|
||||
*/
|
||||
#define AKERR_MAX_ERROR_FNAME_LENGTH 4096
|
||||
#define AKERR_MAX_ERROR_FUNCTION_LENGTH 128
|
||||
#define AKERR_MAX_ERROR_STACKTRACE_BUF_LENGTH (AKERR_MAX_ERROR_CONTEXT_STRING_LENGTH + AKERR_MAX_ERROR_NAME_LENGTH + AKERR_MAX_ERROR_FNAME_LENGTH + AKERR_MAX_ERROR_FUNCTION_LENGTH + 16)
|
||||
|
||||
@@ -296,7 +334,7 @@ akerr_ErrorContext AKERR_NOIGNORE *__akerr_copy_string(char *destination, int ca
|
||||
__err_context = akerr_next_error(); \
|
||||
if ( __err_context == NULL ) { \
|
||||
akerr_log_method("%s:%s:%d: Unable to pull an error context from the array!", __FILE__, (char *)__func__, __LINE__); \
|
||||
exit(1); \
|
||||
akerr_exit(AKERR_EXIT_STATUS_UNREPRESENTABLE); \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user