From d1c6dbd0b15781455e39ef6418510096d9be6b3b Mon Sep 17 00:00:00 2001 From: Kyler Date: Fri, 19 Dec 2025 14:22:33 -0700 Subject: [PATCH] Implemented arm_gcc.py --- SLS_C/build_system/compilers/arm_gcc.py | 202 ++++++++++++++++++++++++ 1 file changed, 202 insertions(+) diff --git a/SLS_C/build_system/compilers/arm_gcc.py b/SLS_C/build_system/compilers/arm_gcc.py index e69de29..600ba3a 100644 --- a/SLS_C/build_system/compilers/arm_gcc.py +++ b/SLS_C/build_system/compilers/arm_gcc.py @@ -0,0 +1,202 @@ +#!/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 import Compiler, CompileResult +from build_system.utils import run + + +class ARMGCCCompiler(Compiler): + """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 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 + """ + # Ensure output directory exists + output.parent.mkdir(parents=True, exist_ok=True) + + # Build command + cmd = [self.executable] + + # Add CPU-specific flags + cmd.append(f"-mcpu={self.cpu}") + if self.thumb: + cmd.append("-mthumb") + + # Add flags + if flags: + cmd.extend(flags) + + # Add compile-only flag + cmd.append(self.get_compile_only_flag()) + + # Add defines + if defines: + cmd.extend([self.get_define_flag(d) for d in defines]) + + # Add include directories + if include_dirs: + cmd.extend([self.get_include_flag(d) for d in include_dirs]) + + # Add dependency generation if requested + dep_file = None + if dependency_file: + cmd.extend(["-MMD", "-MP"]) + dep_file = dependency_file + + # Add source file + cmd.append(str(source)) + + # Add output file + cmd.extend(self.get_output_flag(output)) + + # Run compilation + run(cmd) # type: ignore + + return CompileResult( + object_file=output, + dependency_file=dep_file, + success=True + ) + + 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 + """ + # Ensure output directory exists + output.parent.mkdir(parents=True, exist_ok=True) + + # Build command + cmd = [self.executable] + + # Add CPU-specific flags + cmd.append(f"-mcpu={self.cpu}") + if self.thumb: + cmd.append("-mthumb") + + # Add object files + cmd.extend([str(obj) for obj in objects]) + + # Add linker flags + if flags: + cmd.extend(flags) + + # Add library directories + if library_dirs: + cmd.extend([f"-L{lib_dir}" for lib_dir in library_dirs]) + + # Add libraries + if libraries: + cmd.extend([f"-l{lib}" for lib in libraries]) + + # Add output file + cmd.extend(["-o", str(output)]) + + # Run linker + run(cmd) # type: ignore + + return True + + def get_object_extension(self) -> str: + """Get object file extension for ARM GCC.""" + return ".o" + + def get_dependency_extension(self) -> str: + """Get dependency file extension for ARM GCC.""" + return ".d" + + def supports_dependency_generation(self) -> bool: + """ARM GCC supports automatic dependency generation.""" + return True + + 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 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" + )