166 lines
4.8 KiB
Python
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
|