YREA-SLS/SLS_C/build_system/compilers/arm_gcc.py

166 lines
4.8 KiB
Python

#!/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