#!/bin/bash # Compiles a .jet file into a shared object exporting a stable, dlsym()-able # render entry point - `jetc_render_(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 # # The host server links/dlopen()s the .so 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 " exit 1 fi INPUT="$1" OUTPUT="$2" STEM="$(basename "$OUTPUT" .so)" 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..." 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" ]; 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="" for f in "$CU"/*.cpp; do base=$(basename "$f") obj="$HERE/cu_${base%.cpp}.pic.o" if [ ! -f "$obj" ]; then g++ -g -fPIC -c -std=c++23 -I"$CU" "$f" -o "$obj" & fi cu_pic_list="$cu_pic_list $obj" done wait ar rcs "$HERE/libCoreUtils_pic.a" $cu_pic_list g++ -g -fPIC -c -std=c++23 -I"$CU" -I"$JC" "$HERE/$STEM.compiled.cpp" -o "$HERE/$STEM.compiled.pic.o" echo "Linking $OUTPUT..." g++ -shared -fPIC -o "$OUTPUT" "$HERE/$STEM.compiled.pic.o" $list -std=c++23 \ -L"$HERE" -lCoreUtils_pic -lmysqlclient -lcrypto echo "Built $OUTPUT"