149 lines
9.4 KiB
Bash
Executable file
149 lines
9.4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
# crossArchive.sh -- cross-compile calog's compression/archive stack (libarchive + its 5 codecs:
|
|
# zlib, bzip2, lz4, zstd, xz/liblzma) for musl (fully static Linux, zero runtime deps) and Windows
|
|
# x64, using a single zig toolchain as the cross-compiler. Companion to crossBuild.sh, which proves
|
|
# the core+engines+sockets; this proves the archive library, the one CMake-heavy vendored stack.
|
|
#
|
|
# The musl artifact is fully static and RUNS on the build host, so this script builds AND runs a
|
|
# static testArchive (real round-trip through every codec). The Windows artifact is a testArchive.exe
|
|
# verified as a valid PE (running it needs a Windows host or wine).
|
|
#
|
|
# Scope: this cross-builds libarchive + the five codecs only. The XAR format (native builds enable it
|
|
# via libxml2 + OpenSSL + iconv) is NOT included here -- cross XAR would need those three cross-built
|
|
# too. So XAR is a native-only feature; the cross artifacts cover every codec and the other formats.
|
|
#
|
|
# Requirements: zig (https://ziglang.org/download/) and cmake. Point ZIG at the binary or PATH it:
|
|
# ZIG=/path/to/zig ./tools/crossArchive.sh
|
|
#
|
|
# Why zig for the CMake libs: xz + libarchive build out of tree with CMake. zig is wrapped as a
|
|
# single-binary compiler (bin/zcc-*) so CMake sees a normal cc. The musl toolchain deliberately does
|
|
# NOT set CMAKE_SYSTEM_NAME -- musl-static binaries run on this Linux host, so the build stays
|
|
# "native" and CMake's try_run feature-detection works. The Windows toolchain DOES set it, so CMake
|
|
# enters cross mode and skips its run-only checks (libarchive guards its one CHECK_C_SOURCE_RUNS on
|
|
# CMAKE_CROSSCOMPILING; xz has none), so nothing needs pre-seeding.
|
|
|
|
set -u
|
|
cd "$(dirname "$0")/.."
|
|
R=$(pwd)
|
|
ZIG=${ZIG:-zig}
|
|
X=${OUT:-build/cross}
|
|
XABS="$R/$X"
|
|
|
|
if ! command -v "$ZIG" >/dev/null 2>&1; then
|
|
echo "error: zig not found. Set ZIG=/path/to/zig (see https://ziglang.org/download/)." >&2
|
|
exit 1
|
|
fi
|
|
command -v cmake >/dev/null 2>&1 || { echo "error: cmake not found." >&2; exit 1; }
|
|
ZIGABS=$(command -v "$ZIG"); ZIGABS=$(readlink -f "$ZIGABS" 2>/dev/null || echo "$ZIGABS")
|
|
echo "zig: $($ZIG version)"
|
|
echo "cmake: $(cmake --version | head -1)"
|
|
|
|
mkdir -p "$XABS/bin"
|
|
# --- single-binary compiler/archiver wrappers with the resolved zig path baked in (ephemeral) ---
|
|
gen() { printf '#!/bin/sh\nexec "%s" %s "$@"\n' "$ZIGABS" "$2" > "$XABS/bin/$1"; chmod +x "$XABS/bin/$1"; }
|
|
gen zcc-musl "cc -target x86_64-linux-musl"
|
|
gen zcc-win "cc -target x86_64-windows-gnu"
|
|
gen zar "ar"
|
|
gen zranlib "ranlib"
|
|
# musl toolchain: no CMAKE_SYSTEM_NAME -> native build, try_run works with static musl on the host.
|
|
cat > "$XABS/toolchain-musl.cmake" <<EOF
|
|
set(CMAKE_C_COMPILER "$XABS/bin/zcc-musl")
|
|
set(CMAKE_AR "$XABS/bin/zar")
|
|
set(CMAKE_RANLIB "$XABS/bin/zranlib")
|
|
set(CMAKE_EXE_LINKER_FLAGS_INIT "-static")
|
|
EOF
|
|
# windows toolchain: CMAKE_SYSTEM_NAME=Windows -> cross mode, run-only checks auto-skipped.
|
|
cat > "$XABS/toolchain-win.cmake" <<EOF
|
|
set(CMAKE_SYSTEM_NAME Windows)
|
|
set(CMAKE_SYSTEM_PROCESSOR x86_64)
|
|
set(CMAKE_C_COMPILER "$XABS/bin/zcc-win")
|
|
set(CMAKE_AR "$XABS/bin/zar")
|
|
set(CMAKE_RANLIB "$XABS/bin/zranlib")
|
|
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
|
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
|
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
|
EOF
|
|
|
|
pass=0; fail=0
|
|
CORE="src/broker.c src/value.c src/context.c"
|
|
LUASRC=$(ls vendor/lua/src/*.c | grep -vE '/(lua|luac)\.c$' | tr '\n' ' ')
|
|
|
|
# build_codecs <cc-wrapper> <outdir> -- the 4 object-rule codecs (zlib needs -DHAVE_UNISTD_H so it
|
|
# includes <unistd.h> for lseek; configure normally sets that, our object-rule build must pass it).
|
|
build_codecs() {
|
|
local CC=$1 O=$2 c
|
|
mkdir -p "$O/obj" "$O/lib"
|
|
for c in vendor/zlib/*.c; do "$CC" -std=c11 -D_GNU_SOURCE -DHAVE_UNISTD_H -w -O2 -Ivendor/zlib -c "$c" -o "$O/obj/z_$(basename "$c" .c).o" || return 1; done
|
|
"$XABS/bin/zar" rcs "$O/lib/libz.a" "$O"/obj/z_*.o
|
|
for c in vendor/bzip2/*.c; do "$CC" -std=c11 -D_GNU_SOURCE -w -O2 -Ivendor/bzip2 -c "$c" -o "$O/obj/bz_$(basename "$c" .c).o" || return 1; done
|
|
"$XABS/bin/zar" rcs "$O/lib/libbz2.a" "$O"/obj/bz_*.o
|
|
for c in vendor/lz4/*.c; do "$CC" -std=c11 -D_GNU_SOURCE -w -O2 -Ivendor/lz4 -c "$c" -o "$O/obj/l4_$(basename "$c" .c).o" || return 1; done
|
|
"$XABS/bin/zar" rcs "$O/lib/liblz4.a" "$O"/obj/l4_*.o
|
|
for c in vendor/zstd/common/*.c vendor/zstd/compress/*.c vendor/zstd/decompress/*.c; do "$CC" -std=c11 -D_GNU_SOURCE -w -O2 -DZSTD_DISABLE_ASM -Ivendor/zstd -c "$c" -o "$O/obj/zs_$(basename "$c" .c).o" || return 1; done
|
|
"$XABS/bin/zar" rcs "$O/lib/libzstd.a" "$O"/obj/zs_*.o
|
|
}
|
|
|
|
# build_cmake_libs <toolchain> <outdir> -- xz/liblzma then libarchive, each codec backend pinned to
|
|
# the just-built cross libs (headers are arch-independent -> include dirs stay the vendored source).
|
|
build_cmake_libs() {
|
|
local TC=$1 O=$2
|
|
cmake -S vendor/xz -B "$O/xz" -DCMAKE_TOOLCHAIN_FILE="$TC" \
|
|
-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF \
|
|
-DENABLE_THREADS=OFF -DENABLE_NLS=OFF -DENABLE_DOXYGEN=OFF >"$O/xz-cfg.log" 2>&1 || { echo " xz configure FAILED (see $O/xz-cfg.log)"; return 1; }
|
|
cmake --build "$O/xz" --target liblzma -j >"$O/xz-build.log" 2>&1 || { echo " xz build FAILED (see $O/xz-build.log)"; return 1; }
|
|
cmake -S vendor/libarchive -B "$O/libarchive" -DCMAKE_TOOLCHAIN_FILE="$TC" \
|
|
-DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -DENABLE_TEST=OFF -DENABLE_INSTALL=OFF \
|
|
-DENABLE_TAR=OFF -DENABLE_CPIO=OFF -DENABLE_CAT=OFF -DENABLE_UNZIP=OFF \
|
|
-DENABLE_ACL=OFF -DENABLE_XATTR=OFF -DENABLE_ICONV=OFF -DENABLE_LIBB2=OFF \
|
|
-DENABLE_LIBXML2=OFF -DENABLE_EXPAT=OFF -DENABLE_OPENSSL=OFF \
|
|
-DENABLE_LZO=OFF -DENABLE_NETTLE=OFF -DENABLE_MBEDTLS=OFF -DENABLE_PCREPOSIX=OFF -DENABLE_PCRE2POSIX=OFF \
|
|
-DENABLE_ZLIB=ON -DZLIB_INCLUDE_DIR="$R/vendor/zlib" -DZLIB_LIBRARY="$O/lib/libz.a" \
|
|
-DENABLE_BZip2=ON -DBZIP2_INCLUDE_DIR="$R/vendor/bzip2" -DBZIP2_LIBRARIES="$O/lib/libbz2.a" \
|
|
-DENABLE_LZMA=ON -DLIBLZMA_INCLUDE_DIR="$R/vendor/xz/src/liblzma/api" -DLIBLZMA_LIBRARY="$O/xz/liblzma.a" \
|
|
-DENABLE_ZSTD=ON -DZSTD_INCLUDE_DIR="$R/vendor/zstd" -DZSTD_LIBRARY="$O/lib/libzstd.a" \
|
|
-DENABLE_LZ4=ON -DLZ4_INCLUDE_DIR="$R/vendor/lz4" -DLZ4_LIBRARY="$O/lib/liblz4.a" \
|
|
>"$O/la-cfg.log" 2>&1 || { echo " libarchive configure FAILED (see $O/la-cfg.log)"; return 1; }
|
|
cmake --build "$O/libarchive" --target archive_static -j >"$O/la-build.log" 2>&1 || { echo " libarchive build FAILED (see $O/la-build.log)"; return 1; }
|
|
}
|
|
|
|
# the compression stack link line (libarchive FIRST for static link order), per target outdir.
|
|
archlibs() { echo "$1/libarchive/libarchive/libarchive.a $1/xz/liblzma.a $1/lib/libzstd.a $1/lib/liblz4.a $1/lib/libbz2.a $1/lib/libz.a"; }
|
|
ARCHINC="-Isrc -Isrc/lua -Ilibs -Ivendor/lua/src -Ivendor/libarchive/libarchive"
|
|
|
|
echo "== musl (fully static Linux, built AND run) =="
|
|
if build_codecs "$XABS/bin/zcc-musl" "$XABS/musl" && build_cmake_libs "$XABS/toolchain-musl.cmake" "$XABS/musl"; then
|
|
if "$XABS/bin/zcc-musl" -static -O2 -pthread -w $ARCHINC -DLUA_USE_POSIX \
|
|
$CORE src/lua/luaEngine.c src/lua/luaAdapter.c libs/calogArchive.c libs/calogHandle.c tests/testArchive.c \
|
|
$LUASRC $(archlibs "$XABS/musl") -lm -o "$XABS/musl/testArchive-musl" 2>"$XABS/musl/testArchive-link.err"; then
|
|
if "$XABS/musl/testArchive-musl" >/dev/null 2>&1; then
|
|
echo " [musl RUN ok] testArchive (libarchive + zlib/bzip2/lz4/zstd/xz, fully static)"; pass=$((pass+1))
|
|
else echo " [musl RAN, nonzero] testArchive"; fail=$((fail+1)); fi
|
|
else echo " [musl LINK FAIL] testArchive (see $XABS/musl/testArchive-link.err)"; fail=$((fail+1)); fi
|
|
else fail=$((fail+1)); fi
|
|
|
|
echo "== Windows x64 (.exe built against vendored winpthreads; run needs wine) =="
|
|
# testArchive uses calog's pthread actor model -> needs winpthreads (vendored), like crossBuild.sh.
|
|
rm -rf "$XABS/wpobj"; mkdir -p "$XABS/wpobj" "$XABS/win"
|
|
wpok=1
|
|
for c in vendor/winpthreads/src/*.c; do
|
|
"$XABS/bin/zcc-win" -c -O2 -w -Ivendor/winpthreads/include -Ivendor/winpthreads/src \
|
|
-DWINPTHREAD_STATIC=1 -DIN_WINPTHREAD=1 "$c" -o "$XABS/wpobj/$(basename "$c" .c).o" || { wpok=0; break; }
|
|
done
|
|
"$XABS/bin/zar" rcs "$XABS/win/libwinpthreads.a" "$XABS"/wpobj/*.o 2>/dev/null
|
|
# libarchive on Windows uses system libs the POSIX build does not: CNG crypto (bcrypt) for its AES/
|
|
# PBKDF2, and XmlLite + OLE (xmllite/ole32) for XAR, which auto-replaces the libxml2/expat we disable.
|
|
WINSYS="-lbcrypt -lxmllite -lole32 -ladvapi32 -lcrypt32 -lshlwapi"
|
|
if [ "$wpok" = 1 ] && build_codecs "$XABS/bin/zcc-win" "$XABS/win" && build_cmake_libs "$XABS/toolchain-win.cmake" "$XABS/win"; then
|
|
if "$XABS/bin/zcc-win" -O2 -w $ARCHINC -Ivendor/winpthreads/include -DWINPTHREAD_STATIC=1 \
|
|
$CORE src/lua/luaEngine.c src/lua/luaAdapter.c libs/calogArchive.c libs/calogHandle.c tests/testArchive.c \
|
|
$LUASRC $(archlibs "$XABS/win") "$XABS/win/libwinpthreads.a" $WINSYS -o "$XABS/win/testArchive.exe" 2>"$XABS/win/testArchive-link.err"; then
|
|
if file "$XABS/win/testArchive.exe" | grep -q 'PE32+ executable'; then
|
|
echo " [win BUILT] testArchive.exe (libarchive + 5 codecs, valid PE)"; pass=$((pass+1))
|
|
else echo " [win ??] testArchive.exe (not a PE?)"; fail=$((fail+1)); fi
|
|
else echo " [win LINK FAIL] testArchive.exe (see $XABS/win/testArchive-link.err)"; fail=$((fail+1)); fi
|
|
else fail=$((fail+1)); fi
|
|
|
|
echo
|
|
echo "== crossArchive: $pass ok, $fail failed (artifacts in $X/) =="
|
|
[ "$fail" -eq 0 ]
|