Update build.sh

This commit is contained in:
Nexoniarz 2026-06-20 12:59:28 +00:00 • committed by GitHub
commit 510ba7fd42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

311
build.sh
View file

@ -1,51 +1,290 @@
#!/bin/bash #!/usr/bin/env bash
# ============================================================
# YAPF build script — Clang / LLVM only
# ============================================================
#
# Usage:
# ./build.sh [options]
#
# Options:
# --debug Debug build: no optimisation, full symbols
# --simd Enable SIMD paths (-DYAPF_USE_SIMD)
# --static-only Build only static libraries
# --shared-only Build only shared libraries
# --help Show this message
#
# macOS → produces universal (arm64 + x86_64) .dylib and .a
# Linux → produces native .so + .a; attempts arm64 cross-compile
# if clang supports the aarch64-linux-gnu target and
# lld is available. Install the cross sysroot with:
# Debian/Ubuntu: sudo apt install gcc-aarch64-linux-gnu
# Fedora: sudo dnf install gcc-aarch64-linux-gnu
# ============================================================
# ZIG IS REQUIRED TO COMPILE set -euo pipefail
# Pikture Build Script - Fast, Small, Easy
echo "======================================" # ── ANSI colours (silenced when stdout is not a terminal) ────────────
echo " PIKTURE BUILD CONFIG " if [[ -t 1 ]]; then
echo "======================================" RED=$'\033[0;31m' GRN=$'\033[0;32m' YLW=$'\033[1;33m'
CYN=$'\033[0;36m' BLD=$'\033[1m' RST=$'\033[0m'
EXTRA_FLAGS="" else
RED='' GRN='' YLW='' CYN='' BLD='' RST=''
read -p "Enable SIMD acceleration (AVX/NEON)? [y/N]: " USE_SIMD
if [[ "$USE_SIMD" =~ ^[Yy]$ ]]; then
EXTRA_FLAGS="$EXTRA_FLAGS -DPIKT_USE_SIMD"
fi fi
read -p "Enable OpenMP multithreading? [y/N]: " USE_OMP # ── Helpers ──────────────────────────────────────────────────────────
if [[ "$USE_OMP" =~ ^[Yy]$ ]]; then info() { echo "${CYN}[info]${RST} $*"; }
EXTRA_FLAGS="$EXTRA_FLAGS -DPIKT_USE_THREADS -fopenmp" ok() { echo "${GRN}[ ok ]${RST} $*"; }
warn() { echo "${YLW}[warn]${RST} $*" >&2; }
die() { echo "${RED}[fail]${RST} $*" >&2; exit 1; }
step() { echo; echo "${BLD}──── $* ────${RST}"; }
# ── Option parsing ───────────────────────────────────────────────────
OPT_DEBUG=0
OPT_SIMD=0
OPT_STATIC_ONLY=0
OPT_SHARED_ONLY=0
for arg in "$@"; do
case "$arg" in
--debug) OPT_DEBUG=1 ;;
--simd) OPT_SIMD=1 ;;
--static-only) OPT_STATIC_ONLY=1 ;;
--shared-only) OPT_SHARED_ONLY=1 ;;
--help)
sed -n '3,30p' "$0" | sed 's/^# \?//'
exit 0
;;
*) die "Unknown option: $arg (try --help)" ;;
esac
done
if [[ $OPT_STATIC_ONLY -eq 1 && $OPT_SHARED_ONLY -eq 1 ]]; then
die "--static-only and --shared-only are mutually exclusive"
fi fi
echo "" # ── Tool detection ───────────────────────────────────────────────────
echo "Building with flags: -O3 -fPIC $EXTRA_FLAGS" step "Detecting tools"
echo "======================================"
mkdir -p dist/windows_x64 dist/windows_arm64 dist/macos_x64 dist/macos_arm64 dist/linux_x64 dist/linux_arm64 require() {
command -v "$1" &>/dev/null || die "$1 not found. $2"
}
FLAGS="-O3 -fPIC $EXTRA_FLAGS" require clang "Install LLVM: https://releases.llvm.org/"
# Windows (Shared + Import Lib) CLANG=$(command -v clang)
zig cc -target x86_64-windows $FLAGS -shared pikture.c -o dist/windows_x64/pikture.dll -Wl,--out-implib,dist/windows_x64/pikture.lib CLANG_VER=$("$CLANG" --version | head -1)
zig cc -target aarch64-windows $FLAGS -shared pikture.c -o dist/windows_arm64/pikture.dll -Wl,--out-implib,dist/windows_arm64/pikture.lib info "Compiler : $CLANG_VER"
# macOS (Shared) # Prefer LLVM's archiver; fall back to the system one.
zig cc -target x86_64-macos $FLAGS -shared pikture.c -o dist/macos_x64/libpikture.dylib if command -v llvm-ar &>/dev/null; then AR=$(command -v llvm-ar)
zig cc -target aarch64-macos $FLAGS -shared pikture.c -o dist/macos_arm64/libpikture.dylib elif command -v ar &>/dev/null; then AR=$(command -v ar)
else die "No archiver found (llvm-ar or ar)"
fi
info "Archiver : $AR"
# Linux (Shared) STRIP=""
zig cc -target x86_64-linux-gnu $FLAGS -shared pikture.c -o dist/linux_x64/libpikture.so if command -v llvm-strip &>/dev/null; then STRIP=$(command -v llvm-strip)
zig cc -target aarch64-linux-gnu $FLAGS -shared pikture.c -o dist/linux_arm64/libpikture.so elif command -v strip &>/dev/null; then STRIP=$(command -v strip)
fi
[[ -n "$STRIP" ]] && info "Strip : $STRIP"
# Linux (Static) # ── Compiler flags ───────────────────────────────────────────────────
zig cc -target x86_64-linux-musl $FLAGS -c pikture.c -o pikture_x64.o CFLAGS="-std=c99 -Wall -Wextra -Wpedantic -fPIC"
ar rcs dist/linux_x64/libpikture.a pikture_x64.o LFLAGS=""
zig cc -target aarch64-linux-musl $FLAGS -c pikture.c -o pikture_arm64.o if [[ $OPT_DEBUG -eq 1 ]]; then
ar rcs dist/linux_arm64/libpikture.a pikture_arm64.o CFLAGS="$CFLAGS -O0 -g"
info "Mode : debug"
else
CFLAGS="$CFLAGS -O3 -DNDEBUG"
LFLAGS="$LFLAGS -Wl,-s" # strip symbols from shared libs
info "Mode : release"
fi
rm *.o [[ $OPT_SIMD -eq 1 ]] && { CFLAGS="$CFLAGS -DYAPF_USE_SIMD"; info "SIMD : enabled"; }
echo "Build complete." # ── Detect OS ────────────────────────────────────────────────────────
OS=$(uname -s)
HOST_ARCH=$(uname -m)
info "Host : $OS / $HOST_ARCH"
# ── Output layout ────────────────────────────────────────────────────
mkdir -p dist/include
cp yapf.h dist/include/yapf.h
ok "Header → dist/include/yapf.h"
BUILD_SHARED=$([[ $OPT_STATIC_ONLY -eq 0 ]] && echo 1 || echo 0)
BUILD_STATIC=$([[ $OPT_SHARED_ONLY -eq 0 ]] && echo 1 || echo 0)
# ── Build helpers ────────────────────────────────────────────────────
# compile_shared <target-triple> <out-path>
compile_shared() {
local triple="$1" out="$2"
"$CLANG" $CFLAGS $LFLAGS --target="$triple" -shared yapf.c -o "$out"
}
# compile_static <target-triple> <out-path>
compile_static() {
local triple="$1" out="$2" obj
obj="${out%.a}.o"
"$CLANG" $CFLAGS --target="$triple" -c yapf.c -o "$obj"
"$AR" rcs "$out" "$obj"
rm -f "$obj"
}
# ── macOS build ──────────────────────────────────────────────────────
if [[ "$OS" == "Darwin" ]]; then
require lipo "lipo is part of Xcode Command Line Tools: xcode-select --install"
LIPO=$(command -v lipo)
mkdir -p dist/macos
step "Building macOS arm64"
if [[ $BUILD_SHARED -eq 1 ]]; then
compile_shared arm64-apple-macos11 /tmp/_yapf_arm64.dylib
ok "arm64 dylib"
fi
if [[ $BUILD_STATIC -eq 1 ]]; then
compile_static arm64-apple-macos11 /tmp/_yapf_arm64.a
ok "arm64 static"
fi
step "Building macOS x86_64"
if [[ $BUILD_SHARED -eq 1 ]]; then
compile_shared x86_64-apple-macos10.15 /tmp/_yapf_x64.dylib
ok "x86_64 dylib"
fi
if [[ $BUILD_STATIC -eq 1 ]]; then
compile_static x86_64-apple-macos10.15 /tmp/_yapf_x64.a
ok "x86_64 static"
fi
step "Creating universal binaries (lipo)"
if [[ $BUILD_SHARED -eq 1 ]]; then
"$LIPO" -create /tmp/_yapf_arm64.dylib /tmp/_yapf_x64.dylib \
-output dist/macos/libyapf.dylib
rm -f /tmp/_yapf_arm64.dylib /tmp/_yapf_x64.dylib
ok "dist/macos/libyapf.dylib (universal)"
fi
if [[ $BUILD_STATIC -eq 1 ]]; then
"$LIPO" -create /tmp/_yapf_arm64.a /tmp/_yapf_x64.a \
-output dist/macos/libyapf.a
rm -f /tmp/_yapf_arm64.a /tmp/_yapf_x64.a
ok "dist/macos/libyapf.a (universal)"
fi
# ── Linux build ──────────────────────────────────────────────────────
elif [[ "$OS" == "Linux" ]]; then
# Normalise arch name to the triple component clang expects.
case "$HOST_ARCH" in
x86_64) NATIVE_TRIPLE="x86_64-linux-gnu" ;;
aarch64) NATIVE_TRIPLE="aarch64-linux-gnu" ;;
armv7*) NATIVE_TRIPLE="armv7-linux-gnueabihf" ;;
*) NATIVE_TRIPLE="$HOST_ARCH-linux-gnu" ;;
esac
# Friendly dir name (x86_64 → linux-x64, aarch64 → linux-arm64, etc.)
case "$HOST_ARCH" in
x86_64) NATIVE_DIR="linux-x64" ;;
aarch64) NATIVE_DIR="linux-arm64" ;;
*) NATIVE_DIR="linux-$HOST_ARCH" ;;
esac
mkdir -p "dist/$NATIVE_DIR"
step "Building Linux $HOST_ARCH (native)"
if [[ $BUILD_SHARED -eq 1 ]]; then
compile_shared "$NATIVE_TRIPLE" "dist/$NATIVE_DIR/libyapf.so"
ok "dist/$NATIVE_DIR/libyapf.so"
fi
if [[ $BUILD_STATIC -eq 1 ]]; then
compile_static "$NATIVE_TRIPLE" "dist/$NATIVE_DIR/libyapf.a"
ok "dist/$NATIVE_DIR/libyapf.a"
fi
# ── Cross-compile to the other common arch ────────────────────────
if [[ "$HOST_ARCH" == "x86_64" ]]; then
CROSS_TRIPLE="aarch64-linux-gnu"
CROSS_DIR="linux-arm64"
elif [[ "$HOST_ARCH" == "aarch64" ]]; then
CROSS_TRIPLE="x86_64-linux-gnu"
CROSS_DIR="linux-x64"
else
CROSS_TRIPLE=""
fi
if [[ -n "$CROSS_TRIPLE" ]]; then
step "Cross-compiling Linux ${CROSS_DIR##linux-} (${CROSS_TRIPLE})"
# Probe by actually compiling a file that exercises the C standard
# library headers — a bare "int x;" succeeds even with a broken
# sysroot because it never touches any include paths.
CROSS_PROBE_SRC=$'#include <stdio.h>\nint x;\n'
CROSS_PROBE_OK=0
if printf '%s' "$CROSS_PROBE_SRC" | \
"$CLANG" --target="$CROSS_TRIPLE" -fuse-ld=lld \
-x c - -c -o /dev/null 2>/dev/null; then
CROSS_PROBE_OK=1
fi
if [[ $CROSS_PROBE_OK -eq 0 ]]; then
warn "Cross-sysroot for ${CROSS_TRIPLE} not available — skipping."
warn "To enable: install the cross toolchain for your distro:"
warn " Debian/Ubuntu: sudo apt install gcc-aarch64-linux-gnu lld"
warn " Fedora: sudo dnf install gcc-aarch64-linux-gnu lld"
warn " Arch: sudo pacman -S aarch64-linux-gnu-gcc lld"
else
mkdir -p "dist/$CROSS_DIR"
# Disable set -e locally so a cross-compile failure is non-fatal.
set +e
CROSS_BUILD_OK=1
if [[ $BUILD_SHARED -eq 1 ]]; then
"$CLANG" $CFLAGS $LFLAGS --target="$CROSS_TRIPLE" -fuse-ld=lld \
-shared yapf.c -o "dist/$CROSS_DIR/libyapf.so" 2>/tmp/_yapf_cross_err
if [[ $? -eq 0 ]]; then
ok "dist/$CROSS_DIR/libyapf.so"
else
warn "Shared cross-compile failed:"; cat /tmp/_yapf_cross_err >&2
CROSS_BUILD_OK=0
fi
fi
if [[ $BUILD_STATIC -eq 1 ]]; then
"$CLANG" $CFLAGS --target="$CROSS_TRIPLE" -fuse-ld=lld \
-c yapf.c -o /tmp/_yapf_cross.o 2>/tmp/_yapf_cross_err
if [[ $? -eq 0 ]]; then
"$AR" rcs "dist/$CROSS_DIR/libyapf.a" /tmp/_yapf_cross.o
rm -f /tmp/_yapf_cross.o
ok "dist/$CROSS_DIR/libyapf.a"
else
warn "Static cross-compile failed:"; cat /tmp/_yapf_cross_err >&2
CROSS_BUILD_OK=0
fi
fi
rm -f /tmp/_yapf_cross_err
set -e
if [[ $CROSS_BUILD_OK -eq 0 ]]; then
warn "Cross-compile produced partial results — check warnings above."
fi
fi
fi
else
die "Unsupported OS: $OS. Use build.bat on Windows."
fi
# ── Summary ──────────────────────────────────────────────────────────
step "Summary"
find dist -type f | sort | while IFS= read -r f; do
size=$(du -sh "$f" 2>/dev/null | cut -f1)
printf " ${GRN}%-44s${RST} %s\n" "$f" "$size"
done
echo
ok "Done."