calog/tools/crossWinFull.sh

117 lines
8.8 KiB
Bash

#!/usr/bin/env bash
# crossWinFull.sh -- cross-build the FULL calog CLI as a Windows PE (x86_64-windows-gnu) with zig.
#
# Prereqs under build/cross/win/ (pinned, NOT rebuilt here): openssl (libssl/libcrypto), libxml2,
# pcre2, libssh2, mariadb, postgres (libpq+pgcommon+pgport), tcl (libtcl90), mruby (libmruby),
# libarchive+codecs (xz/zstd/lz4/bz2/z), libwinpthreads. Rebuild them reproducibly from vendor/
# source with `./tools/crossDeps.sh win` before running this script -- that is what makes the full
# cross build reproducible from a clean checkout.
# Compilers: zcc-win / zcxx-win = `zig cc|c++ -target x86_64-windows-gnu`; zar = `zig ar`.
set -eu
cd /home/scott/claude/calog
R=/home/scott/claude/calog
CC="$R/build/cross/bin/zcc-win"
CXX="$R/build/cross/bin/zcxx-win"
AR="$R/build/cross/bin/zar"
ZIG=${ZIG:-${CALOG_ZIG:-/home/scott/zig/current/zig}}
[ -x "$ZIG" ] || { echo "error: zig not found at $ZIG. Set ZIG=/path/to/zig (a PERMANENT install, not a session/temp dir); see https://ziglang.org/download/." >&2; exit 1; }
export CALOG_ZIG="$ZIG" # the build/cross/bin wrappers resolve zig via $CALOG_ZIG
W=$R/build/cross/win
LIB=$W/lib; VO=$W/vmobj; CO=$W/cobj
mkdir -p "$LIB" "$VO" "$CO"
# ---------------------------------------------------------------------------------------------
# 1. Build the engine VMs + sqlite + enet (win32 backend) into static archives.
# s7 needs a <sys/utsname.h> shim on mingw (see build/cross/win/shim/).
# ---------------------------------------------------------------------------------------------
mklib(){ local out=$1 cc=$2; shift 2; local fl=(); while [ "$1" != -- ]; do fl+=("$1"); shift; done; shift
local objs=() s b; rm -rf "$VO/$out"; mkdir -p "$VO/$out"
for s in "$@"; do b=$(basename "$s"); b=${b%.*}; "$cc" "${fl[@]}" -c "$s" -o "$VO/$out/$b.o"; objs+=("$VO/$out/$b.o"); done
"$AR" rcs "$LIB/$out" "${objs[@]}"; echo " [lib] $out"; }
mklib liblua.a "$CC" -std=c99 -w -O2 -Ivendor/lua/src -- $(ls vendor/lua/src/*.c | grep -vE '/(lua|luac)\.c$')
mklib libquickjs.a "$CC" -std=c11 -w -O1 -D_GNU_SOURCE -Ivendor/quickjs -- vendor/quickjs/quickjs.c vendor/quickjs/libregexp.c vendor/quickjs/libunicode.c vendor/quickjs/dtoa.c
mklib libsquirrel.a "$CXX" -std=c++11 -w -O1 -D_SQ64 -DSQUSEDOUBLE -Ivendor/squirrel-src/include -Ivendor/squirrel-src/squirrel -- $(ls vendor/squirrel-src/squirrel/*.cpp)
mklib libmybasic.a "$CC" -std=gnu11 -w -O1 -DMB_DOUBLE_FLOAT -- vendor/ourbasic/ourBasic.c
mklib libberry.a "$CC" -std=c99 -w -O1 -Ivendor/berry/src -Ivendor/berry -- $(ls vendor/berry/src/*.c) vendor/berry/default/be_port.c vendor/berry/default/be_modtab.c
mklib libs7.a "$CC" -std=c99 -w -O1 -D_GNU_SOURCE -I"$W/shim" -Ivendor/s7 -- vendor/s7/s7.c
mklib libwren.a "$CC" -std=c99 -w -O1 -Ivendor/wren -- vendor/wren/wren.c
mklib libjanet.a "$CC" -std=c11 -w -O2 -DJANET_NO_NET -DJANET_NO_PROCESSES -DJANET_NO_DYNAMIC_MODULES -Ivendor/janet -- vendor/janet/janet.c
mklib libsqlite3.a "$CC" -std=c11 -w -O2 -DSQLITE_THREADSAFE=1 -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5 -DSQLITE_OMIT_LOAD_EXTENSION -Ivendor/sqlite -- vendor/sqlite/sqlite3.c
mklib libenet.a "$CC" -std=c11 -w -O2 -Ivendor/enet/include -- $(ls vendor/enet/*.c | grep -vE '/unix\.c$')
# ---------------------------------------------------------------------------------------------
# 2. Patch the pinned libpq.a: rename its private win32 pthread emulation (pg_pthread_*) so it
# stops colliding with winpthreads (ABI-incompatible pthread_mutex_t). Writes a copy; the
# pinned original is left untouched.
# ---------------------------------------------------------------------------------------------
PW=$W/patched; rm -rf "$PW"; mkdir -p "$PW"
TMP=$(mktemp -d); ( cd "$TMP" && cp "$W/postgres/lib/libpq.a" . && "$AR" x libpq.a && \
printf 'pthread_self pg_pthread_self\npthread_setspecific pg_pthread_setspecific\npthread_getspecific pg_pthread_getspecific\npthread_mutex_init pg_pthread_mutex_init\npthread_mutex_lock pg_pthread_mutex_lock\npthread_mutex_unlock pg_pthread_mutex_unlock\n' > s.txt && \
for o in *.o; do objcopy --redefine-syms=s.txt "$o" "$o.n" && mv "$o.n" "$o"; done && \
"$AR" rcs "$PW/libpq.a" *.o ); rm -rf "$TMP"
echo " [patch] libpq.a pthread symbols localized -> $PW/libpq.a"
# ---------------------------------------------------------------------------------------------
# 3. Compile calog's own objects (core + 10 engine adapters/engines + 19 libraries + main).
# ---------------------------------------------------------------------------------------------
INC="-Isrc -Isrc/lua -Isrc/mybasic -Isrc/squirrel -Isrc/js -Isrc/berry -Isrc/s7 -Isrc/wren -Isrc/mruby -Isrc/tcl -Isrc/janet -Ilibs"
WP="-Ivendor/winpthreads/include -DWINPTHREAD_STATIC=1"
# -Wall -Wextra (not -Werror: vendored headers under clang-cross are not warning-clean) so the
# Windows-only #ifdef branches of calog's own sources get compiler scrutiny they never get on Linux.
BASE="-std=c11 -Wall -Wextra -O1 -g -pthread $INC $WP"
ENGDEF="-DCALOG_WITH_LUA -DCALOG_WITH_JS -DCALOG_WITH_SQUIRREL -DCALOG_WITH_MYBASIC -DCALOG_WITH_BERRY -DCALOG_WITH_S7 -DCALOG_WITH_WREN -DCALOG_WITH_MRUBY -DCALOG_WITH_TCL -DCALOG_WITH_JANET"
cc(){ local out=$1 src=$2; shift 2; "$CC" "$@" -c "$src" -o "$CO/$out.o"; }
for f in broker value context; do cc $f src/$f.c $BASE; done
cc luaEngine src/lua/luaEngine.c $BASE; cc jsEngine src/js/jsEngine.c $BASE
cc squirrelEngine src/squirrel/squirrelEngine.c $BASE; cc mybasicEngine src/mybasic/mybasicEngine.c $BASE
cc berryEngine src/berry/berryEngine.c $BASE; cc s7Engine src/s7/s7Engine.c $BASE
cc wrenEngine src/wren/wrenEngine.c $BASE; cc mrubyEngine src/mruby/mrubyEngine.c $BASE
cc tclEngine src/tcl/tclEngine.c $BASE; cc janetEngine src/janet/janetEngine.c $BASE
cc luaAdapter src/lua/luaAdapter.c $BASE -Ivendor/lua/src
cc jsAdapter src/js/jsAdapter.c $BASE -Ivendor/quickjs
cc squirrelAdapter src/squirrel/squirrelAdapter.c $BASE -D_SQ64 -DSQUSEDOUBLE -Ivendor/squirrel-src/include
cc mybasicAdapter src/mybasic/mybasicAdapter.c $BASE -Ivendor/ourbasic -DMB_DOUBLE_FLOAT
cc berryAdapter src/berry/berryAdapter.c $BASE -Ivendor/berry/src -Ivendor/berry
cc s7Adapter src/s7/s7Adapter.c $BASE -Ivendor/s7
cc wrenAdapter src/wren/wrenAdapter.c $BASE -Ivendor/wren
cc mrubyAdapter src/mruby/mrubyAdapter.c $BASE -Ivendor/mruby/include -Ivendor/mruby/build/cross-mingw/include
cc tclAdapter src/tcl/tclAdapter.c $BASE -Ivendor/tcl/generic -DSTATIC_BUILD
cc janetAdapter src/janet/janetAdapter.c $BASE -Ivendor/janet
cc calogMain src/calogMain.c $BASE $ENGDEF
cc calogArchive libs/calogArchive.c $BASE -Ivendor/libarchive/libarchive
cc calogCrypto libs/calogCrypto.c $BASE -I"$W/openssl-src/include"
cc calogCsv libs/calogCsv.c $BASE
cc calogDbFull libs/calogDb.c $BASE -Ivendor/sqlite -I"$W/postgres/include" -Ivendor/mariadb/include -I"$W/mariadb/include" -DCALOG_WITH_SQLITE -DCALOG_WITH_PG -DCALOG_WITH_MYSQL
cc calogExport libs/calogExport.c $BASE
cc calogFs libs/calogFs.c $BASE
cc calogHttp libs/calogHttp.c $BASE -I"$W/openssl-src/include"
cc calogJson libs/calogJson.c $BASE
cc calogKv libs/calogKv.c $BASE
cc calogNet libs/calogNet.c $BASE -Ivendor/enet/include -I"$W/openssl-src/include"
cc calogProc libs/calogProc.c $BASE
cc calogPubsub libs/calogPubsub.c $BASE
cc calogRegex libs/calogRegex.c $BASE -I"$W/pcre2" -DPCRE2_STATIC
cc calogSsh libs/calogSsh.c $BASE -Ivendor/libssh2/include
cc calogTask libs/calogTask.c $BASE $ENGDEF
cc calogTime libs/calogTime.c $BASE
cc calogTimer libs/calogTimer.c $BASE
cc calogXml libs/calogXml.c $BASE -Ivendor/libxml2/include -I"$W/libxml2" -DLIBXML_STATIC
cc calogHandle libs/calogHandle.c $BASE
echo " [obj] all calog objects compiled"
# ---------------------------------------------------------------------------------------------
# 4. Link the full PE. C++ driver (Squirrel) pulls zig's libc++; winpthreads static; the PG
# frontend archives (+ fe_memutils.o) go in a --start-group; Win32 import libs at the end.
# ---------------------------------------------------------------------------------------------
VMLIBS="$LIB/liblua.a $LIB/libquickjs.a $LIB/libsquirrel.a $LIB/libmybasic.a $LIB/libberry.a $LIB/libs7.a $LIB/libwren.a $LIB/libjanet.a $W/mruby/libmruby.a $W/tcl/libtcl90.a $LIB/libsqlite3.a $LIB/libenet.a"
ARCH="$W/libarchive/libarchive/libarchive.a $W/libxml2/libxml2.a $W/xz/liblzma.a $LIB/libzstd.a $LIB/liblz4.a $LIB/libbz2.a $LIB/libz.a"
PG="$PW/libpq.a $W/postgres/lib/libpgcommon_shlib.a $W/postgres/lib/libpgport_shlib.a $W/postgres-build/src/common/fe_memutils.o"
SYS="-lws2_32 -lwinmm -lbcrypt -lxmllite -lole32 -loleaut32 -luuid -lcrypt32 -lsecur32 -ladvapi32 -lshlwapi -luserenv -lnetapi32 -liphlpapi -luser32 -lgdi32 -lshell32 -lwldap32 -ldnsapi -lkernel32"
"$CXX" -O1 -g -o "$W/calog.exe" $CO/*.o \
$VMLIBS "$W/libssh2/libssh2.a" $ARCH "$W/pcre2/libpcre2-8.a" \
-Wl,--start-group $PG -Wl,--end-group \
"$W/mariadb/libmariadb/libmariadbclient.a" "$W/openssl-src/libssl.a" "$W/openssl-src/libcrypto.a" \
"$W/libwinpthreads.a" -lm $SYS
file "$W/calog.exe"