Added riscv_gcc.py
This commit is contained in:
parent
720842c448
commit
f1cf9dc114
|
|
@ -0,0 +1,180 @@
|
|||
#!/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
|
||||
Loading…
Reference in New Issue