Implemented compilers/base.py
This commit is contained in:
parent
018197e290
commit
1a3bfad739
|
|
@ -0,0 +1,170 @@
|
|||
#!/usr/bin/env python3
|
||||
"""
|
||||
Base compiler interface for the build system.
|
||||
Defines the abstract Compiler class that all specific compilers must implement.
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from pathlib import Path
|
||||
from typing import List, Optional
|
||||
from dataclasses import dataclass
|
||||
|
||||
|
||||
@dataclass
|
||||
class CompileResult:
|
||||
"""Result of a compilation operation."""
|
||||
object_file: Path
|
||||
dependency_file: Optional[Path] = None
|
||||
success: bool = True
|
||||
|
||||
|
||||
class Compiler(ABC):
|
||||
"""Abstract base class for all compilers."""
|
||||
|
||||
def __init__(self, name: str, executable: str):
|
||||
"""
|
||||
Initialize the compiler.
|
||||
|
||||
Args:
|
||||
name: Human-readable name of the compiler (e.g., "GCC", "MSVC")
|
||||
executable: Executable name or path (e.g., "gcc", "cl")
|
||||
"""
|
||||
self.name = name
|
||||
self.executable = executable
|
||||
|
||||
@abstractmethod
|
||||
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 single source file to an object file.
|
||||
|
||||
Args:
|
||||
source: Source file path
|
||||
output: Output object file path
|
||||
flags: Additional compiler flags
|
||||
defines: Preprocessor defines (e.g., ["DEBUG", "VERSION=1.0"])
|
||||
include_dirs: Additional include directories
|
||||
dependency_file: Path for dependency file (.d file)
|
||||
|
||||
Returns:
|
||||
CompileResult with object file path and success status
|
||||
|
||||
Raises:
|
||||
subprocess.CalledProcessError: If compilation fails
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
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 or library.
|
||||
|
||||
Args:
|
||||
objects: List of object file paths
|
||||
output: Output executable or library path
|
||||
flags: Additional linker flags
|
||||
libraries: Libraries to link against (e.g., ["m", "pthread"])
|
||||
library_dirs: Additional library search directories
|
||||
|
||||
Returns:
|
||||
True if linking succeeded, False otherwise
|
||||
|
||||
Raises:
|
||||
subprocess.CalledProcessError: If linking fails
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_object_extension(self) -> str:
|
||||
"""
|
||||
Get the file extension for object files.
|
||||
|
||||
Returns:
|
||||
Object file extension (e.g., ".o" or ".obj")
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def get_dependency_extension(self) -> str:
|
||||
"""
|
||||
Get the file extension for dependency files.
|
||||
|
||||
Returns:
|
||||
Dependency file extension (e.g., ".d")
|
||||
"""
|
||||
pass
|
||||
|
||||
def supports_dependency_generation(self) -> bool:
|
||||
"""
|
||||
Check if the compiler supports automatic dependency generation.
|
||||
|
||||
Returns:
|
||||
True if dependency generation is supported, False otherwise
|
||||
"""
|
||||
return True
|
||||
|
||||
def get_define_flag(self, define: str) -> str:
|
||||
"""
|
||||
Get the compiler flag for a preprocessor define.
|
||||
|
||||
Args:
|
||||
define: Define string (e.g., "DEBUG" or "VERSION=1.0")
|
||||
|
||||
Returns:
|
||||
Compiler-specific define flag (e.g., "-DDEBUG" or "/DDEBUG")
|
||||
"""
|
||||
# Most compilers use -D, but can be overridden
|
||||
return f"-D{define}"
|
||||
|
||||
def get_include_flag(self, include_dir: Path) -> str:
|
||||
"""
|
||||
Get the compiler flag for an include directory.
|
||||
|
||||
Args:
|
||||
include_dir: Include directory path
|
||||
|
||||
Returns:
|
||||
Compiler-specific include flag (e.g., "-Iinclude" or "/Iinclude")
|
||||
"""
|
||||
# Most compilers use -I, but can be overridden
|
||||
return f"-I{include_dir}"
|
||||
|
||||
def get_output_flag(self, output: Path) -> List[str]:
|
||||
"""
|
||||
Get the compiler flag(s) for specifying output file.
|
||||
|
||||
Args:
|
||||
output: Output file path
|
||||
|
||||
Returns:
|
||||
List of flags (e.g., ["-o", "output.o"] or ["/Fooutput.obj"])
|
||||
"""
|
||||
# Most compilers use -o, but can be overridden
|
||||
return ["-o", str(output)]
|
||||
|
||||
def get_compile_only_flag(self) -> str:
|
||||
"""
|
||||
Get the flag to compile without linking.
|
||||
|
||||
Returns:
|
||||
Compile-only flag (e.g., "-c")
|
||||
"""
|
||||
return "-c"
|
||||
|
||||
def __str__(self) -> str:
|
||||
"""String representation of the compiler."""
|
||||
return f"{self.name} ({self.executable})"
|
||||
|
||||
def __repr__(self) -> str:
|
||||
"""Detailed string representation."""
|
||||
return f"Compiler(name='{self.name}', executable='{self.executable}')"
|
||||
Loading…
Reference in New Issue