Refactored to use BaseGCCCompiler
This commit is contained in:
parent
a686c2c9e8
commit
a6d867c31e
|
|
@ -6,11 +6,11 @@ Used primarily for RP2040 and other ARM Cortex-M microcontrollers.
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from .base import Compiler, CompileResult
|
from .base_gcc import BaseGCCCompiler
|
||||||
from build_system.utils import run
|
from .base import CompileResult
|
||||||
|
|
||||||
|
|
||||||
class ARMGCCCompiler(Compiler):
|
class ARMGCCCompiler(BaseGCCCompiler):
|
||||||
"""ARM GCC compiler for embedded targets."""
|
"""ARM GCC compiler for embedded targets."""
|
||||||
|
|
||||||
def __init__(self, executable: str = "arm-none-eabi-gcc", cpu: str = "cortex-m0plus"):
|
def __init__(self, executable: str = "arm-none-eabi-gcc", cpu: str = "cortex-m0plus"):
|
||||||
|
|
@ -25,6 +25,18 @@ class ARMGCCCompiler(Compiler):
|
||||||
self.cpu = cpu
|
self.cpu = cpu
|
||||||
self.thumb = True # Use Thumb instruction set by default
|
self.thumb = True # Use Thumb instruction set by default
|
||||||
|
|
||||||
|
def _get_cpu_flags(self) -> List[str]:
|
||||||
|
"""
|
||||||
|
Get CPU-specific flags.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
List of CPU-specific compiler flags
|
||||||
|
"""
|
||||||
|
flags = [f"-mcpu={self.cpu}"]
|
||||||
|
if self.thumb:
|
||||||
|
flags.append("-mthumb")
|
||||||
|
return flags
|
||||||
|
|
||||||
def compile(self,
|
def compile(self,
|
||||||
source: Path,
|
source: Path,
|
||||||
output: Path,
|
output: Path,
|
||||||
|
|
@ -49,51 +61,18 @@ class ARMGCCCompiler(Compiler):
|
||||||
Raises:
|
Raises:
|
||||||
subprocess.CalledProcessError: If compilation fails
|
subprocess.CalledProcessError: If compilation fails
|
||||||
"""
|
"""
|
||||||
# Ensure output directory exists
|
# Prepend CPU-specific flags to user flags
|
||||||
output.parent.mkdir(parents=True, exist_ok=True)
|
cpu_flags = self._get_cpu_flags()
|
||||||
|
combined_flags = cpu_flags + (flags or [])
|
||||||
|
|
||||||
# Build command
|
# Call parent compile with combined flags
|
||||||
cmd = [self.executable]
|
return super().compile(
|
||||||
|
source=source,
|
||||||
# Add CPU-specific flags
|
output=output,
|
||||||
cmd.append(f"-mcpu={self.cpu}")
|
flags=combined_flags,
|
||||||
if self.thumb:
|
defines=defines,
|
||||||
cmd.append("-mthumb")
|
include_dirs=include_dirs,
|
||||||
|
dependency_file=dependency_file
|
||||||
# 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,
|
def link(self,
|
||||||
|
|
@ -118,51 +97,18 @@ class ARMGCCCompiler(Compiler):
|
||||||
Raises:
|
Raises:
|
||||||
subprocess.CalledProcessError: If linking fails
|
subprocess.CalledProcessError: If linking fails
|
||||||
"""
|
"""
|
||||||
# Ensure output directory exists
|
# Prepend CPU-specific flags to user flags
|
||||||
output.parent.mkdir(parents=True, exist_ok=True)
|
cpu_flags = self._get_cpu_flags()
|
||||||
|
combined_flags = cpu_flags + (flags or [])
|
||||||
|
|
||||||
# Build command
|
# Call parent link with combined flags
|
||||||
cmd = [self.executable]
|
return super().link(
|
||||||
|
objects=objects,
|
||||||
# Add CPU-specific flags
|
output=output,
|
||||||
cmd.append(f"-mcpu={self.cpu}")
|
flags=combined_flags,
|
||||||
if self.thumb:
|
libraries=libraries,
|
||||||
cmd.append("-mthumb")
|
library_dirs=library_dirs
|
||||||
|
)
|
||||||
# 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 ARM GCC."""
|
|
||||||
return ".o"
|
|
||||||
|
|
||||||
def get_dependency_extension(self) -> str:
|
|
||||||
"""Get dependency file extension for ARM GCC."""
|
|
||||||
return ".d"
|
|
||||||
|
|
||||||
def supports_dependency_generation(self) -> bool:
|
|
||||||
"""ARM GCC supports automatic dependency generation."""
|
|
||||||
return True
|
|
||||||
|
|
||||||
def set_cpu(self, cpu: str) -> None:
|
def set_cpu(self, cpu: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
@ -183,6 +129,22 @@ class ARMGCCCompiler(Compiler):
|
||||||
self.thumb = enabled
|
self.thumb = enabled
|
||||||
|
|
||||||
|
|
||||||
|
def detect_arm_gcc_compiler() -> Optional[ARMGCCCompiler]:
|
||||||
|
"""
|
||||||
|
Detect and return an available ARM GCC compiler.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ARMGCCCompiler instance if found, None otherwise
|
||||||
|
"""
|
||||||
|
from build_system.utils import which
|
||||||
|
|
||||||
|
# Try to find ARM GCC
|
||||||
|
if which("arm-none-eabi-gcc"):
|
||||||
|
return ARMGCCCompiler()
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def check_arm_toolchain() -> bool:
|
def check_arm_toolchain() -> bool:
|
||||||
"""
|
"""
|
||||||
Check if ARM toolchain is available.
|
Check if ARM toolchain is available.
|
||||||
|
|
@ -200,3 +162,4 @@ def check_arm_toolchain() -> bool:
|
||||||
" Ubuntu/Debian: sudo apt install gcc-arm-none-eabi\n"
|
" Ubuntu/Debian: sudo apt install gcc-arm-none-eabi\n"
|
||||||
" macOS: brew install arm-none-eabi-gcc"
|
" macOS: brew install arm-none-eabi-gcc"
|
||||||
)
|
)
|
||||||
|
return False
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Base GCC-like compiler implementation.
|
||||||
|
Provides common functionality for GCC, Clang, and other GCC-compatible compilers.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import List, Optional
|
||||||
|
from .base import Compiler, CompileResult
|
||||||
|
from build_system.utils import run
|
||||||
|
|
||||||
|
|
||||||
|
class BaseGCCCompiler(Compiler):
|
||||||
|
"""Base class for GCC-compatible compilers (GCC, Clang, etc.)."""
|
||||||
|
|
||||||
|
def __init__(self, name: str, executable: str):
|
||||||
|
"""
|
||||||
|
Initialize base GCC-compatible compiler.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Human-readable compiler name
|
||||||
|
executable: Compiler executable name
|
||||||
|
"""
|
||||||
|
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-compatible compiler.
|
||||||
|
|
||||||
|
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-compatible compiler.
|
||||||
|
|
||||||
|
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-compatible compilers."""
|
||||||
|
return ".o"
|
||||||
|
|
||||||
|
def get_dependency_extension(self) -> str:
|
||||||
|
"""Get dependency file extension for GCC-compatible compilers."""
|
||||||
|
return ".d"
|
||||||
|
|
||||||
|
def supports_dependency_generation(self) -> bool:
|
||||||
|
"""GCC-compatible compilers support automatic dependency generation."""
|
||||||
|
return True
|
||||||
|
|
@ -1,17 +1,15 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
Clang compiler implementation.
|
Clang compiler implementation.
|
||||||
While Clang is compatible with GCC, this provides a dedicated implementation
|
|
||||||
for cases where Clang-specific features or flags are needed.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pathlib import Path
|
from typing import Optional
|
||||||
from typing import List, Optional
|
from .base_gcc import BaseGCCCompiler
|
||||||
from .gcc import GCCCompiler
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
class ClangCompiler(GCCCompiler):
|
class ClangCompiler(BaseGCCCompiler):
|
||||||
"""Clang compiler implementation (inherits from GCC)."""
|
"""Clang compiler implementation."""
|
||||||
|
|
||||||
def __init__(self, executable: str = "clang"):
|
def __init__(self, executable: str = "clang"):
|
||||||
"""
|
"""
|
||||||
|
|
@ -20,9 +18,7 @@ class ClangCompiler(GCCCompiler):
|
||||||
Args:
|
Args:
|
||||||
executable: Compiler executable name ("clang")
|
executable: Compiler executable name ("clang")
|
||||||
"""
|
"""
|
||||||
# Call parent constructor but override the name
|
super().__init__("Clang", executable)
|
||||||
super().__init__(executable)
|
|
||||||
self.name = "Clang"
|
|
||||||
|
|
||||||
def get_version(self) -> Optional[str]:
|
def get_version(self) -> Optional[str]:
|
||||||
"""
|
"""
|
||||||
|
|
@ -31,10 +27,13 @@ class ClangCompiler(GCCCompiler):
|
||||||
Returns:
|
Returns:
|
||||||
Version string if available, None otherwise
|
Version string if available, None otherwise
|
||||||
"""
|
"""
|
||||||
from build_system.utils import run_quiet
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = run_quiet([self.executable, "--version"], check=False)
|
result = subprocess.run(
|
||||||
|
[self.executable, "--version"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False
|
||||||
|
)
|
||||||
if result.returncode == 0 and result.stdout:
|
if result.returncode == 0 and result.stdout:
|
||||||
# Parse first line of version output
|
# Parse first line of version output
|
||||||
first_line = result.stdout.strip().split('\n')[0]
|
first_line = result.stdout.strip().split('\n')[0]
|
||||||
|
|
@ -43,3 +42,22 @@ class ClangCompiler(GCCCompiler):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def detect_clang_compiler() -> Optional[ClangCompiler]:
|
||||||
|
"""
|
||||||
|
Detect and return an available Clang compiler.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
ClangCompiler instance if found, None otherwise
|
||||||
|
"""
|
||||||
|
from build_system.utils import which
|
||||||
|
|
||||||
|
# Try to find Clang
|
||||||
|
compilers = ["clang", "clang-18", "clang-17", "clang-16", "clang-15"]
|
||||||
|
|
||||||
|
for compiler in compilers:
|
||||||
|
if which(compiler):
|
||||||
|
return ClangCompiler(compiler)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
|
||||||
|
|
@ -1,153 +1,64 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
GCC/Clang compiler implementation.
|
GCC compiler implementation.
|
||||||
Handles both GCC and Clang as they use similar command-line interfaces.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from pathlib import Path
|
from typing import Optional
|
||||||
from typing import List, Optional
|
from .base_gcc import BaseGCCCompiler
|
||||||
from .base import Compiler, CompileResult
|
|
||||||
from build_system.utils import run
|
|
||||||
|
|
||||||
|
|
||||||
class GCCCompiler(Compiler):
|
class GCCCompiler(BaseGCCCompiler):
|
||||||
"""GCC or Clang compiler implementation."""
|
"""GCC compiler implementation."""
|
||||||
|
|
||||||
def __init__(self, executable: str = "gcc"):
|
def __init__(self, executable: str = "gcc"):
|
||||||
"""
|
"""
|
||||||
Initialize GCC/Clang compiler.
|
Initialize GCC compiler.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
executable: Compiler executable name ("gcc" or "clang")
|
executable: Compiler executable name ("gcc")
|
||||||
"""
|
"""
|
||||||
name = "Clang" if "clang" in executable.lower() else "GCC"
|
super().__init__("GCC", executable)
|
||||||
super().__init__(name, executable)
|
|
||||||
|
|
||||||
def compile(self,
|
def get_version(self) -> Optional[str]:
|
||||||
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.
|
Get the GCC version string.
|
||||||
|
|
||||||
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:
|
Returns:
|
||||||
CompileResult with object file and dependency file paths
|
Version string if available, None otherwise
|
||||||
|
|
||||||
Raises:
|
|
||||||
subprocess.CalledProcessError: If compilation fails
|
|
||||||
"""
|
"""
|
||||||
# Ensure output directory exists
|
import subprocess
|
||||||
output.parent.mkdir(parents=True, exist_ok=True)
|
|
||||||
|
|
||||||
# Build command
|
try:
|
||||||
cmd = [self.executable]
|
result = subprocess.run(
|
||||||
|
[self.executable, "--version"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False
|
||||||
|
)
|
||||||
|
if result.returncode == 0 and result.stdout:
|
||||||
|
# Parse first line of version output
|
||||||
|
first_line = result.stdout.strip().split('\n')[0]
|
||||||
|
return first_line
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# Add flags
|
return None
|
||||||
if flags:
|
|
||||||
cmd.extend(flags)
|
|
||||||
|
def detect_gcc_compiler() -> Optional[GCCCompiler]:
|
||||||
# Add compile-only flag
|
"""
|
||||||
cmd.append(self.get_compile_only_flag())
|
Detect and return an available GCC compiler.
|
||||||
|
|
||||||
# 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,
|
Returns:
|
||||||
objects: List[Path],
|
GCCCompiler instance if found, None otherwise
|
||||||
output: Path,
|
"""
|
||||||
flags: Optional[List[str]] = None,
|
from build_system.utils import which
|
||||||
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:
|
# Try to find GCC
|
||||||
"""Get object file extension for GCC/Clang."""
|
compilers = ["gcc", "gcc-13", "gcc-12", "gcc-11", "cc"]
|
||||||
return ".o"
|
|
||||||
|
|
||||||
def get_dependency_extension(self) -> str:
|
for compiler in compilers:
|
||||||
"""Get dependency file extension for GCC/Clang."""
|
if which(compiler):
|
||||||
return ".d"
|
return GCCCompiler(compiler)
|
||||||
|
|
||||||
def supports_dependency_generation(self) -> bool:
|
return None
|
||||||
"""GCC/Clang supports automatic dependency generation."""
|
|
||||||
return True
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue