#!/bin/bash # zcc: compiles a ZC (ZygoteC) program into a static binary. the binary holds # the runtime, the program and a memory map sized to them, and needs nothing # from the system but the kernel (linux x86-64 and any host with a static # libc). the program reads and writes through the same syscalls as zy(1). # # src/tools/zcc [-o OUT] [-k] FILE.zc # # -o OUT the binary to write (default: FILE without .zc) # -k keep the build directory and print where it is # CC the C compiler, one with c23 #embed (default: src/tools/findcc.sh). CFLAGS adds to -O2 # # the build is three steps: automap sizes the map to the program and writes the # genome (the compiled program image) for it; the micro core and its linux port # are compiled against that map; and the link is static. make run PROG= builds # the same image without the static link. set -e here="$(cd "$(dirname "$0")/../.." && pwd)" CC=${CC:-$(sh "$here/src/tools/findcc.sh")} out=""; keep=0 while [ $# -gt 0 ]; do case "$1" in -o) [ $# -ge 2 ] || { echo "zcc: -o needs a name" >&2; exit 2; }; out="$2"; shift 2 ;; -k) keep=1; shift ;; -h|--help) printf '%s\n' 'usage: src/tools/zcc [-o OUT] [-k] FILE.zc' 'compiles a source file into a standalone binary; links statically where supported.' 'options:' ' -o OUT output binary path; defaults to the source basename without .zc' ' -k keep the temporary build directory' ' --help, -h show this help and exit' 'environment: CC selects the c compiler (one with #embed); CFLAGS adds compiler flags.'; exit 0 ;; -*) echo "zcc: unknown option $1" >&2; exit 2 ;; *) break ;; esac done [ $# -eq 1 ] || { echo "usage: src/tools/zcc [-o OUT] [-k] FILE.zc" >&2; exit 2; } src="$1" [ -f "$src" ] || { echo "zcc: no such file: $src" >&2; exit 1; } case "$src" in *.zc) ;; *) echo "zcc: the source must end in .zc" >&2; exit 2 ;; esac [ -n "$out" ] || { out="${src%.zc}"; out="$(basename "$out")"; } case "$src" in /*) abs="$src" ;; *) abs="$PWD/$src" ;; esac work="$(mktemp -d "${TMPDIR:-/tmp}/zcc.XXXXXX")" cleanup() { [ "$keep" = 1 ] && echo "zcc: build kept in $work" >&2 || rm -rf "$work"; } trap cleanup EXIT # the map and the genome for this program only ( cd "$here" && bash src/tools/automap.sh run "$work/run" src/runtime/run.zc "$abs" ) >/dev/null cp "$here/src/micro/micro.c" "$here/src/micro/micro_port.h" "$here/src/micro/port_linux.c" \ "$here/src/core/fops.h" "$here/src/core/bops.h" "$here/src/core/stack.h" "$here/src/core/genome.h" "$work/run/" # static where the toolchain allows it; a plain link otherwise, with a note static=-static if ! printf 'int main(void){return 0;}\n' | $CC -x c -static -o "$work/probe" - >/dev/null 2>&1; then static="" echo "zcc: this toolchain cannot link -static; the binary is dynamic" >&2 fi $CC -O2 -w -fwrapv -pthread -DZY_THREADS ${CFLAGS:-} $static "$work/run/micro.c" "$work/run/port_linux.c" \ -I"$work/run" -o "$out" echo "zcc: wrote $out ($(wc -c < "$out" | tr -d ' ') bytes)"