#!/usr/bin/env bash # Step 8: the thing the whole spike is really asking about -- ONE binary that # is both a compiled Flan program and the OCaml compiler, with clang doing the # final link. # # Everything before this proved a piece. This proves the shape: the Flan # program's own main() is renamed out of the way, a C main() takes the main # thread and runs the program there, and caml_startup happens on a side thread # beside it. That is exactly item 11's inversion, built for real. # # It is NOT the merged architecture -- nothing is wired up, the compiler and the # program do not talk. It is a link and a size and a startup number. set -u here=$(cd "$(dirname "$0")" && pwd) root=$(cd "$here/../.." && pwd) src=${1:-test/programs/edn.flan} cd "$root" || exit 1 out=$(mktemp -d); trap 'rm -rf "$out"' EXIT FLAN=_build/default/bin/main.exe OCAMLLIB=$(ocamlopt -where) SYSLIBS="-lm -lpthread -ldl -lzstd" echo "program: $src" # 1. The Flan program, as it is built today, for the baseline sizes. "$FLAN" build "$src" -o "$out/rel" || exit 1 "$FLAN" build "$src" --dev -o "$out/dev" || exit 1 # 2. The same program as an object, with its main renamed so a C main can own # the process. Emit writes @main literally; sed is enough to move it. "$FLAN" emit "$src" --dev > "$out/prog.ll" || exit 1 sed -i 's/define i32 @main(/define i32 @flan_program_main(/' "$out/prog.ll" grep -q 'define i32 @flan_program_main(' "$out/prog.ll" || { echo "could not find @main in the emitted IR -- adjust the rename"; exit 1; } clang -c -x ir "$out/prog.ll" -o "$out/prog.o" || exit 1 # 3. The runtime the program needs, and the agent beside it. clang -c -O2 runtime/flan_rt.c -o "$out/rt.o" || exit 1 clang -c -O2 runtime/flan_dev.c -o "$out/dev.o" || exit 1 clang -c -O2 vendor/agent/flan_agent.c -o "$out/ag.o" || exit 1 # 4. The whole OCaml compiler as one object. ocamlfind ocamlopt -thread -package unix,threads.posix -linkpkg \ -output-complete-obj \ -I "$root/_build/default/lib/.flan.objs/byte" \ -I "$root/_build/default/lib/.flan.objs/native" \ -o "$out/compiler.o" "$root/_build/default/lib/flan.cmxa" \ "$here/thread_ml.ml" || exit 1 # 5. One link. clang, as the project already does it. clang -I"$OCAMLLIB" "$here/merged_main.c" "$out/prog.o" "$out/rt.o" "$out/dev.o" \ "$out/ag.o" "$out/compiler.o" -o "$out/merged" $SYSLIBS || exit 1 echo echo "sizes:" for f in rel dev merged; do printf ' %-30s %9d bytes\n' "$f" "$(stat -c%s "$out/$f")" done printf ' %-30s %9d bytes\n' "what the compiler adds to a dev build" \ "$(( $(stat -c%s "$out/merged") - $(stat -c%s "$out/dev") ))" echo echo "running the merged binary:" "$out/merged" "$src" echo "exit: $?"