Files
JetCore/jetc/build-shared.sh
T
Brad Arant b0cadc3f08 Multi-day accumulated fixes: tag dispatch, session/pooling correctness, SPA rollout, jetc compiler
JetCore engine (Tag.cpp/.h, Global.cpp/.h, __*.cpp tag classes):
- Numerous __mysql.cpp connection-pooling correctness fixes (stale
  result sets, double-indirection sessionid bugs, field caching,
  pool keying) and a session-registration-before-connection-confirmed
  ordering fix (dangling pointer on a failed connect)
- Tag.cpp: large body of fixes to the tag-dispatch/container-scanning
  logic (bare-name fallback, database aliasing, single-quote handling,
  @-prefix session variable resolution, TAGDEF caching, nested split-tag
  scanning for if/while/until/ifrow so an inner one doesn't corrupt an
  outer one's own boundary scan) plus the process-first rendering
  order fix (a <process> now runs before <checksession>/page
  resolution, fixing a real "blank page after successful login" bug)
- Global.h/.cpp: added imapSessions (parallel to the existing __mysql*
  session map) for the new <imap> tag family
- __whiledir.cpp/__include.cpp: caching and directory-name-aliasing
  fixes
- __call.cpp/.h: fixed a dangling-pointer bug
- __write.cpp: fixed an O_WRONLY-only open that couldn't create a new
  file
- __ifrow.cpp/__sql.cpp: fixed the same sessionid double-indirection
  bug __mysql.cpp had (resolveKeyword's result was being used as a map
  key lookup instead of the resolved value itself)

jetc compiler (jetc/JetParser.cpp/.h, JetCodegen.cpp/.h, JetAST.h,
jetc.cpp, build-shared.sh, build-compiled.sh):
- Parser fixes: inline <include>, nested-quote handling, void-tag
  recognition
- Codegen fixes and expanded AST support
- build-shared.sh: atomic rename into place for a freshly-built .jtc
  (a live server dlopen()ing the same path mid-rebuild was corrupting
  its own already-mapped view of the old file) and a staleness check
  so a cached JetCore .o doesn't silently keep serving yesterday's
  fixes forever
- Added -lssl to both build scripts' link lines (needed once the new
  <imap> tag's client-side TLS code existed - previously nothing in
  this codebase used OpenSSL's SSL/TLS client API, only libcrypto)

Site content (jetc/barant-site/): SPA (fetch-and-swap navigation)
rollout across essentially every .page/.jet/.section/.tag/.proc/.method
file - dynamic-content fixes, fragment-mode stripping, native
$[@name] session variables replacing older mechanisms, and this
session's own checkout.page redesign, login start-param redirect fix,
and per-page side-menu (menu.bar/$[PAGE].menu) refresh support.
Completed the earlier main.css/control.css move from assets/ to
assets/images/ (git still showed the old paths as tracked-but-deleted
until now).

Deliberately left out of this commit: dozens of .pre-<description>-
<date> manual backup files (this session's and earlier ones' own
before/after snapshots, not meant for permanent history), compiled
.jtc build outputs, ad hoc test binaries and scripts under jetc/
(login_asan, wcwc_test, optest2_bin, etc.), and jetc/__pycache__/ -
none of these are meant to be tracked; a .gitignore covering them
would be worth adding separately.
2026-09-03 05:20:48 +00:00

114 lines
5.1 KiB
Bash
Executable File

#!/bin/bash
# Compiles a .jet file into a shared object (conventionally named .jtc -
# "jet compiled" - to mark it as an APIServer-loadable content module, not
# a generic .so) exporting a stable, dlsym()-able render entry point -
# `jetc_render_<basename>(jet::Global &global, coreutils::MString &out)`
# - for a long-running server to load and call directly instead of
# spawning a jet-2.0 process per request.
#
# Usage: ./build-shared.sh <input.jet> <output.jtc>
#
# The host server links/dlopen()s the .jtc and calls the exported symbol
# (see the "entry symbol:" line jetc prints) with its own jet::Global -
# this script does not decide that lifecycle, only builds the module.
# coreutils::Exception propagates out of the call uncaught; the host
# decides how to handle a rendering failure (log it, 500, etc.).
set -e
JC="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CU="$JC/../CoreUtils"
HERE="$JC/jetc"
if [ $# -ne 2 ]; then
echo "usage: $0 <input.jet> <output.jtc>"
exit 1
fi
INPUT="$1"
OUTPUT="$2"
STEM="$(basename "$OUTPUT" .jtc)"
if [ ! -x "$HERE/jetc" ]; then
echo "Building jetc..."
g++ -g -std=c++23 -o "$HERE/jetc" "$HERE/jetc.cpp" "$HERE/JetParser.cpp" "$HERE/JetCodegen.cpp"
fi
echo "Compiling $INPUT -> $STEM.compiled.cpp (shared mode)"
"$HERE/jetc" --shared "$INPUT" "$HERE/$STEM.compiled.cpp"
echo "Building JetCore runtime objects as position-independent code..."
# Rebuild whenever the SOURCE is newer than the cached object, not just
# when the object is missing - a pure existence check silently keeps
# serving a stale compile forever once the .o exists once, even after the
# .cpp changes. Confirmed this bit for real: Tag.pic.o (and 6 other
# JetCore objects) sat uncompiled since 2026-08-25 while Tag.cpp itself
# picked up same-day fixes (the <try> tag dispatch among them) - every
# .jtc built off the stale cache silently ran yesterday's JetCore code,
# with <try> falling through as unrecognized literal text at runtime.
list=""
for f in "$JC"/*.cpp; do
base=$(basename "$f")
if [ "$base" = "jet-2.0.cpp" ]; then continue; fi
obj="$HERE/${base%.cpp}.pic.o"
if [ ! -f "$obj" ] || [ "$f" -nt "$obj" ]; then
g++ -g -fPIC -c -std=c++23 -I"$CU" -I"$JC" "$f" -o "$obj" &
fi
list="$list $obj"
done
# libCoreUtils.a (built by CoreUtils/compile) is not position-independent -
# ld refuses to link non-PIC static-library code into a shared object
# ("relocation ... can not be used when making a shared object"). Rather
# than touching CoreUtils's own build (its .a is fine and used as-is by
# jet-2.0 and everything else), build a PIC copy of its objects here and
# archive them - archived the same way libCoreUtils.a itself is, so the
# linker only pulls in objects something actually references, same as a
# normal -lCoreUtils link. This matters: force-linking every CoreUtils
# .cpp directly (as JetCore's own objects are, below) surfaces an
# unrelated, pre-existing incomplete class (IMFMessage - a known
# partially-migrated class, see project memory) as an unresolved vtable
# at dlopen() time, even though nothing here actually uses it - a normal
# archive link never pulls IMFMessage.o in at all, so it never hits this.
cu_pic_list=""
cu_rebuilt=false
for f in "$CU"/*.cpp; do
base=$(basename "$f")
obj="$HERE/cu_${base%.cpp}.pic.o"
if [ ! -f "$obj" ] || [ "$f" -nt "$obj" ]; then
g++ -g -fPIC -c -std=c++23 -I"$CU" "$f" -o "$obj" &
cu_rebuilt=true
fi
cu_pic_list="$cu_pic_list $obj"
done
wait
# Only re-archive when something actually changed - ar rcs on an unchanged
# member set is harmless but pointless work every single build otherwise.
if [ "$cu_rebuilt" = true ] || [ ! -f "$HERE/libCoreUtils_pic.a" ]; then
ar rcs "$HERE/libCoreUtils_pic.a" $cu_pic_list
fi
g++ -g -fPIC -c -std=c++23 -I"$CU" -I"$JC" "$HERE/$STEM.compiled.cpp" -o "$HERE/$STEM.compiled.pic.o"
echo "Linking $OUTPUT..."
# Link to a temp file in the SAME directory as $OUTPUT, then rename() it
# into place, rather than linking directly onto $OUTPUT - a live
# APIServer instance may already have this exact path dlopen()ed (hot-
# reload watches this directory). g++/ld opens $OUTPUT with O_TRUNC and
# writes the new object into that same inode, which is also the one
# backing the running server's mmap()ed view of the OLD module -
# corrupting its code pages out from under it mid-flight. Confirmed as
# the real cause of a live, reproducible dlclose() SIGSEGV (garbage PC
# inside _dl_call_fini): the server's own unload-before-reload path
# calls dlclose() on the now-corrupted mapping shortly after a build
# like this one lands. rename() is atomic and, same filesystem, never
# touches the old inode - any process with it still mapped keeps seeing
# the unmodified original until it unmaps, and the watcher's own
# dlclose()+dlopen() cycle (triggered by the CLOSE_WRITE this rename
# still generates) picks up the new file cleanly on its next load.
TMPOUT="$(dirname "$OUTPUT")/.$STEM.jtc.tmp.$$"
g++ -shared -fPIC -o "$TMPOUT" "$HERE/$STEM.compiled.pic.o" $list -std=c++23 \
-L"$HERE" -lCoreUtils_pic -lmysqlclient -lssl -lcrypto
mv -f "$TMPOUT" "$OUTPUT"
echo "Built $OUTPUT"