#!/bin/bash #============================================================================ # FOXHUNT HFT TRADING SYSTEM - RELEASE BUILD SCRIPT #============================================================================ # Builds optimized production binaries with maximum performance tuning # # Usage: # ./build_release.sh [OPTIONS] # # Options: # --target-dir DIR Override target directory (default: ./target/release) # --features FEATURES Additional features to enable # --skip-tests Skip running tests before build # --cpu-target TARGET CPU optimization target (native, skylake, etc.) # --help Show this help message #============================================================================ set -euo pipefail # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" TARGET_DIR="${TARGET_DIR:-$PROJECT_ROOT/target/release}" FEATURES="${FEATURES:-cuda}" CPU_TARGET="${CPU_TARGET:-native}" SKIP_TESTS="${SKIP_TESTS:-false}" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1" } log_success() { echo -e "${GREEN}[SUCCESS]${NC} $1" } log_warning() { echo -e "${YELLOW}[WARNING]${NC} $1" } log_error() { echo -e "${RED}[ERROR]${NC} $1" } show_help() { cat << EOF Foxhunt HFT Trading System - Release Build Script Usage: $0 [OPTIONS] OPTIONS: --target-dir DIR Override target directory (default: ./target/release) --features FEATURES Additional features to enable (default: cuda) --skip-tests Skip running tests before build --cpu-target TARGET CPU optimization target (default: native) --help Show this help message EXAMPLES: $0 # Standard release build $0 --cpu-target skylake # Build for Intel Skylake $0 --features "cuda,cudnn" # Build with additional GPU features $0 --skip-tests # Skip tests and build only TARGETS: Available CPU targets: native, skylake, haswell, broadwell, zen2, zen3 EOF } # Parse command line arguments parse_args() { while [[ $# -gt 0 ]]; do case $1 in --target-dir) TARGET_DIR="$2" shift 2 ;; --features) FEATURES="$2" shift 2 ;; --skip-tests) SKIP_TESTS=true shift ;; --cpu-target) CPU_TARGET="$2" shift 2 ;; --help) show_help exit 0 ;; *) log_error "Unknown option: $1" show_help exit 1 ;; esac done } # Check prerequisites check_prerequisites() { log_info "Checking build prerequisites..." # Check Rust toolchain if ! command -v cargo &> /dev/null; then log_error "Cargo is not installed" exit 1 fi # Check Rust version local rust_version=$(rustc --version | cut -d' ' -f2) log_info "Using Rust version: $rust_version" # Check if we're in the project root if [[ ! -f "$PROJECT_ROOT/Cargo.toml" ]]; then log_error "Not in project root or Cargo.toml not found" exit 1 fi # Check for required build tools local required_tools=("pkg-config" "gcc" "cmake") for tool in "${required_tools[@]}"; do if ! command -v "$tool" &> /dev/null; then log_warning "$tool is not installed - some dependencies might fail to build" fi done log_success "Prerequisites check completed" } # Set up build environment setup_build_env() { log_info "Setting up optimized build environment..." # Export performance-focused environment variables export CARGO_TARGET_DIR="$TARGET_DIR" export RUST_BACKTRACE=0 export CARGO_INCREMENTAL=0 # CPU-specific optimizations case "$CPU_TARGET" in native) export RUSTFLAGS="-C target-cpu=native -C opt-level=3 -C lto=fat -C codegen-units=1 -C panic=abort" ;; skylake) export RUSTFLAGS="-C target-cpu=skylake -C opt-level=3 -C lto=fat -C codegen-units=1 -C panic=abort" ;; haswell) export RUSTFLAGS="-C target-cpu=haswell -C opt-level=3 -C lto=fat -C codegen-units=1 -C panic=abort" ;; broadwell) export RUSTFLAGS="-C target-cpu=broadwell -C opt-level=3 -C lto=fat -C codegen-units=1 -C panic=abort" ;; zen2) export RUSTFLAGS="-C target-cpu=znver2 -C opt-level=3 -C lto=fat -C codegen-units=1 -C panic=abort" ;; zen3) export RUSTFLAGS="-C target-cpu=znver3 -C opt-level=3 -C lto=fat -C codegen-units=1 -C panic=abort" ;; *) log_warning "Unknown CPU target: $CPU_TARGET, using native" export RUSTFLAGS="-C target-cpu=native -C opt-level=3 -C lto=fat -C codegen-units=1 -C panic=abort" ;; esac # Additional optimizations for HFT export RUSTFLAGS="$RUSTFLAGS -C prefer-dynamic=no -C target-feature=+crt-static" log_info "Build environment configured for $CPU_TARGET target" log_info "RUSTFLAGS: $RUSTFLAGS" } # Run tests if not skipped run_tests() { if [[ "$SKIP_TESTS" == "true" ]]; then log_warning "Skipping tests as requested" return 0 fi log_info "Running test suite before build..." cd "$PROJECT_ROOT" # Run unit tests if cargo test --release --features "$FEATURES" --workspace --lib; then log_success "Unit tests passed" else log_error "Unit tests failed - build aborted" exit 1 fi # Run integration tests (but not the expensive ones) if cargo test --release --features "$FEATURES" --test "*" --exclude performance-tests; then log_success "Integration tests passed" else log_warning "Some integration tests failed - continuing with build" fi } # Build all binary targets build_binaries() { log_info "Building optimized release binaries..." cd "$PROJECT_ROOT" local binaries=( "trading_service" "backtesting_service" "ml_training_service" "tli" "gpu_test" "ml_validation_test" "standalone_ml_test" ) local build_start=$(date +%s) for binary in "${binaries[@]}"; do log_info "Building $binary..." local bin_start=$(date +%s) if cargo build --release --features "$FEATURES" --bin "$binary"; then local bin_end=$(date +%s) local bin_duration=$((bin_end - bin_start)) # Get binary size local binary_path="$TARGET_DIR/$binary" if [[ -f "$binary_path" ]]; then local size=$(ls -lh "$binary_path" | awk '{print $5}') log_success "$binary built successfully (${bin_duration}s, ${size})" # Strip debug symbols for production strip "$binary_path" 2>/dev/null || true local stripped_size=$(ls -lh "$binary_path" | awk '{print $5}') log_info "$binary stripped to ${stripped_size}" else log_error "$binary was not created at expected path: $binary_path" fi else log_error "Failed to build $binary" return 1 fi done local build_end=$(date +%s) local total_duration=$((build_end - build_start)) log_success "All binaries built successfully in ${total_duration}s" } # Generate build info generate_build_info() { log_info "Generating build information..." local build_info_file="$TARGET_DIR/build_info.json" local git_commit=$(git rev-parse HEAD 2>/dev/null || echo "unknown") local git_branch=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown") local build_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") local rust_version=$(rustc --version) cat > "$build_info_file" << EOF { "project": "Foxhunt HFT Trading System", "version": "1.0.0", "build_date": "$build_date", "git_commit": "$git_commit", "git_branch": "$git_branch", "rust_version": "$rust_version", "cpu_target": "$CPU_TARGET", "features": "$FEATURES", "rustflags": "$RUSTFLAGS", "binaries": [ "trading_service", "backtesting_service", "ml_training_service", "tli", "gpu_test", "ml_validation_test", "standalone_ml_test" ] } EOF log_success "Build info saved to: $build_info_file" } # Create deployment archive create_deployment_archive() { log_info "Creating deployment archive..." local archive_name="foxhunt-hft-${git_branch:-unknown}-$(date +%Y%m%d-%H%M%S).tar.gz" local archive_path="$TARGET_DIR/$archive_name" cd "$TARGET_DIR" # Create archive with binaries and build info tar -czf "$archive_name" \ trading_service \ backtesting_service \ ml_training_service \ tli \ gpu_test \ ml_validation_test \ standalone_ml_test \ build_info.json local archive_size=$(ls -lh "$archive_path" | awk '{print $5}') log_success "Deployment archive created: $archive_name (${archive_size})" # Generate checksum local checksum=$(sha256sum "$archive_name" | cut -d' ' -f1) echo "$checksum $archive_name" > "${archive_name}.sha256" log_info "SHA256: $checksum" } # Validate binaries validate_binaries() { log_info "Validating built binaries..." local binaries=( "trading_service" "backtesting_service" "ml_training_service" "tli" ) for binary in "${binaries[@]}"; do local binary_path="$TARGET_DIR/$binary" if [[ -x "$binary_path" ]]; then # Check if binary is executable log_success "$binary is executable" # Try to get version/help (non-blocking) timeout 5s "$binary_path" --version &>/dev/null && log_info "$binary responds to --version" || true timeout 5s "$binary_path" --help &>/dev/null && log_info "$binary responds to --help" || true else log_error "$binary is not executable or missing" return 1 fi done log_success "Binary validation completed" } # Main execution main() { parse_args "$@" log_info "Starting Foxhunt HFT Trading System release build..." log_info "Target directory: $TARGET_DIR" log_info "Features: $FEATURES" log_info "CPU target: $CPU_TARGET" log_info "Skip tests: $SKIP_TESTS" check_prerequisites setup_build_env run_tests build_binaries validate_binaries generate_build_info create_deployment_archive log_success "Release build completed successfully!" log_info "Binaries are available in: $TARGET_DIR" log_info "Deploy using: ./deployment/deploy_production.sh" } # Handle script interruption trap 'log_error "Build interrupted"; exit 1' INT TERM # Run main function with all arguments main "$@"