From 510ba7fd429ee760781b1835baa7739bd984f196 Mon Sep 17 00:00:00 2001 From: Nexoniarz Date: Sat, 20 Jun 2026 12:59:28 +0000 Subject: [PATCH] Update build.sh --- build.sh | 311 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 275 insertions(+), 36 deletions(-) diff --git a/build.sh b/build.sh index e35588a..c690347 100644 --- a/build.sh +++ b/build.sh @@ -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 -# Pikture Build Script - Fast, Small, Easy +set -euo pipefail -echo "======================================" -echo " PIKTURE BUILD CONFIG " -echo "======================================" - -EXTRA_FLAGS="" - -read -p "Enable SIMD acceleration (AVX/NEON)? [y/N]: " USE_SIMD -if [[ "$USE_SIMD" =~ ^[Yy]$ ]]; then - EXTRA_FLAGS="$EXTRA_FLAGS -DPIKT_USE_SIMD" +# ── ANSI colours (silenced when stdout is not a terminal) ──────────── +if [[ -t 1 ]]; then + RED=$'\033[0;31m' GRN=$'\033[0;32m' YLW=$'\033[1;33m' + CYN=$'\033[0;36m' BLD=$'\033[1m' RST=$'\033[0m' +else + RED='' GRN='' YLW='' CYN='' BLD='' RST='' fi -read -p "Enable OpenMP multithreading? [y/N]: " USE_OMP -if [[ "$USE_OMP" =~ ^[Yy]$ ]]; then - EXTRA_FLAGS="$EXTRA_FLAGS -DPIKT_USE_THREADS -fopenmp" +# ── Helpers ────────────────────────────────────────────────────────── +info() { echo "${CYN}[info]${RST} $*"; } +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 -echo "" -echo "Building with flags: -O3 -fPIC $EXTRA_FLAGS" -echo "======================================" +# ── Tool detection ─────────────────────────────────────────────────── +step "Detecting tools" -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) -zig cc -target x86_64-windows $FLAGS -shared pikture.c -o dist/windows_x64/pikture.dll -Wl,--out-implib,dist/windows_x64/pikture.lib -zig cc -target aarch64-windows $FLAGS -shared pikture.c -o dist/windows_arm64/pikture.dll -Wl,--out-implib,dist/windows_arm64/pikture.lib +CLANG=$(command -v clang) +CLANG_VER=$("$CLANG" --version | head -1) +info "Compiler : $CLANG_VER" -# macOS (Shared) -zig cc -target x86_64-macos $FLAGS -shared pikture.c -o dist/macos_x64/libpikture.dylib -zig cc -target aarch64-macos $FLAGS -shared pikture.c -o dist/macos_arm64/libpikture.dylib +# Prefer LLVM's archiver; fall back to the system one. +if command -v llvm-ar &>/dev/null; then AR=$(command -v llvm-ar) +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) -zig cc -target x86_64-linux-gnu $FLAGS -shared pikture.c -o dist/linux_x64/libpikture.so -zig cc -target aarch64-linux-gnu $FLAGS -shared pikture.c -o dist/linux_arm64/libpikture.so +STRIP="" +if command -v llvm-strip &>/dev/null; then STRIP=$(command -v llvm-strip) +elif command -v strip &>/dev/null; then STRIP=$(command -v strip) +fi +[[ -n "$STRIP" ]] && info "Strip : $STRIP" -# Linux (Static) -zig cc -target x86_64-linux-musl $FLAGS -c pikture.c -o pikture_x64.o -ar rcs dist/linux_x64/libpikture.a pikture_x64.o +# ── Compiler flags ─────────────────────────────────────────────────── +CFLAGS="-std=c99 -Wall -Wextra -Wpedantic -fPIC" +LFLAGS="" -zig cc -target aarch64-linux-musl $FLAGS -c pikture.c -o pikture_arm64.o -ar rcs dist/linux_arm64/libpikture.a pikture_arm64.o +if [[ $OPT_DEBUG -eq 1 ]]; then + 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 +compile_shared() { + local triple="$1" out="$2" + "$CLANG" $CFLAGS $LFLAGS --target="$triple" -shared yapf.c -o "$out" +} + +# compile_static +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 \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."