4coder/build_new/helpers/check-toolchain.sh

438 lines
12 KiB
Bash
Raw Normal View History

#!/bin/bash
# check-toolchain.sh - Verify clang installation and build requirements
# Checks for clang, required tools, and platform-specific dependencies
set -e
# =============================================================================
# Configuration
# =============================================================================
# Minimum required versions
MIN_CLANG_VERSION_MAJOR=6
MIN_CLANG_VERSION_MINOR=0
# Required tools
REQUIRED_TOOLS=(
"clang++"
"clang"
"make"
"bash"
)
# Platform-specific tools
REQUIRED_TOOLS_LINUX=(
"pkg-config"
)
REQUIRED_TOOLS_MACOS=(
"xcrun"
)
REQUIRED_TOOLS_WIN32=(
"windres" # For resource compilation
)
# =============================================================================
# Utility Functions
# =============================================================================
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
print_success() {
echo -e "${GREEN}${NC} $1"
}
print_warning() {
echo -e "${YELLOW}${NC} $1"
}
print_error() {
echo -e "${RED}${NC} $1"
}
print_info() {
echo -e " $1"
}
# =============================================================================
# Version Checking
# =============================================================================
check_clang_version() {
local clang_version
local major minor
if ! command -v clang++ &> /dev/null; then
print_error "clang++ not found in PATH"
return 1
fi
clang_version=$(clang++ --version | head -n1)
print_info "Found: $clang_version"
# Extract version numbers (handles various clang version formats)
if [[ $clang_version =~ ([0-9]+)\.([0-9]+) ]]; then
major=${BASH_REMATCH[1]}
minor=${BASH_REMATCH[2]}
if [[ $major -gt $MIN_CLANG_VERSION_MAJOR ]] || \
[[ $major -eq $MIN_CLANG_VERSION_MAJOR && $minor -ge $MIN_CLANG_VERSION_MINOR ]]; then
print_success "clang++ version $major.$minor meets minimum requirement ($MIN_CLANG_VERSION_MAJOR.$MIN_CLANG_VERSION_MINOR)"
return 0
else
print_error "clang++ version $major.$minor is below minimum requirement ($MIN_CLANG_VERSION_MAJOR.$MIN_CLANG_VERSION_MINOR)"
return 1
fi
else
print_warning "Could not parse clang++ version, proceeding anyway"
return 0
fi
}
# =============================================================================
# Tool Checking
# =============================================================================
check_tool() {
local tool=$1
local required=${2:-true}
if command -v "$tool" &> /dev/null; then
local version_info
case "$tool" in
"clang++"|"clang")
version_info=$(command "$tool" --version 2>/dev/null | head -n1 || echo "version unknown")
;;
"make")
version_info=$(command "$tool" --version 2>/dev/null | head -n1 || echo "version unknown")
;;
"pkg-config")
version_info=$(command "$tool" --version 2>/dev/null || echo "version unknown")
;;
*)
version_info="available"
;;
esac
print_success "$tool found ($version_info)"
return 0
else
if [[ "$required" == "true" ]]; then
print_error "$tool not found in PATH"
return 1
else
print_warning "$tool not found (optional)"
return 0
fi
fi
}
check_basic_tools() {
local all_good=true
print_info "Checking basic tools..."
for tool in "${REQUIRED_TOOLS[@]}"; do
if ! check_tool "$tool"; then
all_good=false
fi
done
if [[ "$all_good" == "true" ]]; then
return 0
else
return 1
fi
}
check_platform_tools() {
local platform=$1
local all_good=true
local tools_var
case "$platform" in
"linux")
tools_var="REQUIRED_TOOLS_LINUX[@]"
;;
"macos")
tools_var="REQUIRED_TOOLS_MACOS[@]"
;;
"win32")
tools_var="REQUIRED_TOOLS_WIN32[@]"
;;
*)
print_warning "Unknown platform '$platform', skipping platform-specific tool checks"
return 0
;;
esac
print_info "Checking platform-specific tools for $platform..."
# Use indirect reference to get the array
local tools_array_name="$tools_var"
if [[ -n "${!tools_array_name:-}" ]]; then
local tools_array=("${!tools_array_name}")
for tool in "${tools_array[@]}"; do
if ! check_tool "$tool"; then
all_good=false
fi
done
fi
if [[ "$all_good" == "true" ]]; then
return 0
else
return 1
fi
}
# =============================================================================
# Platform-Specific Checks
# =============================================================================
check_macos_requirements() {
print_info "Checking macOS-specific requirements..."
# Check for Xcode command line tools
if ! xcode-select -p &> /dev/null; then
print_error "Xcode command line tools not installed"
print_info "Install with: xcode-select --install"
return 1
else
print_success "Xcode command line tools installed"
fi
# Check for macOS SDK
local sdk_path
sdk_path=$(xcrun --show-sdk-path 2>/dev/null || echo "")
if [[ -n "$sdk_path" && -d "$sdk_path" ]]; then
print_success "macOS SDK found at $sdk_path"
else
print_warning "macOS SDK not found or not accessible"
fi
# Check for required frameworks (just check if headers exist)
local frameworks=("Cocoa" "OpenGL" "Metal")
for framework in "${frameworks[@]}"; do
if [[ -d "$sdk_path/System/Library/Frameworks/$framework.framework" ]]; then
print_success "$framework framework available"
else
print_warning "$framework framework not found"
fi
done
return 0
}
check_linux_requirements() {
print_info "Checking Linux-specific requirements..."
# Check for development packages
local packages=("libx11-dev" "libgl1-mesa-dev" "libfreetype6-dev" "libfontconfig1-dev")
local missing_packages=()
for package in "${packages[@]}"; do
if dpkg -l | grep -q "$package" 2>/dev/null; then
print_success "$package installed"
elif rpm -q "$package" &>/dev/null; then
print_success "$package installed"
else
print_warning "$package not found (may be required)"
missing_packages+=("$package")
fi
done
if [[ ${#missing_packages[@]} -gt 0 ]]; then
print_info "Missing packages (Ubuntu/Debian): ${missing_packages[*]}"
print_info "Install with: sudo apt-get install ${missing_packages[*]}"
fi
return 0
}
check_win32_requirements() {
print_info "Checking Windows-specific requirements..."
# Check for Windows SDK (approximate check)
if [[ -n "${WINDOWSSDKDIR:-}" ]]; then
print_success "Windows SDK environment detected"
else
print_warning "Windows SDK environment not detected"
print_info "Make sure Visual Studio or Windows SDK is installed"
fi
return 0
}
# =============================================================================
# Library Checks
# =============================================================================
check_freetype_library() {
local platform=$1
local arch=$2
print_info "Checking FreeType library availability..."
case "$platform" in
"macos")
local freetype_lib="non-source/foreign/x64/libfreetype-mac.a"
if [[ -f "$freetype_lib" ]]; then
print_success "FreeType library found: $freetype_lib"
else
print_error "FreeType library not found: $freetype_lib"
return 1
fi
;;
"linux")
if pkg-config --exists freetype2; then
local freetype_version
freetype_version=$(pkg-config --modversion freetype2)
print_success "FreeType2 found via pkg-config (version $freetype_version)"
else
print_warning "FreeType2 not found via pkg-config"
fi
;;
"win32")
local freetype_lib="non-source/foreign/x64/freetype.lib"
if [[ -f "$freetype_lib" ]]; then
print_success "FreeType library found: $freetype_lib"
else
print_error "FreeType library not found: $freetype_lib"
return 1
fi
;;
esac
return 0
}
# =============================================================================
# Main Checking Function
# =============================================================================
check_build_environment() {
local platform
local arch
local all_good=true
echo "=== 4coder Build Environment Check ==="
echo
# Detect platform
if command -v "$(dirname "$0")/detect-platform.sh" &> /dev/null; then
platform=$($(dirname "$0")/detect-platform.sh detect)
arch=$($(dirname "$0")/detect-platform.sh arch)
print_info "Detected platform: $platform"
print_info "Detected architecture: $arch"
else
print_warning "Platform detection script not found, assuming current platform"
platform="unknown"
arch="unknown"
fi
echo
# Check clang version
if ! check_clang_version; then
all_good=false
fi
echo
# Check basic tools
if ! check_basic_tools; then
all_good=false
fi
echo
# Check platform-specific tools
if ! check_platform_tools "$platform"; then
all_good=false
fi
echo
# Check platform-specific requirements
case "$platform" in
"macos")
if ! check_macos_requirements; then
all_good=false
fi
;;
"linux")
if ! check_linux_requirements; then
all_good=false
fi
;;
"win32")
if ! check_win32_requirements; then
all_good=false
fi
;;
esac
echo
# Check libraries
if ! check_freetype_library "$platform" "$arch"; then
all_good=false
fi
echo
# Final result
if [[ "$all_good" == "true" ]]; then
print_success "Build environment check passed!"
print_info "System is ready for 4coder compilation"
return 0
else
print_error "Build environment check failed"
print_info "Some requirements are missing. Please install missing components and try again."
return 1
fi
}
# =============================================================================
# Main execution
# =============================================================================
main() {
local command="${1:-check}"
case "$command" in
"check")
check_build_environment
;;
"clang")
check_clang_version
;;
"tools")
check_basic_tools
;;
"help"|"-h"|"--help")
echo "Usage: $0 [check|clang|tools|help]"
echo ""
echo "Commands:"
echo " check - Run full build environment check (default)"
echo " clang - Check clang version only"
echo " tools - Check basic tools only"
echo " help - Show this help message"
;;
*)
echo "Error: Unknown command '$command'" >&2
echo "Run '$0 help' for usage information" >&2
return 1
;;
esac
}
# Only run main if script is executed directly (not sourced)
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
main "$@"
fi