#!/usr/bin/env bash set -eo pipefail # Find the odin binary export PATH="$HOME/.odin:$PATH" SRC_DIR="src" OUT_DIR="out" OUT_NAME="pong" # flags for every odin build; unix-style errors (file:line:col: msg) are what the vis error picker parses ODIN_FLAGS=(-error-pos-style:unix) # ---- ctags ------------------------------------------------------------ # tags = project tags (-t, vis runs it on every .odin save) # + stdlib tags (-T, once, or after an Odin update), shared by all projects TAGS_FILE="tags" STD_TAGS="${XDG_CACHE_HOME:-$HOME/.cache}/odin-tags/std.tags" # --languages=Odin keeps vendor's bundled C/JS out of the index; # --fields=+n adds the line:N field the vis pickers jump to CTAGS_OPTS=(--languages=Odin --fields=+n) # ----------------------------------------------------------------------- BUILD_ONLY=0 OPTIMIZED=0 WEB=0 CLEAN=0 DEBUGGER=0 VALGRIND=0 TAGS="" usage() { echo "Usage: $0 [-b] [-o] [-w] [-d] [-v] [-c] [-t] [-T] [-h]" echo " -b build only, don't run" echo " -o optimized release build (-o:speed, no debug info)" echo " -w web/WASM build (js_wasm32 target)" echo " -d build then launch in debugger instead of running" echo " -v build then run under Valgrind" echo " -c clean build artifacts" echo " -t re-index $SRC_DIR and merge it with the stdlib tags" echo " -T index Odin core + vendor (once, or after an Odin update)" echo " -h show this help" exit 1 } # stdlib tags, header lines stripped so the merged file keeps only one set generate_std_tags() { local root root="$(odin root 2>/dev/null || echo "$HOME/.odin")" root="${root%/}" mkdir -p "$(dirname "$STD_TAGS")" ctags -R -f - "${CTAGS_OPTS[@]}" "$root/core" "$root/vendor" | grep -v '^!_TAG_' > "$STD_TAGS.tmp" mv -f "$STD_TAGS.tmp" "$STD_TAGS" echo "Stdlib tags written -> $STD_TAGS" } # project tags merged with the stdlib tags; both inputs are byte-sorted generate_tags() { if [ ! -f "$STD_TAGS" ]; then echo "No stdlib tags; run $0 -T first" >&2 exit 1 fi # $$ keeps two overlapping on-save runs from sharing temp files local src_tags="$TAGS_FILE.src.$$" local merged="$TAGS_FILE.tmp.$$" ctags -R -f "$src_tags" "${CTAGS_OPTS[@]}" "$SRC_DIR" LC_ALL=C sort -m -u "$src_tags" "$STD_TAGS" > "$merged" mv -f "$merged" "$TAGS_FILE" rm -f "$src_tags" } while getopts "bowdvctTh" opt; do case $opt in b) BUILD_ONLY=1 ;; o) OPTIMIZED=1 ;; w) WEB=1 ;; d) DEBUGGER=1 ;; v) VALGRIND=1 ;; c) CLEAN=1 ;; t) TAGS=src ;; T) TAGS=std ;; h) usage ;; *) usage ;; esac done case "$TAGS" in src) generate_tags; exit 0 ;; std) generate_std_tags; exit 0 ;; esac mkdir -p "$OUT_DIR" if [ "$CLEAN" -eq 1 ]; then echo "Cleaning..." rm -rf "${OUT_DIR:?}"/* exit 0 fi if [ "$WEB" -eq 1 ]; then echo "Building web (WASM)..." odin build "$SRC_DIR" "${ODIN_FLAGS[@]}" \ -target:js_wasm32 \ -out:"$OUT_DIR/$OUT_NAME.wasm" \ $( [ "$OPTIMIZED" -eq 1 ] && echo "-o:speed" || echo "-debug" ) # Copy the HTML shell if one exists if [ -f "web/index_template.html" ]; then cp web/index_template.html "$OUT_DIR/index.html" fi echo "Web build complete -> $OUT_DIR/$OUT_NAME.wasm" exit 0 fi if [ "$OPTIMIZED" -eq 1 ]; then echo "Building optimized ($SRC_DIR -> $OUT_DIR/$OUT_NAME)..." odin build "$SRC_DIR" "${ODIN_FLAGS[@]}" \ -out:"$OUT_DIR/$OUT_NAME" \ -o:speed \ -no-bounds-check else echo "Building debug ($SRC_DIR -> $OUT_DIR/$OUT_NAME)..." odin build "$SRC_DIR" "${ODIN_FLAGS[@]}" \ -out:"$OUT_DIR/$OUT_NAME" \ -debug \ -define:DEBUG_MODE=true fi echo "Build complete." if [ "$BUILD_ONLY" -eq 0 ]; then echo "----------------------------------------" if [ "$DEBUGGER" -eq 1 ]; then lldb "$OUT_DIR/$OUT_NAME" elif [ "$VALGRIND" -eq 1 ]; then VG_STATUS=0 valgrind \ --leak-check=full \ --show-leak-kinds=definite,possible \ --track-origins=yes \ --errors-for-leak-kinds=definite,possible \ --error-exitcode=1 \ --log-file="$OUT_DIR/valgrind.log" \ "./$OUT_DIR/$OUT_NAME" || VG_STATUS=$? echo echo "Valgrind report written to $OUT_DIR/valgrind.log" [ "$VG_STATUS" -ne 0 ] && echo "Valgrind reported errors (exit $VG_STATUS)" exit "$VG_STATUS" else "./$OUT_DIR/$OUT_NAME" fi fi