Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 51 additions & 8 deletions .github/scripts/contrib_check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,29 @@ mkdir -p "$run_dir"
# code is correct. Those tests are gated for RUNTIME correctness (the thing that
# actually caught the WS rot); making them leak-clean is separate follow-up
# work. i18n/collate was written leak-clean by design, so it IS leak-gated.
AVC="contrib/avcodec"
TW="contrib/tinyweb"
I18N="contrib/i18n"
# <label>|<test .ae>|<extra C sources>|<leakgate>|<pkg-config modules>
#
# Column 5 is optional and names the pkg-config modules the test must LINK
# against. It exists because `ae build --extra foo.c` compiles the shim but has
# no way to pass -l flags — a module needing a system library therefore
# compiles and then dies at link with "undefined reference". When column 5 is
# set the runner stages an aether.toml workspace (the same shape
# tests/integration/sqlite_roundtrip uses) so the flags reach gcc via
# get_link_flags(), and SKIPS the entry when pkg-config cannot find the
# modules — an absent system library is a provisioning gap, not a test failure.
TESTS=(
"tinyweb/spec|$TW/test_spec.ae||run"
"tinyweb/inventory|$TW/test_inventory.ae|$TW/ws_handshake.c|run"
"tinyweb/integration|$TW/test_integration.ae|$TW/ws_handshake.c|run"
"tinyweb/schema_api|$TW/test_schema_api.ae|$TW/ws_handshake.c|run"
"tinyweb/websocket|$TW/test_websocket.ae|$TW/ws_handshake.c|run"
"i18n/collate|$I18N/collate/test_collate.ae|$I18N/aether_i18n.c $I18N/utf8proc/utf8proc.c $I18N/ducet/ducet_data.c|leak"
# avcodec: needs FFmpeg's dev libraries to LINK and the ffmpeg BINARY to
# generate its clip; the test itself SKIPs cleanly without the latter.
"avcodec/decode|$AVC/test_avcodec.ae|$AVC/aether_avcodec.c|run|libavcodec libavformat libavutil libswscale"
"tinyweb/spec|$TW/test_spec.ae||run|"
"tinyweb/inventory|$TW/test_inventory.ae|$TW/ws_handshake.c|run|"
"tinyweb/integration|$TW/test_integration.ae|$TW/ws_handshake.c|run|"
"tinyweb/schema_api|$TW/test_schema_api.ae|$TW/ws_handshake.c|run|"
"tinyweb/websocket|$TW/test_websocket.ae|$TW/ws_handshake.c|run|"
"i18n/collate|$I18N/collate/test_collate.ae|$I18N/aether_i18n.c $I18N/utf8proc/utf8proc.c $I18N/ducet/ducet_data.c|leak|"
)

# Kill any stray cache/test binaries squatting ports before we start (aborted
Expand All @@ -57,7 +71,7 @@ reap_orphans() {
reap_orphans

for entry in "${TESTS[@]}"; do
IFS='|' read -r label src extras leakgate <<< "$entry"
IFS='|' read -r label src extras leakgate pcmods <<< "$entry"

if [ ! -f "$src" ]; then
printf ' SKIP %-22s (%s not found)\n' "$label" "$src"
Expand All @@ -71,7 +85,36 @@ for entry in "${TESTS[@]}"; do
extra_flags=""
for c in $extras; do extra_flags="$extra_flags --extra $c"; done

if ! berr="$("$AE$EXE_EXT" build "$src" $extra_flags -o "$out" 2>&1)"; then
if [ -n "$pcmods" ]; then
# Needs system libraries. Skip rather than fail when they are absent —
# a missing FFmpeg is a provisioning gap on this box, not a code defect.
if ! pkg-config --exists $pcmods 2>/dev/null; then
printf ' SKIP %-22s (pkg-config: %s not found)\n' "$label" "$pcmods"
continue
fi
# `ae build --extra` cannot pass -l flags, so stage a workspace whose
# aether.toml carries them; ae threads link_flags into gcc via
# get_link_flags(). Same shape as tests/integration/sqlite_roundtrip.
work="$run_dir/${safe}.work"
rm -rf "$work"; mkdir -p "$work"
ln -s "$(pwd)/contrib" "$work/contrib"
cp "$src" "$work/probe.ae"
extra_toml=""
for c in $extras; do extra_toml="$extra_toml\"$c\", "; done
{
printf '[project]\nname = "%s"\nversion = "0.0.0"\n\n' "$safe"
printf '[[bin]]\nname = "probe"\npath = "probe.ae"\n'
printf 'extra_sources = [%s]\n\n' "${extra_toml%, }"
printf '[build]\nlink_flags = "%s"\n' "$(pkg-config --libs $pcmods)"
} > "$work/aether.toml"
abs_out="$(pwd)/$out"; abs_ae="$(pwd)/${AE#./}$EXE_EXT"
if ! berr="$( cd "$work" && "$abs_ae" build probe.ae -o "$abs_out" 2>&1 )"; then
printf ' FAIL %-22s (build)\n' "$label"
echo "$berr" | grep -iE "error" | head -5
rc=1
continue
fi
elif ! berr="$("$AE$EXE_EXT" build "$src" $extra_flags -o "$out" 2>&1)"; then
printf ' FAIL %-22s (build)\n' "$label"
echo "$berr" | grep -iE "error" | head -5
rc=1
Expand Down
41 changes: 41 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,47 @@ case (no `--with=fs` → engine errors clearly):

## Other parked work

### Contrib runtime coverage is split across two mechanisms

`contrib/sqlite` is **not** in `.github/scripts/contrib_check.sh` — it is
covered by `tests/integration/sqlite_roundtrip/` instead. So contrib
runtime coverage currently lives in two places with different shapes, and
nothing says which a new module should use.

Noticed while fixing the `avcodec` entry (2026-08-09), which had been added
to `contrib_check.sh` but could never pass: the runner builds with
`ae build --extra shim.c`, which compiles a C shim but **cannot pass `-l`
flags**, so any module backed by a system library compiled and then died at
link with `undefined reference`. The fix taught `contrib_check.sh` a fifth
column naming pkg-config modules; when set it stages an `aether.toml`
workspace carrying `link_flags` — which is precisely the shape
`sqlite_roundtrip` had been using all along, hand-rolled in its own `.sh`.

So the two mechanisms now overlap: `contrib_check.sh` can do what
`sqlite_roundtrip` does, generically and in a table.

**The work:** move `contrib/sqlite` into the `contrib_check.sh` table

```
"sqlite/roundtrip|contrib/sqlite/test_sqlite.ae|contrib/sqlite/aether_sqlite.c|run|sqlite3"
```

and retire `tests/integration/sqlite_roundtrip/`. Needs a
`contrib/sqlite/test_sqlite.ae` first — the existing `probe.ae` is written
for the workspace harness and would need adapting.

**Why it is worth doing:** one table means a new native-backed contrib
module gets runtime coverage by adding one line, rather than by copying a
50-line shell driver and rediscovering the `aether.toml` trick. It also
puts sqlite into the nightly's `make contrib-check-valgrind` sweep, which
it is currently outside of.

**Why it is parked:** the avcodec fix already covers the mechanism, sqlite
*is* tested today (just elsewhere), and consolidating means rewriting a
working test — pure cleanup with no new coverage. Do it when someone next
adds a native-backed contrib module and has to choose between the two
patterns.

### `std.bignum` — deferred optimizations

The arbitrary-precision integer surface (`std/bignum/module.ae`) is functionally
Expand Down
244 changes: 244 additions & 0 deletions contrib/avcodec/aether_avcodec.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading