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>
128 lines
5.3 KiB
YAML
128 lines
5.3 KiB
YAML
name: libakerror CI Build
|
|
run-name: ${{ gitea.actor }} libakerror test
|
|
on: [push]
|
|
|
|
jobs:
|
|
cmake_build:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- run: echo "Triggered by ${{ gitea.event_name }} from ${{ gitea.repository }}@${{ gitea.ref }}. Building on ${{ runner.os }}."
|
|
- name: Check out repository code
|
|
uses: actions/checkout@v4
|
|
- name: dependencies
|
|
run: |
|
|
sudo apt-get update -y
|
|
sudo apt-get install -y cmake gcc moreutils
|
|
- name: build and install
|
|
run: |
|
|
mkdir installdir
|
|
cmake -S . -B build -DCMAKE_INSTALL_PREFIX=installdir
|
|
cmake --build build
|
|
cmake --install build
|
|
# --output-junit resolves relative to the test dir, so give an absolute
|
|
# path to land the report in the workspace root for the reporter below.
|
|
- name: test (JUnit)
|
|
run: ctest --test-dir build --output-on-failure --output-junit "$(pwd)/ctest-junit.xml"
|
|
# annotate_only: true skips creating a check run via the Checks API, which
|
|
# Gitea does not support and 404s on (mikepenz/action-junit-report#23).
|
|
# Results surface via the job summary instead.
|
|
- name: publish test results
|
|
if: always()
|
|
uses: mikepenz/action-junit-report@v4
|
|
with:
|
|
report_paths: 'ctest-junit.xml'
|
|
annotate_only: true
|
|
detailed_summary: true
|
|
include_passed: true
|
|
fail_on_failure: 'true'
|
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
|
|
|
# Builds and tests the AKERR_USE_STDLIB=OFF configuration end to end (issue
|
|
# #12), and separately proves that the generated header compiles under a
|
|
# genuinely freestanding toolchain (-nostdinc -ffreestanding, no libc at
|
|
# all) via tests/freestanding_fixture.c, which is never linked or run.
|
|
cmake_build_freestanding:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out repository code
|
|
uses: actions/checkout@v4
|
|
- name: dependencies
|
|
run: |
|
|
sudo apt-get update -y
|
|
sudo apt-get install -y cmake gcc
|
|
- name: configure, build and test (AKERR_USE_STDLIB=OFF)
|
|
run: |
|
|
cmake -S . -B build-off -DAKERR_USE_STDLIB=OFF -DAKERR_THREADS=none
|
|
cmake --build build-off
|
|
ctest --test-dir build-off --output-on-failure
|
|
- name: freestanding consumer fixture (compile-only, no libc)
|
|
run: |
|
|
gcc -c -std=c11 \
|
|
-nostdinc -ffreestanding \
|
|
-isystem "$(gcc -print-file-name=include)" \
|
|
-I build-off/generated/include \
|
|
-I tests \
|
|
tests/freestanding_fixture.c -o /tmp/freestanding_fixture.o
|
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
|
|
|
coverage:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out repository code
|
|
uses: actions/checkout@v4
|
|
- name: dependencies
|
|
run: |
|
|
sudo apt-get update -y
|
|
sudo apt-get install -y cmake gcc moreutils python3
|
|
# Run the suite against a gcov-instrumented build and gate on coverage of
|
|
# the library sources. Thresholds keep headroom below the current numbers
|
|
# (src/error.c: ~94% line, ~60% branch) and apply per file as well as to
|
|
# the total, so the generated status-name table cannot mask a regression.
|
|
- name: coverage
|
|
run: |
|
|
python3 scripts/coverage.py --junit coverage-junit.xml --threshold 90 --branch-threshold 50
|
|
# Publish even when the threshold gate fails, so gaps are visible.
|
|
# Display-only (fail_on_failure: false); the --threshold above is the gate.
|
|
# annotate_only avoids the Checks API 404 on Gitea (see note above).
|
|
- name: publish coverage results
|
|
if: always()
|
|
uses: mikepenz/action-junit-report@v4
|
|
with:
|
|
report_paths: 'coverage-junit.xml'
|
|
annotate_only: true
|
|
detailed_summary: true
|
|
include_passed: true
|
|
fail_on_failure: 'false'
|
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|
|
|
|
mutation_test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Check out repository code
|
|
uses: actions/checkout@v4
|
|
- name: dependencies
|
|
run: |
|
|
sudo apt-get update -y
|
|
sudo apt-get install -y cmake gcc moreutils python3
|
|
# Verify the tests actually catch bugs: break the library many ways and
|
|
# confirm the suite fails. Gated on src/error.c (fast, deterministic).
|
|
# The threshold keeps headroom below the current score for equivalent
|
|
# mutants; see tests/MUTATION.md. Run the full default target locally for
|
|
# deeper (slower) coverage including the macro header.
|
|
- name: mutation testing
|
|
run: |
|
|
python3 scripts/mutation_test.py --target src/error.c --junit mutation-junit.xml --threshold 65
|
|
# Publish even when the threshold gate fails, so survivors are visible.
|
|
# Display-only (fail_on_failure: false); the --threshold above is the gate.
|
|
# annotate_only avoids the Checks API 404 on Gitea (see note above).
|
|
- name: publish mutation results
|
|
if: always()
|
|
uses: mikepenz/action-junit-report@v4
|
|
with:
|
|
report_paths: 'mutation-junit.xml'
|
|
annotate_only: true
|
|
detailed_summary: true
|
|
include_passed: true
|
|
fail_on_failure: 'false'
|
|
- run: echo "🍏 This job's status is ${{ job.status }}."
|