144 lines
3.9 KiB
Python
144 lines
3.9 KiB
Python
"""
|
|
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}")
|