ae8c452fb5
# Conflicts: # fleet-beacon # fleet-beacon~f062955 (feat(fleet): add fleet-beacon with penguin support and remote targets)
130 lines
4.7 KiB
Bash
Executable File
130 lines
4.7 KiB
Bash
Executable File
#!/bin/sh
|
|
# pdecc — one-shot Processing-to-Raylib compiler CLI.
|
|
#
|
|
# Transpile + compile a .pde sketch into an optimized native binary in one
|
|
# step, using the pde2c transpiler and the processing.h single-header runtime.
|
|
# Submitted as a single source file or a sketch directory (multi-tab), the
|
|
# resulting binary is written next to the sketch source by default.
|
|
#
|
|
# ./pdecc sketch in current directory
|
|
# ./pdecc sketch.pde single-file sketch
|
|
# ./pdecc ~/path/to/sketch sketch directory (all .pde tabs together)
|
|
# ./pdecc -o bin sketch.pde write binary to "bin" instead
|
|
# ./pdecc -O0 sketch.pde override default -O2 optimization
|
|
# ./pdecc -n sketch.pde build only (do not run)
|
|
# ./pdecc --keep sketch.pde keep the tmp build dir
|
|
#
|
|
# Exit status: 0 on success, non-zero on transpile/compile failure.
|
|
set -u
|
|
|
|
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
|
|
OPT="2" # default optimization level (no leading 'O')
|
|
OUT="" # explicit -o output path (default: next to source)
|
|
RUN=1 # run after building unless -n
|
|
KEEP=0 # keep tmp dir when --keep
|
|
|
|
# ---- argument parsing -----------------------------------------------------
|
|
TARGET=""
|
|
while [ $# -gt 0 ]; do
|
|
case "$1" in
|
|
-o) shift; [ $# -eq 0 ] && { echo "pdecc: -o needs a path" >&2; exit 1; }
|
|
OUT="$1";;
|
|
-O|-O0|-O1|-O2|-O3|-Os) OPT="${1#-O}";;
|
|
-n|--no-run) RUN=0;;
|
|
--keep) KEEP=1;;
|
|
-h|--help)
|
|
sed -n '2,16p' "$0"; exit 0;;
|
|
-*) echo "pdecc: unknown option: $1" >&2; exit 1;;
|
|
*) [ -n "$TARGET" ] && { echo "pdecc: too many arguments: $1" >&2; exit 1; }
|
|
TARGET="$1";;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# ---- resolve target: dir, .pde file, or current dir -----------------------
|
|
if [ -z "$TARGET" ]; then
|
|
TARGET=$(pwd)
|
|
fi
|
|
TARGET=$(realpath "$TARGET")
|
|
|
|
if [ -d "$TARGET" ]; then
|
|
SKETCH_DIR="$TARGET"
|
|
MAIN_PDE="$SKETCH_DIR/$(basename "$SKETCH_DIR").pde"
|
|
if [ ! -f "$MAIN_PDE" ]; then
|
|
echo "pdecc: expected main tab $MAIN_PDE (folder name must match the main .pde)" >&2
|
|
exit 1
|
|
fi
|
|
BNAME=$(basename "$SKETCH_DIR")
|
|
elif [ -f "$TARGET" ] && [ "${TARGET##*.}" = "pde" ]; then
|
|
MAIN_PDE="$TARGET"
|
|
SKETCH_DIR=$(dirname "$MAIN_PDE")
|
|
BNAME=$(basename "$MAIN_PDE" .pde)
|
|
else
|
|
echo "pdecc: invalid target: $TARGET (expected a .pde file or a sketch directory)" >&2
|
|
exit 1
|
|
fi
|
|
|
|
OUT="${OUT:-$SKETCH_DIR/$BNAME}"
|
|
|
|
# ---- build dir -------------------------------------------------------------
|
|
TMP=$(mktemp -d /tmp/pdecc.XXXXXX)
|
|
cleanup() { [ "$KEEP" = "1" ] || rm -rf "$TMP"; }
|
|
trap cleanup EXIT INT TERM
|
|
|
|
# rebuild transpiler only when its source changed
|
|
if [ "$SCRIPT_DIR/pde2c.c" -nt "$SCRIPT_DIR/pde2c" ] || [ ! -x "$SCRIPT_DIR/pde2c" ]; then
|
|
gcc "$SCRIPT_DIR/pde2c.c" -o "$SCRIPT_DIR/pde2c" || exit 1
|
|
fi
|
|
|
|
# rebuild precompiled header only when processing.h got newer; skip re-parsing
|
|
# raylib/rlgl/raymath on every compile (cuts turnaround from ~3s to ~0.2s).
|
|
if [ "$SCRIPT_DIR/processing.h" -nt "$SCRIPT_DIR/processing.h.gch" ] || \
|
|
[ ! -f "$SCRIPT_DIR/processing.h.gch" ]; then
|
|
if ! gcc $("$SCRIPT_DIR/pdedeps" --includes) -x c-header "$SCRIPT_DIR/processing.h" \
|
|
-o "$SCRIPT_DIR/processing.h.gch" 2>/dev/null; then
|
|
rm -f "$SCRIPT_DIR/processing.h.gch" # stale/broken PCH: fall back to
|
|
fi # slow path (never fatal)
|
|
fi
|
|
|
|
# ---- merge tabs: main tab first, then the rest alphabetically -------------
|
|
{
|
|
printf '//@file %s\n' "$(basename "$MAIN_PDE")"
|
|
cat "$MAIN_PDE"
|
|
for f in $(find "$SKETCH_DIR" -maxdepth 1 -name '*.pde' | sort); do
|
|
[ "$f" = "$MAIN_PDE" ] && continue
|
|
printf '//@file %s\n' "$(basename "$f")"
|
|
cat "$f"
|
|
done
|
|
} > "$TMP/combined.pde"
|
|
|
|
if ! grep -q '[^[:space:]]' "$TMP/combined.pde"; then
|
|
echo "pdecc: no .pde content found in $SKETCH_DIR" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# copy runtime resources so font loading resolves from the build dir
|
|
cp "$SCRIPT_DIR/terminus.ttf" "$TMP/terminus.ttf" 2>/dev/null || true
|
|
|
|
# ---- transpile -------------------------------------------------------------
|
|
if ! "$SCRIPT_DIR/pde2c" "$TMP/combined.pde" > "$TMP/sketch.c" 2> "$TMP/pde2c.err"; then
|
|
echo "pdecc: transpile failed for $BNAME" >&2
|
|
cat "$TMP/pde2c.err" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# ---- compile to an optimized native binary ---------------------------------
|
|
if ! gcc -O"$OPT" $("$SCRIPT_DIR/pdedeps" --includes) "$TMP/sketch.c" -o "$OUT" \
|
|
$("$SCRIPT_DIR/pdedeps" --libs) 2> "$TMP/gcc.err"; then
|
|
echo "pdecc: compilation failed for $BNAME" >&2
|
|
head -20 "$TMP/gcc.err" >&2
|
|
if [ "$KEEP" = "1" ]; then
|
|
echo "pdecc: kept build dir $TMP (set --keep or PDE_KEEP=1 to inspect)" >&2
|
|
fi
|
|
exit 1
|
|
fi
|
|
|
|
echo "pdecc: built $OUT"
|
|
[ "$RUN" = "1" ] && (cd "$SKETCH_DIR" && exec "$OUT")
|
|
exit 0
|