ludic/tools/native/lib.sh
Orkuncakilkaya 0e3cef813f feat(pkg): windows-x64 builds of ludic.physics (Jolt v5.6.0) and ludic.nativeecho, built on the PC by their native/build.sh
tools/native/lib.sh passes -implib rather than /implib: Git Bash rewrites an argument starting
with / into a Windows path, and lld-link was handed 'C:\Program Files\Git\implib;...'. Both DLLs
import KERNEL32 alone, so no C++ runtime ships beside them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-27 13:29:55 +03:00

82 lines
3.4 KiB
Bash

# tools/native/lib.sh - what every package's native/build.sh shares (phase 15). Sourced, not run.
#
# A native library is built here from a pinned source, never downloaded as a binary: the upstream
# tag is fetched, its SHA-256 checked, and it and the package's shim compiled with clang into
# lib/<target>/. The same script runs on the Mac (Terminal) and on the PC (Git Bash, with the LLVM
# installer's clang), so there is one recipe per library, not two.
set -eu
# macos-arm64, macos-x64, windows-x64 or linux-x64 - the names `native` lines use
native_target() {
if [ -n "${LUDIC_NATIVE_TARGET:-}" ]; then echo "$LUDIC_NATIVE_TARGET"; return; fi
case "$(uname -s)" in
Darwin) if [ "$(uname -m)" = arm64 ]; then echo macos-arm64; else echo macos-x64; fi ;;
MINGW*|MSYS*|CYGWIN*) echo windows-x64 ;;
*) echo linux-x64 ;;
esac
}
# the clang that builds: $LUDIC_CC, else clang on PATH, else the LLVM installer's on Windows
native_cc() {
if [ -n "${LUDIC_CC:-}" ]; then echo "$LUDIC_CC"; return; fi
if command -v clang >/dev/null 2>&1; then echo clang; return; fi
if [ -x "/c/Program Files/LLVM/bin/clang.exe" ]; then echo "/c/Program Files/LLVM/bin/clang.exe"; return; fi
echo "native: no clang (set LUDIC_CC)" >&2; exit 1
}
native_cxx() {
local cc; cc="$(native_cc)"
case "$cc" in *clang.exe) echo "${cc%clang.exe}clang++.exe" ;; *clang) echo "${cc}++" ;; *) echo "$cc" ;; esac
}
native_sha256() {
if command -v shasum >/dev/null 2>&1; then shasum -a 256 "$1" | cut -d' ' -f1
else sha256sum "$1" | cut -d' ' -f1; fi
}
# native_fetch <dir> <url> <sha256>: the archive at url, checked, unpacked into <dir> (its one
# top-level directory stripped). A checksum that does not match stops the build.
native_fetch() {
local dir="$1" url="$2" want="$3"
local tgz="$dir.tar.gz"
mkdir -p "$(dirname "$dir")"
if [ ! -f "$tgz" ]; then curl -fsSL "$url" -o "$tgz.part" && mv "$tgz.part" "$tgz"; fi
local got; got="$(native_sha256 "$tgz")"
if [ "$got" != "$want" ]; then
echo "native: $url is $got, pinned $want" >&2; rm -f "$tgz"; exit 1
fi
if [ ! -d "$dir" ]; then
mkdir -p "$dir.part" && tar -xzf "$tgz" -C "$dir.part" --strip-components 1 && mv "$dir.part" "$dir"
fi
}
# native_link <package dir> <name> <objects...>: lib<name>.dylib (install name @rpath, so the
# executable finds it beside itself, in Contents/Frameworks or in lib/<target> while developing)
# or <name>.dll with its import library <name>.lib, into <package>/lib/<target>/
native_link() {
local pkg="$1" name="$2"; shift 2
local t; t="$(native_target)"
local out="$pkg/lib/$t"
mkdir -p "$out"
local cxx; cxx="$(native_cxx)"
case "$t" in
macos-*)
"$cxx" -dynamiclib -O2 -Wl,-install_name,@rpath/lib$name.dylib -Wl,-dead_strip "$@" -o "$out/lib$name.dylib"
echo "native: $out/lib$name.dylib" ;;
windows-*)
# -implib, not /implib: Git Bash rewrites an argument starting with "/" into a Windows path
"$cxx" -shared -O2 "$@" -o "$out/$name.dll" -Wl,-implib:"$out/$name.lib"
echo "native: $out/$name.dll + $name.lib" ;;
*)
"$cxx" -shared -O2 -fPIC -Wl,-soname,lib$name.so "$@" -o "$out/lib$name.so"
echo "native: $out/lib$name.so" ;;
esac
}
# the flags every object is compiled with: optimised, position independent, symbols hidden unless
# the shim exports them
native_cflags() {
case "$(native_target)" in
windows-*) echo "-O2" ;;
*) echo "-O2 -fPIC -fvisibility=hidden" ;;
esac
}