Implemented gcc.py
This commit is contained in:
parent
2fb369b9d4
commit
202e8700c2
|
|
@ -0,0 +1,153 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
GCC/Clang compiler implementation.
|
||||||
|
Handles both GCC and Clang as they use similar command-line interfaces.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Optional
|
||||||
|
from .base import Compiler, CompileResult
|
||||||
|
from build_system.utils import run
|
||||||
|
|
||||||
|
|
||||||
|
class GCCCompiler(Compiler):
|
||||||
|
"""GCC or Clang compiler implementation."""
|
||||||
|
|
||||||
|
def __init__(self, executable: str = "gcc"):
|
||||||
|
"""
|
||||||
|
Initialize GCC/Clang compiler.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
executable: Compiler executable name ("gcc" or "clang")
|
||||||
|
"""
|
||||||
|
name = "Clang" if "clang" in executable.lower() else "GCC"
|
||||||
|
super().__init__(name, executable)
|
||||||
|
|
||||||
|
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 GCC/Clang.
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
# Ensure output directory exists
|
||||||
|
output.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# Build command
|
||||||
|
cmd = [self.executable]
|
||||||
|
|
||||||
|
# Add flags
|
||||||
|
if flags:
|
||||||
|
cmd.extend(flags)
|
||||||
|
|
||||||
|
# Add compile-only flag
|
||||||
|
cmd.append(self.get_compile_only_flag())
|
||||||
|
|
||||||
|
# Add defines
|
||||||
|
if defines:
|
||||||
|
cmd.extend([self.get_define_flag(d) for d in defines])
|
||||||
|
|
||||||
|
# Add include directories
|
||||||
|
if include_dirs:
|
||||||
|
cmd.extend([self.get_include_flag(d) for d in include_dirs])
|
||||||
|
|
||||||
|
# Add dependency generation if requested
|
||||||
|
dep_file = None
|
||||||
|
if dependency_file:
|
||||||
|
cmd.extend(["-MMD", "-MP"])
|
||||||
|
dep_file = dependency_file
|
||||||
|
|
||||||
|
# Add source file
|
||||||
|
cmd.append(str(source))
|
||||||
|
|
||||||
|
# Add output file
|
||||||
|
cmd.extend(self.get_output_flag(output))
|
||||||
|
|
||||||
|
# Run compilation
|
||||||
|
run(cmd) # type: ignore
|
||||||
|
|
||||||
|
return CompileResult(
|
||||||
|
object_file=output,
|
||||||
|
dependency_file=dep_file,
|
||||||
|
success=True
|
||||||
|
)
|
||||||
|
|
||||||
|
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 GCC/Clang.
|
||||||
|
|
||||||
|
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
|
||||||
|
"""
|
||||||
|
# Ensure output directory exists
|
||||||
|
output.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# Build command
|
||||||
|
cmd = [self.executable]
|
||||||
|
|
||||||
|
# Add object files
|
||||||
|
cmd.extend([str(obj) for obj in objects])
|
||||||
|
|
||||||
|
# Add linker flags
|
||||||
|
if flags:
|
||||||
|
cmd.extend(flags)
|
||||||
|
|
||||||
|
# Add library directories
|
||||||
|
if library_dirs:
|
||||||
|
cmd.extend([f"-L{lib_dir}" for lib_dir in library_dirs])
|
||||||
|
|
||||||
|
# Add libraries
|
||||||
|
if libraries:
|
||||||
|
cmd.extend([f"-l{lib}" for lib in libraries])
|
||||||
|
|
||||||
|
# Add output file
|
||||||
|
cmd.extend(["-o", str(output)])
|
||||||
|
|
||||||
|
# Run linker
|
||||||
|
run(cmd) # type: ignore
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_object_extension(self) -> str:
|
||||||
|
"""Get object file extension for GCC/Clang."""
|
||||||
|
return ".o"
|
||||||
|
|
||||||
|
def get_dependency_extension(self) -> str:
|
||||||
|
"""Get dependency file extension for GCC/Clang."""
|
||||||
|
return ".d"
|
||||||
|
|
||||||
|
def supports_dependency_generation(self) -> bool:
|
||||||
|
"""GCC/Clang supports automatic dependency generation."""
|
||||||
|
return True
|
||||||
Loading…
Reference in New Issue