#!/bin/bash #============================================================================== # @file setup_environment.sh # @brief Setup development environment for Automotive RTOS #============================================================================== set -e # Script directory - handle spaces and special characters properly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" # Color codes RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color #============================================================================== # OS Detection #============================================================================== detect_os() { case "$(uname -s)" in Darwin*) OS="macos" OS_VERSION=$(sw_vers -productVersion 2>/dev/null || echo "unknown") ARCH=$(uname -m) ;; Linux*) OS="linux" if [ -f /etc/os-release ]; then . /etc/os-release DISTRO="$ID" elif [ -f /etc/debian_version ]; then DISTRO="debian" elif [ -f /etc/redhat-release ]; then DISTRO="redhat" else DISTRO="unknown" fi ARCH=$(uname -m) ;; MINGW*|MSYS*|CYGWIN*) OS="windows" ;; *) OS="unknown" ;; esac } #============================================================================== # Print Banner #============================================================================== print_banner() { echo -e "${BLUE}========================================${NC}" echo -e "${BLUE} Automotive RTOS Environment Setup${NC}" echo -e "${BLUE}========================================${NC}" echo -e " OS: ${CYAN}${OS}${NC}" if [ "$OS" = "linux" ]; then echo -e " Distro: ${CYAN}${DISTRO}${NC}" fi if [ "$OS" = "macos" ]; then echo -e " Version: ${CYAN}${OS_VERSION}${NC}" fi echo -e " Arch: ${CYAN}${ARCH}${NC}" echo "" } #============================================================================== # Command Check #============================================================================== command_exists() { command -v "$1" >/dev/null 2>&1 } #============================================================================== # Install Package - Cross-platform #============================================================================== install_package() { local package=$1 echo -e "${YELLOW}Installing ${package}...${NC}" case "$OS" in macos) if command_exists brew; then brew install "$package" || { echo -e "${YELLOW}Failed to install ${package} via brew${NC}" return 1 } else echo -e "${RED}Homebrew not found. Please install Homebrew first:${NC}" echo " /bin/bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)\"" return 1 fi ;; linux) case "$DISTRO" in ubuntu|debian) sudo apt-get update sudo apt-get install -y "$package" ;; fedora|centos|rhel) sudo dnf install -y "$package" || sudo yum install -y "$package" ;; arch) sudo pacman -S --noconfirm "$package" ;; *) echo -e "${RED}Unsupported Linux distribution: ${DISTRO}${NC}" return 1 ;; esac ;; windows) echo -e "${YELLOW}Please install ${package} manually on Windows${NC}" echo " Visit: https://${package}.org/download/" return 1 ;; *) echo -e "${RED}Unsupported OS${NC}" return 1 ;; esac echo -e "${GREEN}✓ ${package} installed${NC}" return 0 } #============================================================================== # Install ARM Toolchain #============================================================================== install_arm_toolchain() { echo -e "${YELLOW}Installing ARM toolchain...${NC}" # Check if already installed if command_exists arm-none-eabi-gcc; then echo -e "${GREEN}✓ ARM toolchain already installed: $(arm-none-eabi-gcc --version | head -n1)${NC}" return 0 fi case "$OS" in macos) if command_exists brew; then echo -e "${YELLOW}Installing ARM toolchain via Homebrew...${NC}" # Try the official tap first brew tap ArmMbed/homebrew-formulae 2>/dev/null || true brew install arm-none-eabi-gcc 2>/dev/null || { echo -e "${YELLOW}Trying alternative installation method...${NC}" # Alternative: download from ARM developer site echo -e "${YELLOW}Please download ARM toolchain from:${NC}" echo " https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads" echo -e "${YELLOW}Choose the macOS (Apple Silicon or Intel) version${NC}" echo -e "${YELLOW}After downloading, add to PATH:${NC}" echo " export PATH=\"/path/to/arm-gnu-toolchain/bin:\$PATH\"" } else echo -e "${RED}Homebrew not found${NC}" return 1 fi ;; linux) case "$DISTRO" in ubuntu|debian) sudo apt-get install -y gcc-arm-none-eabi binutils-arm-none-eabi ;; fedora|centos|rhel) sudo dnf install -y arm-none-eabi-gcc arm-none-eabi-binutils ;; arch) sudo pacman -S --noconfirm arm-none-eabi-gcc arm-none-eabi-binutils ;; esac ;; windows) echo -e "${YELLOW}Download ARM toolchain from:${NC}" echo " https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads" ;; esac # Verify installation if command_exists arm-none-eabi-gcc; then echo -e "${GREEN}✓ ARM toolchain installed: $(arm-none-eabi-gcc --version | head -n1)${NC}" return 0 else echo -e "${YELLOW}ARM toolchain not found in PATH${NC}" echo -e "${YELLOW}Please add it manually or install from ARM developer site${NC}" return 1 fi } #============================================================================== # Install Build Tools #============================================================================== install_build_tools() { echo -e "${YELLOW}Installing build tools...${NC}" # CMake if command_exists cmake; then echo -e "${GREEN}✓ CMake already installed: $(cmake --version | head -n1)${NC}" else install_package cmake fi # Make if command_exists make; then echo -e "${GREEN}✓ Make already installed${NC}" else install_package make fi # Git if command_exists git; then echo -e "${GREEN}✓ Git already installed: $(git --version)${NC}" else install_package git fi } #============================================================================== # Install Debug Tools #============================================================================== install_debug_tools() { echo -e "${YELLOW}Installing debug tools...${NC}" case "$OS" in macos) # GDB for ARM if command_exists arm-none-eabi-gdb; then echo -e "${GREEN}✓ ARM GDB already installed${NC}" elif command_exists gdb; then echo -e "${GREEN}✓ GDB installed (may not support ARM targets)${NC}" echo -e "${YELLOW} Consider installing arm-none-eabi-gdb via brew${NC}" else echo -e "${YELLOW}Installing GDB...${NC}" brew install gdb 2>/dev/null || echo -e "${YELLOW} GDB installation skipped${NC}" fi # OpenOCD if command_exists openocd; then echo -e "${GREEN}✓ OpenOCD already installed${NC}" else echo -e "${YELLOW}Installing OpenOCD...${NC}" brew install openocd 2>/dev/null || echo -e "${YELLOW} OpenOCD installation skipped${NC}" fi # STLink tools if command_exists st-flash; then echo -e "${GREEN}✓ STLink tools already installed${NC}" else echo -e "${YELLOW}Installing STLink tools...${NC}" brew install stlink 2>/dev/null || echo -e "${YELLOW} STLink installation skipped${NC}" fi ;; linux) # GDB multiarch if command_exists gdb-multiarch; then echo -e "${GREEN}✓ GDB multiarch already installed${NC}" else install_package gdb-multiarch fi # OpenOCD if command_exists openocd; then echo -e "${GREEN}✓ OpenOCD already installed${NC}" else install_package openocd fi # STLink tools if command_exists st-flash; then echo -e "${GREEN}✓ STLink tools already installed${NC}" else install_package stlink-tools fi ;; esac } #============================================================================== # Install Analysis Tools #============================================================================== install_analysis_tools() { echo -e "${YELLOW}Installing analysis tools...${NC}" # Cppcheck if command_exists cppcheck; then echo -e "${GREEN}✓ Cppcheck already installed${NC}" else install_package cppcheck fi # Clang if command_exists clang; then echo -e "${GREEN}✓ Clang already installed${NC}" else install_package llvm fi # Valgrind (Linux only) if [ "$OS" = "linux" ]; then if command_exists valgrind; then echo -e "${GREEN}✓ Valgrind already installed${NC}" else install_package valgrind fi fi } #============================================================================== # Install Python Tools #============================================================================== install_python_tools() { echo -e "${YELLOW}Installing Python tools...${NC}" # Python3 if command_exists python3; then echo -e "${GREEN}✓ Python3 already installed: $(python3 --version)${NC}" else install_package python3 fi # Pip3 if command_exists pip3; then echo -e "${GREEN}✓ Pip3 already installed${NC}" else install_package python3-pip fi # Python packages echo -e "${YELLOW}Installing Python packages...${NC}" pip3 install --user \ pyelftools \ pyserial \ numpy \ matplotlib \ pytest \ coverage \ gcovr 2>/dev/null || { echo -e "${YELLOW}Some Python packages may need sudo${NC}" echo -e "${YELLOW}Try: pip3 install --user ${NC}" } } #============================================================================== # Setup Project Directories #============================================================================== setup_project_dirs() { echo -e "${YELLOW}Setting up project directories...${NC}" mkdir -p "${PROJECT_ROOT}/build" mkdir -p "${PROJECT_ROOT}/build/logs" mkdir -p "${PROJECT_ROOT}/build/misra" mkdir -p "${PROJECT_ROOT}/build/docs" mkdir -p "${PROJECT_ROOT}/build/coverage" mkdir -p "${PROJECT_ROOT}/build/tests" echo -e "${GREEN}✓ Project directories created${NC}" } #============================================================================== # Setup Git Hooks #============================================================================== setup_git_hooks() { echo -e "${YELLOW}Setting up git hooks...${NC}" if [ -d "${PROJECT_ROOT}/.git" ]; then HOOKS_DIR="${PROJECT_ROOT}/.git/hooks" mkdir -p "${HOOKS_DIR}" # Pre-commit hook cat > "${HOOKS_DIR}/pre-commit" << 'EOF' #!/bin/bash # Pre-commit hook for Automotive RTOS echo "Running pre-commit checks..." # Check for trailing whitespace if git diff --cached --check; then echo "✓ No whitespace issues" else echo "✗ Trailing whitespace found" exit 1 fi # Check for large files large_files=$(git diff --cached --name-only | xargs -I{} du -k {} 2>/dev/null | awk '$1 > 1024 {print $2}') if [ -n "$large_files" ]; then echo "✗ Large files detected (>1MB):" echo "$large_files" exit 1 fi echo "✓ Pre-commit checks passed" EOF chmod +x "${HOOKS_DIR}/pre-commit" # Pre-push hook cat > "${HOOKS_DIR}/pre-push" << 'EOF' #!/bin/bash # Pre-push hook for Automotive RTOS echo "Running pre-push checks..." # Run quick static analysis if [ -f "scripts/static_analysis.sh" ]; then bash scripts/static_analysis.sh --quick fi echo "✓ Pre-push checks passed" EOF chmod +x "${HOOKS_DIR}/pre-push" echo -e "${GREEN}✓ Git hooks installed${NC}" else echo -e "${YELLOW}Not a git repository. Skipping git hooks.${NC}" fi } #============================================================================== # Setup VS Code Configuration #============================================================================== setup_vscode() { echo -e "${YELLOW}Setting up VS Code configuration...${NC}" VSCODE_DIR="${PROJECT_ROOT}/.vscode" mkdir -p "${VSCODE_DIR}" # Only create if files don't exist if [ ! -f "${VSCODE_DIR}/settings.json" ]; then cat > "${VSCODE_DIR}/settings.json" << 'EOF' { "editor.formatOnSave": true, "editor.tabSize": 4, "files.encoding": "utf8", "C_Cpp.default.includePath": [ "${workspaceFolder}/kernel/include", "${workspaceFolder}/drivers/include", "${workspaceFolder}/middleware", "${workspaceFolder}/config" ], "C_Cpp.default.compilerPath": "/opt/homebrew/bin/arm-none-eabi-gcc" } EOF echo -e "${GREEN}✓ VS Code settings created${NC}" else echo -e "${YELLOW}VS Code settings already exist. Skipping.${NC}" fi } #============================================================================== # Setup Environment Variables #============================================================================== setup_env_vars() { echo -e "${YELLOW}Setting up environment variables...${NC}" ENV_FILE="${PROJECT_ROOT}/.env" # Detect toolchain path if command_exists arm-none-eabi-gcc; then TOOLCHAIN_PATH="$(dirname $(which arm-none-eabi-gcc))" else TOOLCHAIN_PATH="/opt/homebrew/bin" fi cat > "${ENV_FILE}" << EOF # Automotive RTOS Environment Variables # Generated on $(date) export RTOS_ROOT="${PROJECT_ROOT}" export RTOS_BUILD_DIR="\${RTOS_ROOT}/build" export RTOS_TOOLCHAIN="${TOOLCHAIN_PATH}/arm-none-eabi-" export RTOS_TARGET="stm32f407_discovery" export RTOS_DEBUG_PORT="3333" # Add toolchain to PATH if not already there if [[ ":\$PATH:" != *":${TOOLCHAIN_PATH}:"* ]]; then export PATH="${TOOLCHAIN_PATH}:\$PATH" fi EOF # Add to shell profile if not already there SHELL_PROFILE="" case "$SHELL" in */bash) SHELL_PROFILE="$HOME/.bash_profile" [ -f "$HOME/.bashrc" ] && SHELL_PROFILE="$HOME/.bashrc" ;; */zsh) SHELL_PROFILE="$HOME/.zshrc" ;; esac if [ -n "$SHELL_PROFILE" ] && [ -f "$SHELL_PROFILE" ]; then if ! grep -q "RTOS_ROOT" "$SHELL_PROFILE"; then echo "" >> "$SHELL_PROFILE" echo "# Automotive RTOS Environment" >> "$SHELL_PROFILE" echo "source ${ENV_FILE}" >> "$SHELL_PROFILE" echo -e "${GREEN}✓ Added to ${SHELL_PROFILE}${NC}" fi fi echo -e "${GREEN}✓ Environment variables configured${NC}" echo -e "${YELLOW}To apply now, run: source ${ENV_FILE}${NC}" } #============================================================================== # Main Setup Function #============================================================================== main() { detect_os print_banner # Parse arguments INSTALL_TOOLCHAIN=true INSTALL_BUILD=true INSTALL_DEBUG=true INSTALL_ANALYSIS=true INSTALL_PYTHON=true while [[ $# -gt 0 ]]; do case $1 in --minimal) INSTALL_DEBUG=false INSTALL_ANALYSIS=false INSTALL_PYTHON=false shift ;; --no-toolchain) INSTALL_TOOLCHAIN=false shift ;; --no-debug) INSTALL_DEBUG=false shift ;; --no-analysis) INSTALL_ANALYSIS=false shift ;; --no-python) INSTALL_PYTHON=false shift ;; -h|--help) echo "Usage: $0 [OPTIONS]" echo " --minimal Minimal installation" echo " --no-toolchain Skip ARM toolchain" echo " --no-debug Skip debug tools" echo " --no-analysis Skip analysis tools" echo " --no-python Skip Python tools" exit 0 ;; *) echo "Unknown option: $1" exit 1 ;; esac done # Install components if [ "$INSTALL_TOOLCHAIN" = true ]; then install_arm_toolchain || echo -e "${YELLOW}Toolchain installation incomplete${NC}" fi if [ "$INSTALL_BUILD" = true ]; then install_build_tools fi if [ "$INSTALL_DEBUG" = true ]; then install_debug_tools fi if [ "$INSTALL_ANALYSIS" = true ]; then install_analysis_tools fi if [ "$INSTALL_PYTHON" = true ]; then install_python_tools fi # Setup project setup_project_dirs setup_git_hooks setup_vscode setup_env_vars # Print summary echo "" echo -e "${GREEN}========================================${NC}" echo -e "${GREEN} Environment Setup Complete${NC}" echo -e "${GREEN}========================================${NC}" echo "" echo -e "Next steps:" echo -e " 1. Apply environment: ${CYAN}source ${PROJECT_ROOT}/.env${NC}" echo -e " 2. Build project: ${CYAN}bash scripts/build_all.sh${NC}" echo -e " 3. Run tests: ${CYAN}bash scripts/run_tests.sh${NC}" echo "" # Check if toolchain is working if command_exists arm-none-eabi-gcc; then echo -e "${GREEN}✓ ARM toolchain ready: $(arm-none-eabi-gcc --version | head -n1)${NC}" else echo -e "${YELLOW}⚠ ARM toolchain not found${NC}" echo -e "${YELLOW} Download from: https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads${NC}" echo -e "${YELLOW} For macOS Apple Silicon, choose: arm-gnu-toolchain-*-darwin-arm64-arm-none-eabi.tar.xz${NC}" echo -e "${YELLOW} Extract and add to PATH${NC}" fi } # Run main main "$@"