""" Compiler module for the build system. This module provides compiler implementations for various toolchains: - GCC (Unix/Linux) - Clang (macOS/Unix) - MSVC (Windows) - ARM GCC (embedded ARM targets) Usage: from compilers import GCCCompiler, ClangCompiler, MSVCCompiler compiler = GCCCompiler() compiler.compile(source, output, includes=[...], defines={...}) """ from typing import Optional from .base import Compiler from .gcc import GCCCompiler from .clang import ClangCompiler from .msvc import MSVCCompiler from .arm_gcc import ARMGCCCompiler, RP2040Compiler __all__ = [ 'Compiler', 'GCCCompiler', 'ClangCompiler', 'MSVCCompiler', 'ARMGCCCompiler', 'RP2040Compiler', ] def detect_compiler(platform: Optional[str] = None): """ Detect and return an appropriate compiler for the given platform. Args: platform: Target platform ('linux', 'windows', 'darwin'/'macos', 'rp2040', etc.) If None, detects current platform. Returns: An instance of the appropriate Compiler subclass Raises: RuntimeError: If no suitable compiler is found """ import platform as plat import shutil # Detect current platform if not specified if platform is None: system = plat.system().lower() if system == "darwin": platform = "macos" else: platform = system platform = platform.lower() # Try to find appropriate compiler if platform in ("linux", "unix"): # Prefer GCC on Linux if shutil.which("gcc"): return GCCCompiler("gcc") elif shutil.which("clang"): return ClangCompiler("clang") else: raise RuntimeError("No suitable compiler found (tried gcc, clang)") elif platform in ("macos", "darwin"): # Prefer Clang on macOS (default compiler) if shutil.which("clang"): return ClangCompiler("clang") elif shutil.which("gcc"): return GCCCompiler("gcc") else: raise RuntimeError("No suitable compiler found (tried clang, gcc)") elif platform == "windows": # Try MSVC first, then MinGW GCC if shutil.which("cl"): return MSVCCompiler("cl") elif shutil.which("gcc"): return GCCCompiler("gcc") else: raise RuntimeError("No suitable compiler found (tried cl, gcc)") elif platform == "rp2040": # RP2040 needs ARM toolchain if shutil.which("arm-none-eabi-gcc"): return RP2040Compiler() else: raise RuntimeError( "ARM GCC toolchain not found. Please install arm-none-eabi-gcc:\n" " Ubuntu/Debian: sudo apt install gcc-arm-none-eabi\n" " macOS: brew install arm-none-eabi-gcc" ) else: raise ValueError(f"Unknown platform: {platform}") def get_available_compilers(): """ Get a list of all compilers available on the current system. Returns: Dictionary mapping compiler names to Compiler instances """ import shutil available = {} # Check GCC if shutil.which("gcc"): available['gcc'] = GCCCompiler() # Check Clang if shutil.which("clang"): available['clang'] = ClangCompiler() # Check MSVC if shutil.which("cl"): available['msvc'] = MSVCCompiler() # Check ARM GCC if shutil.which("arm-none-eabi-gcc"): available['arm-gcc'] = ARMGCCCompiler() available['rp2040'] = RP2040Compiler() return available def print_available_compilers(): """Print all available compilers on the system.""" compilers = get_available_compilers() if not compilers: print("No compilers found on this system.") return print("Available compilers:") for name, compiler in compilers.items(): print(f" - {name}: {compiler.executable}")