Support cross static script binaries

ober

4c063858982768f32cf86318485aefd0fb58c585

diff --git a/support/build-static-script.sh b/support/build-static-script.sh
index 2c4712f..1a7291d 100755
--- a/support/build-static-script.sh
+++ b/support/build-static-script.sh
@@ -23,9 +23,12 @@ OUTPUT="${2:?Usage: build-static-script.sh <script.ss> <output-name>}"
 
 JERBOA_HOME="${JERBOA_HOME:-/build/mine/jerboa}"
 MUSL_CHEZ="${JERBOA_MUSL_CHEZ_PREFIX:-/build/chez-musl}"
-NATIVE_A="${JERBOA_HOME}/jerboa-native-rs/target/x86_64-unknown-linux-musl/release/libjerboa_native.a"
-LIBDIRS="${JERBOA_HOME}/lib"
+NATIVE_A="${JERBOA_NATIVE_STATIC_ARCHIVE:-${JERBOA_HOME}/jerboa-native-rs/target/x86_64-unknown-linux-musl/release/libjerboa_native.a}"
+LIBDIRS="${BINARY_LIBDIRS:-${LIBDIRS:-${JERBOA_HOME}/lib}}"
 SCHEME="${SCHEME:-scheme}"
+TARGET_MACHINE="${TARGET_MACHINE:-}"
+MUSL_CC="${MUSL_CC:-musl-gcc}"
+MUSL_STRIP="${MUSL_STRIP:-${MUSL_CC%-gcc}-strip}"
 
 echo "=== Jerboa static build: ${SCRIPT} → ${OUTPUT} ==="
 echo "    JERBOA_HOME = ${JERBOA_HOME}"
@@ -33,10 +36,13 @@ echo "    MUSL_CHEZ   = ${MUSL_CHEZ}"
 echo ""
 
 # ── Locate musl Chez libkernel.a ─────────────────────────────────────────────
+MACHINE_TYPE="${TARGET_MACHINE}"
+if [ -z "${MACHINE_TYPE}" ]; then
 MACHINE_TYPE=$(${SCHEME} -q <<'EOF'
 (display (machine-type)) (exit)
 EOF
 )
+fi
 
 CSV_DIR=""
 for d in "${MUSL_CHEZ}/lib/csv"*/"${MACHINE_TYPE}"; do
@@ -54,6 +60,7 @@ fi
 
 echo "  Chez:   ${CSV_DIR}"
 echo "  Native: ${NATIVE_A}"
+echo "  Libs:   ${LIBDIRS}"
 echo ""
 
 if [ ! -f "${NATIVE_A}" ]; then
@@ -71,6 +78,7 @@ echo "==> Step 1: Compile ${SCRIPT} with WPO → ${WPO_SO}"
 echo "    Library object cache: ${OBJ_DIR}"
 
 LD_LIBRARY_PATH="${JERBOA_HOME}/jerboa-native-rs/target/release:${LD_LIBRARY_PATH:-}" \
+  JERBOA_XPATCH="${JERBOA_XPATCH:-}" \
   ${SCHEME} --libdirs "${LIBDIRS}" \
     --script "${JERBOA_HOME}/support/build-boot.ss" "${SCRIPT}" "${WPO_SO}" "${OBJ_DIR}"
 
@@ -91,7 +99,8 @@ convert_to_header() {
     echo "  ${input} → ${header}"
     printf "static const unsigned char %s[] = {\n" "${varname}" > "${header}"
     od -An -tx1 -v "${input}" \
-        | sed 's/^ *//;s/ *$//;s/  */ /g;s/ /,0x/g;s/^/0x/;s/$/,/' >> "${header}"
+        | sed -e '/^[[:space:]]*$/d' \
+              -e 's/^ *//;s/ *$//;s/  */ /g;s/ /,0x/g;s/^/0x/;s/$/,/' >> "${header}"
     printf "};\n" >> "${header}"
     printf "static const unsigned int %s = sizeof(%s);\n" \
         "${sizename}" "${varname}" >> "${header}"
@@ -164,6 +173,10 @@ static unsigned short wrap_ntohs(unsigned short x) { return ntohs(x); }
 static unsigned long  wrap_htonl(unsigned long  x) { return htonl(x); }
 static unsigned long  wrap_ntohl(unsigned long  x) { return ntohl(x); }
 
+#define JERBOA_WEAK __attribute__((weak))
+#define JERBOA_REGISTER_OPTIONAL_SYMBOL(name, fn) \
+    do { if (fn) Sforeign_symbol((name), (void *)(fn)); } while (0)
+
 /* ── FFI registration ─────────────────────────────────────────────────────── */
 /* Called by Sbuild_heap before Scheme code runs.
  * Register every symbol that any imported library calls via foreign-procedure. */
@@ -207,28 +220,28 @@ extern int    jerboa_pbkdf2_verify(int,unsigned char*,unsigned long long,unsigne
 extern unsigned long long jerboa_scrypt(unsigned char*,unsigned long long,unsigned char*,unsigned long long,unsigned long long,unsigned long long,unsigned long long,unsigned char*,unsigned long long);
 extern int    jerboa_timing_safe_equal(unsigned char*,unsigned char*,unsigned long long);
 /* SQLite */
-extern int    jerboa_sqlite_open(unsigned char*,unsigned long long,int);
-extern int    jerboa_sqlite_exec(int,unsigned char*,unsigned long long);
-extern int    jerboa_sqlite_prepare(int,unsigned char*,unsigned long long);
-extern int    jerboa_sqlite_step(int);
-extern int    jerboa_sqlite_finalize(int);
-extern int    jerboa_sqlite_reset(int);
-extern int    jerboa_sqlite_column_count(int);
-extern int    jerboa_sqlite_column_type(int,int);
-extern unsigned char* jerboa_sqlite_column_name(int,int);
-extern unsigned char* jerboa_sqlite_column_text(int,int);
-extern long long jerboa_sqlite_column_int(int,int);
-extern double jerboa_sqlite_column_double(int,int);
-extern unsigned char* jerboa_sqlite_column_blob(int,int);
-extern int    jerboa_sqlite_bind_text(int,int,unsigned char*,unsigned long long);
-extern int    jerboa_sqlite_bind_int(int,int,long long);
-extern int    jerboa_sqlite_bind_double(int,int,double);
-extern int    jerboa_sqlite_bind_null(int,int);
-extern int    jerboa_sqlite_bind_blob(int,int,unsigned char*,unsigned long long);
-extern int    jerboa_sqlite_close(int);
-extern unsigned char* jerboa_sqlite_errmsg(int);
-extern int    jerboa_sqlite_changes(int);
-extern long long jerboa_sqlite_last_insert_rowid(int);
+extern int    jerboa_sqlite_open(unsigned char*,unsigned long long,int) JERBOA_WEAK;
+extern int    jerboa_sqlite_exec(int,unsigned char*,unsigned long long) JERBOA_WEAK;
+extern int    jerboa_sqlite_prepare(int,unsigned char*,unsigned long long) JERBOA_WEAK;
+extern int    jerboa_sqlite_step(int) JERBOA_WEAK;
+extern int    jerboa_sqlite_finalize(int) JERBOA_WEAK;
+extern int    jerboa_sqlite_reset(int) JERBOA_WEAK;
+extern int    jerboa_sqlite_column_count(int) JERBOA_WEAK;
+extern int    jerboa_sqlite_column_type(int,int) JERBOA_WEAK;
+extern unsigned char* jerboa_sqlite_column_name(int,int) JERBOA_WEAK;
+extern unsigned char* jerboa_sqlite_column_text(int,int) JERBOA_WEAK;
+extern long long jerboa_sqlite_column_int(int,int) JERBOA_WEAK;
+extern double jerboa_sqlite_column_double(int,int) JERBOA_WEAK;
+extern unsigned char* jerboa_sqlite_column_blob(int,int) JERBOA_WEAK;
+extern int    jerboa_sqlite_bind_text(int,int,unsigned char*,unsigned long long) JERBOA_WEAK;
+extern int    jerboa_sqlite_bind_int(int,int,long long) JERBOA_WEAK;
+extern int    jerboa_sqlite_bind_double(int,int,double) JERBOA_WEAK;
+extern int    jerboa_sqlite_bind_null(int,int) JERBOA_WEAK;
+extern int    jerboa_sqlite_bind_blob(int,int,unsigned char*,unsigned long long) JERBOA_WEAK;
+extern int    jerboa_sqlite_close(int) JERBOA_WEAK;
+extern unsigned char* jerboa_sqlite_errmsg(int) JERBOA_WEAK;
+extern int    jerboa_sqlite_changes(int) JERBOA_WEAK;
+extern long long jerboa_sqlite_last_insert_rowid(int) JERBOA_WEAK;
 /* Regex */
 extern int    jerboa_regex_compile(unsigned char*,unsigned long long);
 extern int    jerboa_regex_compile_ex(unsigned char*,unsigned long long,int);
@@ -296,28 +309,28 @@ static void custom_init(void) {
     Sforeign_symbol("jerboa_pbkdf2_verify",         (void *)jerboa_pbkdf2_verify);
     Sforeign_symbol("jerboa_scrypt",                (void *)jerboa_scrypt);
     Sforeign_symbol("jerboa_timing_safe_equal",     (void *)jerboa_timing_safe_equal);
-    Sforeign_symbol("jerboa_sqlite_open",           (void *)jerboa_sqlite_open);
-    Sforeign_symbol("jerboa_sqlite_exec",           (void *)jerboa_sqlite_exec);
-    Sforeign_symbol("jerboa_sqlite_prepare",        (void *)jerboa_sqlite_prepare);
-    Sforeign_symbol("jerboa_sqlite_step",           (void *)jerboa_sqlite_step);
-    Sforeign_symbol("jerboa_sqlite_finalize",       (void *)jerboa_sqlite_finalize);
-    Sforeign_symbol("jerboa_sqlite_reset",          (void *)jerboa_sqlite_reset);
-    Sforeign_symbol("jerboa_sqlite_column_count",   (void *)jerboa_sqlite_column_count);
-    Sforeign_symbol("jerboa_sqlite_column_type",    (void *)jerboa_sqlite_column_type);
-    Sforeign_symbol("jerboa_sqlite_column_name",    (void *)jerboa_sqlite_column_name);
-    Sforeign_symbol("jerboa_sqlite_column_text",    (void *)jerboa_sqlite_column_text);
-    Sforeign_symbol("jerboa_sqlite_column_int",     (void *)jerboa_sqlite_column_int);
-    Sforeign_symbol("jerboa_sqlite_column_double",  (void *)jerboa_sqlite_column_double);
-    Sforeign_symbol("jerboa_sqlite_column_blob",    (void *)jerboa_sqlite_column_blob);
-    Sforeign_symbol("jerboa_sqlite_bind_text",      (void *)jerboa_sqlite_bind_text);
-    Sforeign_symbol("jerboa_sqlite_bind_int",       (void *)jerboa_sqlite_bind_int);
-    Sforeign_symbol("jerboa_sqlite_bind_double",    (void *)jerboa_sqlite_bind_double);
-    Sforeign_symbol("jerboa_sqlite_bind_null",      (void *)jerboa_sqlite_bind_null);
-    Sforeign_symbol("jerboa_sqlite_bind_blob",      (void *)jerboa_sqlite_bind_blob);
-    Sforeign_symbol("jerboa_sqlite_close",          (void *)jerboa_sqlite_close);
-    Sforeign_symbol("jerboa_sqlite_errmsg",         (void *)jerboa_sqlite_errmsg);
-    Sforeign_symbol("jerboa_sqlite_changes",        (void *)jerboa_sqlite_changes);
-    Sforeign_symbol("jerboa_sqlite_last_insert_rowid",(void*)jerboa_sqlite_last_insert_rowid);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_open",           jerboa_sqlite_open);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_exec",           jerboa_sqlite_exec);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_prepare",        jerboa_sqlite_prepare);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_step",           jerboa_sqlite_step);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_finalize",       jerboa_sqlite_finalize);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_reset",          jerboa_sqlite_reset);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_column_count",   jerboa_sqlite_column_count);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_column_type",    jerboa_sqlite_column_type);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_column_name",    jerboa_sqlite_column_name);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_column_text",    jerboa_sqlite_column_text);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_column_int",     jerboa_sqlite_column_int);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_column_double",  jerboa_sqlite_column_double);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_column_blob",    jerboa_sqlite_column_blob);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_bind_text",      jerboa_sqlite_bind_text);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_bind_int",       jerboa_sqlite_bind_int);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_bind_double",    jerboa_sqlite_bind_double);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_bind_null",      jerboa_sqlite_bind_null);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_bind_blob",      jerboa_sqlite_bind_blob);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_close",          jerboa_sqlite_close);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_errmsg",         jerboa_sqlite_errmsg);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_changes",        jerboa_sqlite_changes);
+    JERBOA_REGISTER_OPTIONAL_SYMBOL("jerboa_sqlite_last_insert_rowid", jerboa_sqlite_last_insert_rowid);
     Sforeign_symbol("jerboa_regex_compile",         (void *)jerboa_regex_compile);
     Sforeign_symbol("jerboa_regex_compile_ex",      (void *)jerboa_regex_compile_ex);
     Sforeign_symbol("jerboa_regex_free",            (void *)jerboa_regex_free);
@@ -470,7 +483,8 @@ EXTRA_ARCHIVES=""
 [ -f "${LZ4_A}" ] && EXTRA_ARCHIVES="${EXTRA_ARCHIVES} ${LZ4_A}"
 [ -f "${Z_A}"   ] && EXTRA_ARCHIVES="${EXTRA_ARCHIVES} ${Z_A}"
 
-musl-gcc \
+"${MUSL_CC}" \
+    -I. \
     -I"${CSV_DIR}" \
     -O2 \
     -o "${OUTPUT}" \
@@ -484,7 +498,11 @@ musl-gcc \
 # ── Step 5: Strip + verify ────────────────────────────────────────────────────
 echo ""
 echo "==> Step 5: Strip and verify"
-strip "${OUTPUT}"
+if command -v "${MUSL_STRIP}" >/dev/null 2>&1; then
+    "${MUSL_STRIP}" "${OUTPUT}"
+elif command -v strip >/dev/null 2>&1; then
+    strip "${OUTPUT}" 2>/dev/null || true
+fi
 
 SIZE=$(du -sh "${OUTPUT}" | cut -f1)
 echo ""
@@ -494,7 +512,11 @@ file "${OUTPUT}"
 echo ""
 
 # Warn if over target
-SIZE_BYTES=$(stat -c%s "${OUTPUT}")
+if stat -c%s "${OUTPUT}" >/dev/null 2>&1; then
+    SIZE_BYTES=$(stat -c%s "${OUTPUT}")
+else
+    SIZE_BYTES=$(stat -f%z "${OUTPUT}")
+fi
 if [ "${SIZE_BYTES}" -gt $((25 * 1024 * 1024)) ]; then
     echo "WARNING: binary is ${SIZE} — exceeds 25MB target"
 fi