#!/bin/bash # # compile-theoria - Windows build script for Theoria Chess Engine # For use in MSYS2 MINGW64 environment with clang # # Builds Windows executables for Theoria16, Theoria17, Theoria17-1024, and Theoria17-3072 # set -e # ============================================================================ # CONFIGURATION # ============================================================================ VERSION="0.1" JOBS=8 # Source directories SF16_SRC="/s/theoria/sf16/src" SF17_SRC="/s/theoria/sf17/src" SF17_1024_SRC="/s/theoria/sf17-threats-1024/src" SF17_3072_SRC="/s/theoria/sf17-threats-3072/src" # NNUE directories NNUE_SF16="/x/ML/models/theoria16" NNUE_SF17="/x/ML/models/theoria17" NNUE_SF17_1024="/x/ML/models/theoria17-threat-1024" NNUE_SF17_3072="/x/ML/models/theoria17-threat-3072" # Build output directories BUILD_SF16="/s/theoria/build/theoria16" BUILD_SF17="/s/theoria/build/theoria17" BUILD_SF17_1024="/s/theoria/build/theoria17-1024" BUILD_SF17_3072="/s/theoria/build/theoria17-3072" # Target NNUE filenames (what the Makefile expects) TARGET_NNUE_SF16="nn-b1a57edbea57.nnue" TARGET_NNUE_SF17="nn-1c0000000000.nnue" TARGET_NNUE_SF17_THREATS="nn-c288c895ea92.nnue" # NNUE file patterns for listing PATTERN_SF16="nnue-pytorch-sf16-leela-epoch-*.nnue" PATTERN_SF17="theoria17-HalfKAv2_hm-L13072-leela96-epoch_*.nnue" PATTERN_SF17_1024="theoria17-Full_Threats-L11024-leela96-epoch_*.nnue" PATTERN_SF17_3072="theoria17-Full_Threats-leela96-epoch_*.nnue" # ============================================================================ # FUNCTIONS # ============================================================================ print_header() { echo "" echo "========================================" echo " Theoria Chess Engine - Windows Build" echo " MSYS2 MINGW64 + Clang" echo "========================================" echo "" } select_project() { echo "Select project to build:" echo " 1) Theoria16 (SF16 base)" echo " 2) Theoria17 (HalfKAv2_hm - SF17)" echo " 3) Theoria17-1024 (SF17 + L1=1024)" echo " 4) Theoria17-3072 (SF17 + L1=3072)" echo " 5) All projects" echo "" read -p "Choice [1-5]: " project_choice case $project_choice in 1) PROJECTS="sf16" ;; 2) PROJECTS="sf17" ;; 3) PROJECTS="sf17-1024" ;; 4) PROJECTS="sf17-3072" ;; 5) PROJECTS="sf16 sf17 sf17-1024 sf17-3072" ;; *) echo "Invalid choice"; exit 1 ;; esac } select_arch() { echo "" echo "Select architecture:" echo " 1) Both AVX2 and BMI2" echo " 2) AVX2 only" echo " 3) BMI2 only" echo "" read -p "Choice [1-3]: " arch_choice case $arch_choice in 1) ARCHS="avx2 bmi2" ;; 2) ARCHS="avx2" ;; 3) ARCHS="bmi2" ;; *) echo "Invalid choice"; exit 1 ;; esac } list_nnue_files() { local nnue_dir="$1" local pattern="$2" # List files and extract epoch numbers, sort numerically ls "$nnue_dir"/$pattern 2>/dev/null | while read f; do basename "$f" done | sort -t'-' -k$(echo "$pattern" | grep -o '-' | wc -l) -n 2>/dev/null || \ ls "$nnue_dir"/$pattern 2>/dev/null | while read f; do basename "$f" done | sort -t'_' -k$(echo "$pattern" | grep -o '_' | wc -l) -n 2>/dev/null } select_nnue() { local project="$1" local nnue_dir="" local pattern="" case $project in sf16) nnue_dir="$NNUE_SF16" pattern="$PATTERN_SF16" ;; sf17) nnue_dir="$NNUE_SF17" pattern="$PATTERN_SF17" ;; sf17-1024) nnue_dir="$NNUE_SF17_1024" pattern="$PATTERN_SF17_1024" ;; sf17-3072) nnue_dir="$NNUE_SF17_3072" pattern="$PATTERN_SF17_3072" ;; esac echo "" echo "Available NNUE files for $project:" echo "----------------------------------------" local files=() local i=1 while IFS= read -r file; do if [ -n "$file" ]; then files+=("$file") echo " $i) $file" ((i++)) fi done < <(list_nnue_files "$nnue_dir" "$pattern") if [ ${#files[@]} -eq 0 ]; then echo "ERROR: No NNUE files found in $nnue_dir" exit 1 fi echo "" read -p "Select NNUE [1-${#files[@]}]: " nnue_choice if [ "$nnue_choice" -lt 1 ] || [ "$nnue_choice" -gt ${#files[@]} ]; then echo "Invalid choice" exit 1 fi SELECTED_NNUE="${files[$((nnue_choice-1))]}" SELECTED_NNUE_PATH="$nnue_dir/$SELECTED_NNUE" # Extract epoch number for exe naming if [[ "$SELECTED_NNUE" =~ epoch[-_]([0-9]+) ]]; then SELECTED_EPOCH="${BASH_REMATCH[1]}" else SELECTED_EPOCH="unknown" fi echo "Selected: $SELECTED_NNUE (epoch $SELECTED_EPOCH)" } build_project() { local project="$1" local arch="$2" local nnue_path="$3" local epoch="$4" local src_dir="" local build_dir="" local target_nnue="" local exe_name="" local make_arch="" case $project in sf16) src_dir="$SF16_SRC" build_dir="$BUILD_SF16" target_nnue="$TARGET_NNUE_SF16" exe_name="theoria16-${VERSION}-epoch-${epoch}-${arch}.exe" ;; sf17) src_dir="$SF17_SRC" build_dir="$BUILD_SF17" target_nnue="$TARGET_NNUE_SF17" exe_name="theoria17-${VERSION}-epoch_${epoch}-${arch}.exe" ;; sf17-1024) src_dir="$SF17_1024_SRC" build_dir="$BUILD_SF17_1024" target_nnue="$TARGET_NNUE_SF17_THREATS" exe_name="theoria17-1024-${VERSION}-epoch_${epoch}-${arch}.exe" ;; sf17-3072) src_dir="$SF17_3072_SRC" build_dir="$BUILD_SF17_3072" target_nnue="$TARGET_NNUE_SF17_THREATS" exe_name="theoria17-3072-${VERSION}-epoch_${epoch}-${arch}.exe" ;; esac case $arch in avx2) make_arch="x86-64-avx2" ;; bmi2) make_arch="x86-64-bmi2" ;; esac echo "" echo "========================================" echo "Building: $exe_name" echo "========================================" echo "Source: $src_dir" echo "NNUE: $(basename "$nnue_path")" echo "Arch: $make_arch" echo "" # Create build directory if needed mkdir -p "$build_dir" # Change to source directory cd "$src_dir" # Copy NNUE file to src with expected name echo "Copying NNUE to src..." cp "$nnue_path" "$target_nnue" # Clean and build echo "Cleaning..." mingw32-make clean >/dev/null 2>&1 || true echo "Building with clang..." mingw32-make -j${JOBS} ARCH=${make_arch} COMP=clang CXX=clang++ build EXE="$exe_name" # Move exe to build directory if [ -f "$exe_name" ]; then mv "$exe_name" "$build_dir/" echo "" echo "SUCCESS: $build_dir/$exe_name" else echo "ERROR: Build failed - exe not created" exit 1 fi # Clean up NNUE from src rm -f "$target_nnue" # Clean object files mingw32-make clean >/dev/null 2>&1 || true } show_summary() { echo "" echo "========================================" echo " Build Summary" echo "========================================" echo "" echo "Projects: $PROJECTS" echo "Architectures: $ARCHS" echo "" local total=0 for p in $PROJECTS; do for a in $ARCHS; do total=$((total + 1)) done done echo "Total builds: $total" echo "" read -p "Proceed? [y/N]: " confirm if [[ ! "$confirm" =~ ^[Yy]$ ]]; then echo "Aborted." exit 0 fi } # ============================================================================ # MAIN # ============================================================================ print_header # Check we're in MINGW64 environment if [[ "$MSYSTEM" != "MINGW64" ]]; then echo "ERROR: This script must be run in MSYS2 MINGW64 environment" echo "Open 'MSYS2 MINGW64' from Start menu" exit 1 fi # Check clang is available if ! command -v clang++ &> /dev/null; then echo "ERROR: clang++ not found. Install with:" echo " pacman -S mingw-w64-x86_64-clang mingw-w64-x86_64-lld" exit 1 fi select_project select_arch # Collect NNUE selections for each project declare -A NNUE_SELECTIONS declare -A EPOCH_SELECTIONS for proj in $PROJECTS; do select_nnue "$proj" NNUE_SELECTIONS[$proj]="$SELECTED_NNUE_PATH" EPOCH_SELECTIONS[$proj]="$SELECTED_EPOCH" done show_summary # Build each project/arch combination for proj in $PROJECTS; do for arch in $ARCHS; do build_project "$proj" "$arch" "${NNUE_SELECTIONS[$proj]}" "${EPOCH_SELECTIONS[$proj]}" done done echo "" echo "========================================" echo " All builds complete!" echo "========================================" echo "" echo "Output locations:" for proj in $PROJECTS; do case $proj in sf16) echo " $BUILD_SF16" ;; sf17) echo " $BUILD_SF17" ;; sf17-1024) echo " $BUILD_SF17_1024" ;; sf17-3072) echo " $BUILD_SF17_3072" ;; esac done echo ""