From b4166a44067ef96600321ff1d7ef122ab94bb0c7 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Tue, 14 Apr 2026 13:36:20 +0900 Subject: [PATCH 1/2] feat(#460): Add binary-size regression gate script and baseline Add scripts/ci/check-text-size.sh that extracts the .text section size from the built library, compares against the committed baseline in tests/baseline_size.txt, and fails if growth exceeds the 5120-byte budget (section 14, #446). Baseline recorded from Linux GCC build (ubuntu:24.04, 148496 bytes). --- scripts/ci/check-text-size.sh | 96 +++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100755 scripts/ci/check-text-size.sh diff --git a/scripts/ci/check-text-size.sh b/scripts/ci/check-text-size.sh new file mode 100755 index 00000000..6d12aa06 --- /dev/null +++ b/scripts/ci/check-text-size.sh @@ -0,0 +1,96 @@ +#!/bin/sh +# check-text-size.sh - Binary-size regression gate for libwirelog (Issue #460) +# +# Computes .text section size of the built library, compares against +# the committed baseline in tests/baseline_size.txt, and fails if +# growth exceeds the 5120-byte budget (section 14, Issue #446). +# +# Usage: scripts/ci/check-text-size.sh +# Example: scripts/ci/check-text-size.sh builddir/libwirelog.so +# +# To update the baseline after legitimate growth: +# echo > tests/baseline_size.txt + +set -e + +THRESHOLD=5120 +SCRIPT_DIR=$(cd "$(dirname "$0")" && pwd) +REPO_ROOT=$(cd "$SCRIPT_DIR/../.." && pwd) +BASELINE_FILE="$REPO_ROOT/tests/baseline_size.txt" + +die() { + printf 'error: %s\n' "$1" >&2 + exit 1 +} + +if [ $# -lt 1 ]; then + die "usage: $0 " +fi + +LIB="$1" + +if [ ! -f "$LIB" ]; then + die "library not found: $LIB" +fi + +# Extract .text section size (platform-aware) +extract_text_size() { + case "$(uname -s)" in + Linux) + size --format=sysv "$1" | awk '/^\.text[[:space:]]/ { print $2 }' + ;; + Darwin) + size -m "$1" | awk '/Section __text:/ { print $3 }' + ;; + *) + die "unsupported platform: $(uname -s)" + ;; + esac +} + +TEXT_SIZE=$(extract_text_size "$LIB") + +if [ -z "$TEXT_SIZE" ]; then + die "could not extract .text section size from $LIB" +fi + +# Validate extracted size is numeric +case "$TEXT_SIZE" in + ''|*[!0-9]*) + die "non-numeric .text size extracted: '$TEXT_SIZE'" + ;; +esac + +# Read baseline +if [ ! -f "$BASELINE_FILE" ]; then + die "baseline file not found: $BASELINE_FILE" +fi + +BASELINE=$(tr -d '[:space:]' < "$BASELINE_FILE") + +case "$BASELINE" in + ''|*[!0-9]*) + die "invalid baseline value in $BASELINE_FILE: '$BASELINE'" + ;; +esac + +# Compute delta (positive = growth, negative = shrinkage) +DELTA=$((TEXT_SIZE - BASELINE)) + +printf '.text size: %d bytes\n' "$TEXT_SIZE" +printf 'baseline: %d bytes\n' "$BASELINE" +if [ "$DELTA" -ge 0 ]; then + printf 'delta: +%d bytes\n' "$DELTA" +else + printf 'delta: %d bytes\n' "$DELTA" +fi +printf 'threshold: +%d bytes\n' "$THRESHOLD" + +if [ "$DELTA" -gt "$THRESHOLD" ]; then + printf '\nFAIL: .text growth (+%d) exceeds %d-byte budget\n' "$DELTA" "$THRESHOLD" >&2 + printf 'To update the baseline after a legitimate change:\n' >&2 + printf ' echo %d > tests/baseline_size.txt\n' "$TEXT_SIZE" >&2 + exit 1 +fi + +printf '\nPASS: .text delta within budget\n' From e7cfbe5d33bf40e3f5a81c9f364504f70780c473 Mon Sep 17 00:00:00 2001 From: Justin Kim Date: Tue, 14 Apr 2026 13:36:26 +0900 Subject: [PATCH 2/2] ci(#460): Integrate binary-size check into PR and main workflows Add .text size regression gate to ci-pr.yml (blocking, Linux GCC only) and ci-main.yml (non-blocking monitoring). Runs after build+test, before sanitizers, to avoid wasting compute on size-rejected builds. --- .github/workflows/ci-main.yml | 5 +++++ .github/workflows/ci-pr.yml | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml index 3c4d2dfa..ab2da32f 100644 --- a/.github/workflows/ci-main.yml +++ b/.github/workflows/ci-main.yml @@ -132,6 +132,11 @@ jobs: if: runner.os != 'Windows' run: meson test -C builddir --print-errorlogs + - name: Check binary size + if: runner.os == 'Linux' && matrix.compiler == 'gcc' + continue-on-error: true + run: scripts/ci/check-text-size.sh builddir/libwirelog.so + - name: Publish results if: always() shell: bash diff --git a/.github/workflows/ci-pr.yml b/.github/workflows/ci-pr.yml index d79ea7a8..b0a07912 100644 --- a/.github/workflows/ci-pr.yml +++ b/.github/workflows/ci-pr.yml @@ -117,6 +117,14 @@ jobs: call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" meson test -C builddir --print-errorlogs + # ======================================================================= + # Binary size regression gate (Issue #460) + # Only runs on Linux GCC (reference platform for .text baseline) + # ======================================================================= + - name: Check binary size + if: runner.os == 'Linux' && matrix.compiler == 'gcc' + run: scripts/ci/check-text-size.sh builddir/libwirelog.so + # ======================================================================= # Phase 3: Sanitizers (ASan + UBSan) — runs on same platform after build # Linux: GCC + Clang; macOS: Clang (Windows: skipped)