#!/usr/bin/env python3 """ RISC-V GCC compiler implementation for embedded targets. Used primarily for ESP32-C3 and other RISC-V microcontrollers. """ from pathlib import Path from typing import List, Optional from .base_gcc import BaseGCCCompiler from .base import CompileResult from build_system.utils import run class RISCVGCCCompiler(BaseGCCCompiler): """RISC-V GCC compiler for embedded targets.""" def __init__(self, executable: str = "riscv32-esp-elf-gcc", arch: str = "rv32imc", abi: str = "ilp32"): """ Initialize RISC-V GCC compiler. Args: executable: Compiler executable name arch: Target architecture (e.g., "rv32imc", "rv32imac") abi: Target ABI (e.g., "ilp32", "ilp32f") """ super().__init__("RISC-V GCC", executable) self.arch = arch self.abi = abi def _get_arch_flags(self) -> List[str]: """ Get architecture-specific flags. Returns: List of architecture-specific compiler flags """ return [ f"-march={self.arch}", f"-mabi={self.abi}" ] 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 RISC-V 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 architecture-specific flags to user flags arch_flags = self._get_arch_flags() combined_flags = arch_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 RISC-V 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 architecture-specific flags to user flags arch_flags = self._get_arch_flags() combined_flags = arch_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_arch(self, arch: str) -> None: """ Set the target architecture. Args: arch: Target architecture (e.g., "rv32imc", "rv32imac") """ self.arch = arch def set_abi(self, abi: str) -> None: """ Set the target ABI. Args: abi: Target ABI (e.g., "ilp32", "ilp32f") """ self.abi = abi def detect_riscv_gcc_compiler() -> Optional[RISCVGCCCompiler]: """ Detect and return an available RISC-V GCC compiler. Returns: RISCVGCCCompiler instance if found, None otherwise """ from build_system.utils import which # Try to find RISC-V GCC (ESP32 toolchain first, then generic) compilers = [ "riscv32-esp-elf-gcc", # ESP-IDF toolchain "riscv32-unknown-elf-gcc", # Generic RISC-V toolchain "riscv64-unknown-elf-gcc" # 64-bit RISC-V toolchain ] for compiler in compilers: if which(compiler): return RISCVGCCCompiler(compiler) return None def check_riscv_toolchain() -> bool: """ Check if RISC-V toolchain is available. Returns: True if RISC-V toolchain is found, False otherwise """ from build_system.utils import check_tool # Check for ESP32-C3 toolchain first if check_tool("riscv32-esp-elf-gcc"): return True # Check for generic RISC-V toolchain if check_tool("riscv32-unknown-elf-gcc"): return True print("ERROR: RISC-V toolchain not found. Install one of:") print(" ESP32-C3: Install ESP-IDF (https://docs.espressif.com/projects/esp-idf/)") print(" Generic RISC-V:") print(" Ubuntu/Debian: sudo apt install gcc-riscv64-unknown-elf") print(" macOS: brew tap riscv/riscv && brew install riscv-tools") return False