#!/usr/bin/env bash set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" WORK_DIR="${WORK_DIR:-$ROOT_DIR/External/NativeStatic/.work}" TARGET_CPU="${TARGET_CPU:-x64}" RID="${RID:-linux-$TARGET_CPU}" OUTPUT_DIR="${OUTPUT_DIR:-$ROOT_DIR/External/NativeStatic/$RID}" SKIASHARP_VERSION="${SKIASHARP_VERSION:-3.119.2}" ANGLE_BRANCH="${ANGLE_BRANCH:-7151}" BUILD_JOBS="${BUILD_JOBS:-$(nproc)}" ANGLE_PATCH_DIR="${ANGLE_PATCH_DIR:-$ROOT_DIR/External/NativeStatic/patches}" LLVM_AR="${LLVM_AR:-llvm-ar-19}" usage() { cat <<'USAGE' Usage: scripts/build-linux-static-graphics.sh [skia|angle|all] Environment: WORK_DIR Source/build cache directory. Default: External/NativeStatic/.work OUTPUT_DIR Final static library directory. Default: External/NativeStatic/linux-$TARGET_CPU SKIASHARP_VERSION SkiaSharp release branch version. Default: 3.119.2 ANGLE_BRANCH ANGLE chromium branch. Default: 7151 TARGET_CPU GN target_cpu. Default: x64. Supported: x64, arm64 RID Output RID. Default: linux-$TARGET_CPU BUILD_JOBS Ninja parallelism. Default: nproc ANGLE_PATCH_DIR ANGLE patch directory. Default: External/NativeStatic/patches LLVM_AR llvm-ar command used to expand thin archives. Default: llvm-ar-19 USAGE } require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then echo "Missing required command: $1" >&2 exit 1 fi } ensure_tools() { require_cmd git require_cmd python3 require_cmd clang require_cmd clang++ require_cmd ar require_cmd "$LLVM_AR" require_cmd ninja require_cmd pkg-config } ensure_depot_tools() { local depot_dir="$WORK_DIR/depot_tools" if [[ ! -d "$depot_dir/.git" ]]; then git clone --depth 1 https://chromium.googlesource.com/chromium/tools/depot_tools.git "$depot_dir" else git -C "$depot_dir" pull --ff-only fi export PATH="$depot_dir:$PATH" } sync_skiasharp() { local src="$WORK_DIR/SkiaSharp-$SKIASHARP_VERSION" if [[ ! -d "$src/.git" ]]; then git clone --depth 1 --branch "release/$SKIASHARP_VERSION" https://github.com/mono/SkiaSharp.git "$src" else git -C "$src" fetch --depth 1 origin "release/$SKIASHARP_VERSION" git -C "$src" checkout -q FETCH_HEAD fi git -C "$src" submodule update --init --depth 1 externals/skia >&2 echo "$src" } sync_skia_deps() { local skia_dir="$1/externals/skia" if [[ ! -x "$skia_dir/bin/gn" ]]; then python3 "$skia_dir/tools/git-sync-deps" fi } build_skia() { ensure_tools ensure_depot_tools local src src="$(sync_skiasharp)" sync_skia_deps "$src" local skia_dir="$src/externals/skia" local out_dir="$skia_dir/out/linux-static-$TARGET_CPU" mkdir -p "$out_dir" "$OUTPUT_DIR" cat >"$out_dir/args.gn" <"$out_dir/args.gn" </dev/null 2>&1; then : elif [[ -f "$deps_patch" ]]; then git -C "$src" apply "$deps_patch" fi } copy_first_existing() { local dest="$1" shift for src in "$@"; do if [[ -f "$src" ]]; then cp "$src" "$dest" echo "Wrote $dest" return 0 fi done echo "None of the expected files exist for $dest:" >&2 printf ' %s\n' "$@" >&2 return 1 } copy_full_archive_from_thin() { local base_dir="$1" local dest="$2" shift 2 local src for src in "$@"; do if [[ -f "$src" ]]; then if [[ "$(head -c 7 "$src")" == "!" ]]; then local tmp="$dest.tmp" local rel_src="${src#$base_dir/}" ( cd "$base_dir" mapfile -t members < <("$LLVM_AR" t "$rel_src") "$LLVM_AR" rcs "$tmp" "${members[@]}" ) mv "$tmp" "$dest" else cp "$src" "$dest" fi echo "Wrote $dest" return 0 fi done echo "None of the expected files exist for $dest:" >&2 printf ' %s\n' "$@" >&2 return 1 } main() { mkdir -p "$WORK_DIR" "$OUTPUT_DIR" case "${1:-all}" in skia) build_skia ;; angle) build_angle ;; all) build_skia build_angle ;; -h|--help|help) usage ;; *) usage >&2 exit 1 ;; esac } main "$@"