jextract-25 early-access build (25-jextract+2-4) on JDK 25.0.5+8 against SQLite 3.45.1: 25 functions and 13 constants generated into 4 committed files (the whole header would be 83 files), a small Db wrapper, the four arena kinds used wrongly on purpose, ADDRESS vs C_POINTER zero-length vs unbounded segments and the SIGSEGV from getString on a NULL pointer, sqlite3_open out-parameter, return codes to exceptions, a sqlite3_exec upcall and the VM exit when it throws, the JDK 25 native-access warning and --illegal-native-access=deny, library loading failures, and a JMH benchmark of FFM vs hand-written JNI vs plain Java (indicative only: shared 2-CPU machine). Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_017ic4b6Kg9RWSTJzyz6KP9X
82 lines
4.6 KiB
Bash
Executable File
82 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Regenerates every file in output/ except 10-jmh.txt (that one has its own script, about 4 minutes).
|
|
# JAVA_HOME=/path/to/jdk-25 JEXTRACT=/path/to/jextract ./scripts/run-all.sh
|
|
set -uo pipefail
|
|
unset JAVA_TOOL_OPTIONS # the JVM prints a "Picked up JAVA_TOOL_OPTIONS" banner in some sandboxes; it is noise in a transcript
|
|
HERE="$(cd "$(dirname "$0")/.." && pwd)"; cd "$HERE"
|
|
JAVA_HOME="${JAVA_HOME:?set JAVA_HOME to a JDK 25}"; export PATH="$JAVA_HOME/bin:$PATH"
|
|
JEXTRACT="${JEXTRACT:-$HERE/tools/jextract-25/bin/jextract}"
|
|
SQLITE_H="${SQLITE_H:-/usr/include/sqlite3.h}"
|
|
BUILD="${BUILD:-$HERE/build}"; OUT="$HERE/output"; mkdir -p "$OUT" "$BUILD/classes"
|
|
NA="--enable-native-access=ALL-UNNAMED"
|
|
run() { echo "\$ java $NA -cp build/classes demo.$1${2:+ $2}"; java $NA -cp "$BUILD/classes" demo."$1" ${2:-} 2>&1; }
|
|
|
|
# 01 - what was installed
|
|
{
|
|
echo "\$ jextract --version"; "$JEXTRACT" --version 2>&1
|
|
echo "\$ java -version"; java -version 2>&1
|
|
echo "\$ gcc --version | head -1"; gcc --version | head -1
|
|
echo "\$ dpkg-query -W libsqlite3-dev libsqlite3-0"; dpkg-query -W libsqlite3-dev libsqlite3-0
|
|
echo "\$ grep -E '#define SQLITE_(VERSION|VERSION_NUMBER) ' $SQLITE_H"; grep -E '#define SQLITE_(VERSION|VERSION_NUMBER) ' "$SQLITE_H"
|
|
} > "$OUT/01-tools.txt"
|
|
|
|
# 02 - generate bindings: the trimmed set that is committed, and the whole header for size comparison
|
|
{
|
|
echo "\$ scripts/gen.sh"
|
|
JEXTRACT="$JEXTRACT" SQLITE_H="$SQLITE_H" scripts/gen.sh 2>&1
|
|
echo "\$ find generated -name '*.java' | wc -l"; find generated -name '*.java' | wc -l
|
|
echo "\$ wc -l \$(find generated -name '*.java') | sort -n"; wc -l $(find generated -name '*.java') | sort -n
|
|
F="$(mktemp -d)"
|
|
echo "\$ jextract --output <tmp> -t demo.sqlite.full -l sqlite3 $SQLITE_H # no filters: the whole header"
|
|
"$JEXTRACT" --output "$F" -t demo.sqlite.full -l sqlite3 "$SQLITE_H" > "$F.log" 2>&1
|
|
echo "warnings: $(grep -c warning "$F.log")"; grep 'Skipping sqlite3 ' "$F.log"; grep 'Skipping sqlite3_stmt ' "$F.log"
|
|
echo "files: $(find "$F" -name '*.java' | wc -l)"
|
|
echo "lines: $(cat $(find "$F" -name '*.java') | wc -l)"
|
|
echo "bytes: $(cat $(find "$F" -name '*.java') | wc -c)"
|
|
echo "lines in the one big header class: $(wc -l < "$F/demo/sqlite/full/sqlite3_h.java")"
|
|
rm -rf "$F" "$F.log"
|
|
echo "\$ grep -o 'public static [A-Za-z.]* sqlite3_open[a-z_0-9\$]*(' generated/demo/sqlite/sqlite3_h.java | sort -u"
|
|
grep -o 'public static [A-Za-z.]* sqlite3_open[a-z_0-9$]*(' generated/demo/sqlite/sqlite3_h.java | sort -u
|
|
} > "$OUT/02-generate.txt"
|
|
|
|
# compile generated + hand-written sources
|
|
rm -rf "$BUILD/classes"; mkdir -p "$BUILD/classes"
|
|
javac -d "$BUILD/classes" $(find generated src -name '*.java') || exit 1
|
|
|
|
{ run Hello; echo; echo "\$ java $NA -Djextract.trace.downcalls=true -cp build/classes demo.Hello"; java $NA -Djextract.trace.downcalls=true -cp "$BUILD/classes" demo.Hello 2>&1; } > "$OUT/03-hello.txt"
|
|
|
|
{
|
|
echo "\$ java -cp build/classes demo.Hello # no flag at all, JDK 25 default"
|
|
java -cp "$BUILD/classes" demo.Hello 2>&1
|
|
echo; echo "\$ java --illegal-native-access=deny -cp build/classes demo.Hello"
|
|
java --illegal-native-access=deny -cp "$BUILD/classes" demo.Hello 2>&1 | head -6
|
|
} > "$OUT/04-native-access.txt"
|
|
|
|
run Tour > "$OUT/05-tour.txt"
|
|
run Arenas > "$OUT/06-arenas.txt"
|
|
{
|
|
run Trap; echo
|
|
echo "\$ java $NA -XX:ErrorFile=/tmp/jextract-hs_err.log -cp build/classes demo.NullText # first lines of the crash banner"
|
|
java $NA -XX:ErrorFile=/tmp/jextract-hs_err.log -cp "$BUILD/classes" demo.NullText 2>&1 | sed -n '1,9p'
|
|
echo "exit code: ${PIPESTATUS[0]}"
|
|
} > "$OUT/07-pointer-traps.txt"
|
|
run Errors > "$OUT/08-errors.txt"
|
|
{ run Callbacks; echo; echo "\$ java $NA -cp build/classes demo.Callbacks explode"; java $NA -cp "$BUILD/classes" demo.Callbacks explode 2>&1; echo "exit code: $?"; } > "$OUT/09-callbacks.txt"
|
|
# 11 - how the -l option decides what gets loaded
|
|
{
|
|
T="$(mktemp -d)"
|
|
n=0
|
|
for lib in sqlitez :libsqlite3.so.0; do
|
|
n=$((n+1))
|
|
echo "\$ jextract -t demo.sqlite -l $lib --include-function sqlite3_libversion --header-class-name sqlite3_h $SQLITE_H"
|
|
"$JEXTRACT" --output "$T/gen$n" -t demo.sqlite -l "$lib" --include-function sqlite3_libversion --header-class-name sqlite3_h "$SQLITE_H" 2>&1
|
|
grep -h 'libraryLookup' "$T/gen$n/demo/sqlite/sqlite3_h.java" | sed 's/^ *//'
|
|
mkdir -p "$T/c$n"; javac -d "$T/c$n" "$T/gen$n"/demo/sqlite/*.java src/extra/V.java
|
|
echo "\$ java $NA -cp <classes> V"
|
|
java $NA -cp "$T/c$n" V 2>&1 | head -5
|
|
echo
|
|
done
|
|
rm -rf "$T"
|
|
} > "$OUT/11-library-loading.txt"
|
|
echo done
|