#!/usr/bin/env python3 """ ARM GCC compiler implementation for embedded targets. Used primarily for RP2040 and other ARM Cortex-M microcontrollers. """ from pathlib import Path from typing import List, Optional from .base_gcc import BaseGCCCompiler from .base import CompileResult class ARMGCCCompiler(BaseGCCCompiler): """ARM GCC compiler for embedded targets.""" def __init__(self, executable: str = "arm-none-eabi-gcc", cpu: str = "cortex-m0plus"): """ Initialize ARM GCC compiler. Args: executable: Compiler executable name cpu: Target CPU (e.g., "cortex-m0plus", "cortex-m4") """ super().__init__("ARM GCC", executable) self.cpu = cpu self.thumb = True # Use Thumb instruction set by default def _get_cpu_flags(self) -> List[str]: """ Get CPU-specific flags. Returns: List of CPU-specific compiler flags """ flags = [f"-mcpu={self.cpu}"] if self.thumb: flags.append("-mthumb") return flags def compile(self, source: Path, output: Path, flags: Optional[List[str]] = None, defines: Optional[List[str]] = None, include_dirs: Optional[List[Path]] = None, dependency_file: Optional[Path] = None) -> CompileResult: """ Compile a source file using ARM GCC. Args: source: Source file path output: Output object file path flags: Additional compiler flags defines: Preprocessor defines include_dirs: Additional include directories dependency_file: Path for dependency file (.d file) Returns: CompileResult with object file and dependency file paths Raises: subprocess.CalledProcessError: If compilation fails """ # Prepend CPU-specific flags to user flags cpu_flags = self._get_cpu_flags() combined_flags = cpu_flags + (flags or []) # Call parent compile with combined flags return super().compile( source=source, output=output, flags=combined_flags, defines=defines, include_dirs=include_dirs, dependency_file=dependency_file ) def link(self, objects: List[Path], output: Path, flags: Optional[List[str]] = None, libraries: Optional[List[str]] = None, library_dirs: Optional[List[Path]] = None) -> bool: """ Link object files into an executable using ARM GCC. Args: objects: List of object file paths output: Output executable path flags: Additional linker flags libraries: Libraries to link against library_dirs: Additional library search directories Returns: True if linking succeeded Raises: subprocess.CalledProcessError: If linking fails """ # Prepend CPU-specific flags to user flags cpu_flags = self._get_cpu_flags() combined_flags = cpu_flags + (flags or []) # Call parent link with combined flags return super().link( objects=objects, output=output, flags=combined_flags, libraries=libraries, library_dirs=library_dirs ) def set_cpu(self, cpu: str) -> None: """ Set the target CPU. Args: cpu: Target CPU name (e.g., "cortex-m0plus", "cortex-m4") """ self.cpu = cpu def set_thumb(self, enabled: bool) -> None: """ Enable or disable Thumb instruction set. Args: enabled: True to enable Thumb, False to disable """ self.thumb = enabled def detect_arm_gcc_compiler() -> Optional[ARMGCCCompiler]: """ Detect and return an available ARM GCC compiler. Returns: ARMGCCCompiler instance if found, None otherwise """ from build_system.utils import which # Try to find ARM GCC if which("arm-none-eabi-gcc"): return ARMGCCCompiler() return None def check_arm_toolchain() -> bool: """ Check if ARM toolchain is available. Returns: True if ARM toolchain is found, False otherwise """ from build_system.utils import check_tool if check_tool("arm-none-eabi-gcc"): return True else: print( "ARM toolchain not found. Install arm-none-eabi-gcc:\n" " Ubuntu/Debian: sudo apt install gcc-arm-none-eabi\n" " macOS: brew install arm-none-eabi-gcc" ) return False