#!/bin/sh set -eu umask 022 PATH=/usr/bin:/bin:/usr/sbin:/sbin export PATH usage() { echo "usage: $0 --output ABSOLUTE_DIR --target-dir ABSOLUTE_DIR" >&2 exit 2 } output= target_dir= while test "$#" -gt 0; do case "$1" in --output) test "$#" -ge 2 || usage output=$2 shift 2 ;; --target-dir) test "$#" -ge 2 || usage target_dir=$2 shift 2 ;; *) usage ;; esac done test -n "$output" || usage test -n "$target_dir" || usage ROOT=$(CDPATH= cd -P -- "$(dirname "$0")/../.." && pwd -P) CORE="$ROOT/core" resolve_new_path() { requested=$1 label=$2 case "$requested" in /*) ;; *) usage ;; esac if test -e "$requested" || test -L "$requested"; then echo "$label must not exist: $requested" >&2 exit 2 fi parent=$(dirname -- "$requested") name=$(basename -- "$requested") case "$name" in ''|.|..) usage ;; esac physical_parent=$(CDPATH= cd -P -- "$parent" 2>/dev/null && pwd -P) || { echo "$label parent must already exist: $parent" >&2 exit 2 } candidate="$physical_parent/$name" case "$candidate" in "$ROOT"|"$ROOT"/*) echo "$label must be outside the repository: $requested" >&2 exit 2 ;; esac printf '%s\n' "$candidate" } output=$(resolve_new_path "$output" output) target_dir=$(resolve_new_path "$target_dir" "target directory") case "$output/:$target_dir/" in "$target_dir/"*:*|*:"$output/"*) echo "output and target directory must be separate" >&2 exit 2 ;; esac mkdir "$output" if ! mkdir "$target_dir"; then rmdir "$output" exit 2 fi output=$(CDPATH= cd -P -- "$output" && pwd -P) target_dir=$(CDPATH= cd -P -- "$target_dir" && pwd -P) for reserved_path in "$output" "$target_dir"; do case "$reserved_path" in "$ROOT"|"$ROOT"/*) echo "reserved packaging path resolved inside the repository: $reserved_path" >&2 exit 2 ;; esac done case "$output/:$target_dir/" in "$target_dir/"*:*|*:"$output/"*) echo "reserved output and target directory must be separate" >&2 exit 2 ;; esac test "$(/usr/bin/uname -s)" = Darwin || { echo "XCFramework packaging requires macOS" >&2 exit 2 } test "$(/usr/bin/uname -m)" = arm64 || { echo "XCFramework packaging requires an arm64 host" >&2 exit 2 } user_record=$(/usr/bin/dscacheutil -q user -a name "$(/usr/bin/id -un)") trusted_home=$(printf '%s\n' "$user_record" | awk '$1 == "dir:" { print $2; exit }') rustup="$trusted_home/.cargo/bin/rustup" test -x "$rustup" || { echo "rustup not found at trusted user path" >&2 exit 2 } cargo_bin=$(/usr/bin/env -i \ HOME="$trusted_home" \ PATH="$PATH" \ RUSTUP_HOME="$trusted_home/.rustup" \ "$rustup" which --toolchain 1.97.1 cargo) rustc_bin=$(/usr/bin/env -i \ HOME="$trusted_home" \ PATH="$PATH" \ RUSTUP_HOME="$trusted_home/.rustup" \ "$rustup" which --toolchain 1.97.1 rustc) rustc_version=$(/usr/bin/env -i HOME="$trusted_home" PATH="$PATH" "$rustc_bin" --version) cargo_version=$(/usr/bin/env -i HOME="$trusted_home" PATH="$PATH" "$cargo_bin" --version) test "$rustc_version" = 'rustc 1.97.1 (8bab26f4f 2026-07-14)' || { echo "unexpected rustc identity: $rustc_version" >&2 exit 2 } test "$cargo_version" = 'cargo 1.97.1 (c980f4866 2026-06-30)' || { echo "unexpected cargo identity: $cargo_version" >&2 exit 2 } xcodebuild=$(/usr/bin/env -i PATH="$PATH" /usr/bin/xcrun --find xcodebuild) xcode_version=$(/usr/bin/env -i HOME="$trusted_home" PATH="$PATH" "$xcodebuild" -version) test "$xcode_version" = 'Xcode 26.6 Build version 17F113' || { echo "unexpected Xcode identity: $xcode_version" >&2 exit 2 } clang=$(/usr/bin/env -i PATH="$PATH" /usr/bin/xcrun --find clang) ar=$(/usr/bin/env -i PATH="$PATH" /usr/bin/xcrun --find ar) clang_identity=$(/usr/bin/env -i HOME="$trusted_home" PATH="$PATH" "$clang" --version) clang_version=$(printf '%s\n' "$clang_identity" | sed -n '1p') sdk=$(/usr/bin/env -i PATH="$PATH" /usr/bin/xcrun --sdk macosx --show-sdk-path) config_dir=$CORE while :; do if test -e "$config_dir/.cargo/config" || test -e "$config_dir/.cargo/config.toml"; then echo "Cargo config is not permitted in the packaging path: $config_dir/.cargo" >&2 exit 2 fi test "$config_dir" = / && break config_dir=$(dirname "$config_dir") done source_commit=$(/usr/bin/env -i HOME="$trusted_home" PATH="$PATH" \ /usr/bin/git -C "$ROOT" rev-parse HEAD) source_epoch=$(/usr/bin/env -i HOME="$trusted_home" PATH="$PATH" \ /usr/bin/git -C "$ROOT" show -s --format=%ct HEAD) rustflags="--remap-path-prefix=$ROOT=. --remap-path-prefix=$target_dir=/cargo-target" cflags="-fdebug-prefix-map=$ROOT=. -ffile-prefix-map=$ROOT=. -fdebug-prefix-map=$target_dir=/cargo-target -ffile-prefix-map=$target_dir=/cargo-target" cargo_home="$target_dir/cargo-home" build_tmp="$target_dir/tmp" mkdir "$cargo_home" "$build_tmp" for cache in registry git; do if test -e "$trusted_home/.cargo/$cache"; then ln -s "$trusted_home/.cargo/$cache" "$cargo_home/$cache" fi done ( cd "$CORE" /usr/bin/env -i \ AR="$ar" \ AR_aarch64_apple_darwin="$ar" \ CARGO_HOME="$cargo_home" \ CARGO_INCREMENTAL=0 \ CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1 \ CARGO_PROFILE_RELEASE_INCREMENTAL=false \ CARGO_PROFILE_RELEASE_LTO=fat \ CARGO_PROFILE_RELEASE_PANIC=abort \ CARGO_TARGET_AARCH64_APPLE_DARWIN_LINKER="$clang" \ CARGO_TARGET_DIR="$target_dir" \ CC="$clang" \ CC_aarch64_apple_darwin="$clang" \ CFLAGS="$cflags" \ CFLAGS_aarch64_apple_darwin="$cflags" \ HOME="$trusted_home" \ MACOSX_DEPLOYMENT_TARGET=14.0 \ PATH="$PATH" \ RUSTC="$rustc_bin" \ RUSTFLAGS="$rustflags" \ SDKROOT="$sdk" \ SOURCE_DATE_EPOCH="$source_epoch" \ TMPDIR="$build_tmp" \ ZERO_AR_DATE=1 \ "$cargo_bin" build \ --target aarch64-apple-darwin \ --release \ --frozen ) headers="$target_dir/xcframework-headers" mkdir -p "$headers" "$output" cp "$ROOT/core/include/versevdi_core.h" "$headers/" cp "$ROOT/core/include/module.modulemap" "$headers/" /usr/bin/env -i \ HOME="$trusted_home" \ PATH="$PATH" \ TMPDIR="$build_tmp" \ "$xcodebuild" -create-xcframework \ -library "$target_dir/aarch64-apple-darwin/release/libversevdi_core.a" \ -headers "$headers" \ -output "$output/VerseVDICore.xcframework" timestamp=$(date -r "$source_epoch" +%Y%m%d%H%M.%S) find "$output/VerseVDICore.xcframework" -exec touch -h -t "$timestamp" {} + { printf 'rustc=%s\n' "$rustc_version" printf 'cargo=%s\n' "$cargo_version" printf 'cargo_path=%s\n' "$cargo_bin" printf 'rustc_path=%s\n' "$rustc_bin" printf 'xcode=%s\n' "$xcode_version" printf 'clang=%s\n' "$clang_version" printf 'sdk=%s\n' "$sdk" printf 'cargo_config=isolated-home-and-no-project-config\n' printf 'target=aarch64-apple-darwin\n' printf 'deployment_target=14.0\n' printf 'source_commit=%s\n' "$source_commit" printf 'source_epoch=%s\n' "$source_epoch" printf 'rustflags=--remap-path-prefix==. --remap-path-prefix==/cargo-target\n' printf 'cflags=-fdebug-prefix-map/-ffile-prefix-map for and \n' } >"$output/build-environment.txt" touch -t "$timestamp" "$output/build-environment.txt" "$output"