From 1a3bfad7395e9b536be78741ebbd6cbbb8f385d2 Mon Sep 17 00:00:00 2001 From: Kyler Date: Fri, 19 Dec 2025 14:03:16 -0700 Subject: [PATCH] Implemented compilers/base.py --- SLS_C/build_system/compilers/base.py | 170 +++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/SLS_C/build_system/compilers/base.py b/SLS_C/build_system/compilers/base.py index e69de29..2a23998 100644 --- a/SLS_C/build_system/compilers/base.py +++ b/SLS_C/build_system/compilers/base.py @@ -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}')"