|
| 1 | +#!/usr/bin/env bash |
| 2 | +# |
| 3 | +# check-headers.sh |
| 4 | +# |
| 5 | +# Verifies that every public-facing wolfSSL header compiles standalone |
| 6 | +# from a fresh consumer's perspective: |
| 7 | +# |
| 8 | +# #include <wolfssl/options.h> |
| 9 | +# #include <wolfssl/...the header...> |
| 10 | +# int main(void) { return 0; } |
| 11 | +# |
| 12 | +# Catches the common breakage where a header silently relies on a |
| 13 | +# transitive include from an earlier `.c` file and stops compiling |
| 14 | +# when downstream code includes it first. |
| 15 | +# |
| 16 | +# Requires: |
| 17 | +# * ./configure has been run (so wolfssl/options.h exists). |
| 18 | +# * gcc and standard build env. |
| 19 | +# |
| 20 | +# Usage: |
| 21 | +# .github/scripts/check-headers.sh # scan default header set |
| 22 | +# .github/scripts/check-headers.sh <files> # scan a specific list |
| 23 | + |
| 24 | +set -u |
| 25 | + |
| 26 | +ROOT="$(git rev-parse --show-toplevel)" |
| 27 | +cd "$ROOT" || exit 2 |
| 28 | + |
| 29 | +if [ ! -f wolfssl/options.h ]; then |
| 30 | + echo "::error::wolfssl/options.h not found - run ./configure first" >&2 |
| 31 | + exit 2 |
| 32 | +fi |
| 33 | + |
| 34 | +CC="${CC:-gcc}" |
| 35 | +GHA="${GITHUB_ACTIONS:-}" |
| 36 | + |
| 37 | +emit() { |
| 38 | + local file="$1" msg="$2" |
| 39 | + if [ -n "$GHA" ]; then |
| 40 | + printf '::error file=%s,line=1,title=header-self-include::%s\n' "$file" "$msg" |
| 41 | + else |
| 42 | + printf '%s: %s\n' "$file" "$msg" |
| 43 | + fi |
| 44 | +} |
| 45 | + |
| 46 | +# Default scope: public wolfssl headers excluding vendor/port subdirs and |
| 47 | +# files that are intentionally not standalone-includable. |
| 48 | +if [ "$#" -gt 0 ]; then |
| 49 | + HEADERS=("$@") |
| 50 | +else |
| 51 | + # Exclusions: |
| 52 | + # * generated / private / test-data headers. |
| 53 | + # * wolfcrypt math backends (tfm vs sp_int are mutually exclusive). |
| 54 | + # * port/* headers whose first-line vendor SDK include can't be |
| 55 | + # satisfied in a generic CI environment (mcapi.h, kcapi.h, |
| 56 | + # em_device.h, fsl_dcp.h, hw/inout.h, etc.) or that reference |
| 57 | + # vendor-only types. Fix the offending header's vendor #include |
| 58 | + # with an #ifdef guard and drop the exclusion in a follow-up. |
| 59 | + mapfile -t HEADERS < <( |
| 60 | + git ls-files 'wolfssl/*.h' 'wolfssl/wolfcrypt/*.h' \ |
| 61 | + 'wolfssl/wolfcrypt/port/**/*.h' 'wolfssl/openssl/*.h' \ |
| 62 | + | grep -vE '^wolfssl/(options|internal|certs_test|certs_test_sm|debug-trace-error-codes|debug-untrace-error-codes)\.h$' \ |
| 63 | + | grep -vE '^wolfssl/wolfcrypt/(fips_test|selftest|tfm)\.h$' \ |
| 64 | + | grep -vE '^wolfssl/wolfcrypt/port/aria/aria-crypt(ocb)?\.h$' \ |
| 65 | + | grep -vE '^wolfssl/wolfcrypt/port/autosar/(CryIf|Crypto)\.h$' \ |
| 66 | + | grep -vE '^wolfssl/wolfcrypt/port/caam/(caam_driver|caam_qnx|wolfcaam_hash)\.h$' \ |
| 67 | + | grep -vE '^wolfssl/wolfcrypt/port/kcapi/' \ |
| 68 | + | grep -vE '^wolfssl/wolfcrypt/port/nxp/(dcp_port|se050_port)\.h$' \ |
| 69 | + | grep -vE '^wolfssl/wolfcrypt/port/Renesas/(renesas_fspsm_internal|renesas-rx64-hw-crypt|renesas-tsip-crypt|renesas_tsip_internal)\.h$' \ |
| 70 | + | grep -vE '^wolfssl/wolfcrypt/port/silabs/silabs_aes\.h$' |
| 71 | + ) |
| 72 | +fi |
| 73 | + |
| 74 | +TMPDIR="$(mktemp -d)" |
| 75 | +trap 'rm -rf "$TMPDIR"' EXIT |
| 76 | + |
| 77 | +FAIL=0 |
| 78 | +PASS=0 |
| 79 | +for h in "${HEADERS[@]}"; do |
| 80 | + [ -f "$h" ] || continue |
| 81 | + cat > "$TMPDIR/test.c" <<EOF |
| 82 | +#include <wolfssl/options.h> |
| 83 | +#include <$h> |
| 84 | +int main(void) { return 0; } |
| 85 | +EOF |
| 86 | + if out="$("$CC" -I. -c -o /dev/null "$TMPDIR/test.c" 2>&1)"; then |
| 87 | + PASS=$((PASS + 1)) |
| 88 | + else |
| 89 | + FAIL=$((FAIL + 1)) |
| 90 | + first_err="$(printf '%s' "$out" | grep -E 'error:' | head -1 | sed 's/.*error: //')" |
| 91 | + emit "$h" "header does not compile standalone: ${first_err:-(see build log)}" |
| 92 | + if [ -z "$GHA" ]; then |
| 93 | + printf '%s\n' "$out" | head -8 | sed 's/^/ /' |
| 94 | + fi |
| 95 | + fi |
| 96 | +done |
| 97 | + |
| 98 | +echo "check-headers: $PASS pass, $FAIL fail" |
| 99 | +[ "$FAIL" -eq 0 ] |
0 commit comments