Files
foxhunt/deployment/build_release.sh

383 lines
11 KiB
Bash
Executable File

#!/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 "$@"