Compare commits
No commits in common. "f1cf9dc11476b37a80523596132030e1eb156cc2" and "a6d867c31ea9c328cae0afb8175676e0f7637cbb" have entirely different histories.
f1cf9dc114
...
a6d867c31e
|
|
@ -1,224 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
MSVC (Microsoft Visual C++) compiler implementation.
|
|
||||||
Used for Windows native builds.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List, Optional
|
|
||||||
from .base import Compiler, CompileResult
|
|
||||||
from build_system.utils import run
|
|
||||||
import subprocess
|
|
||||||
|
|
||||||
|
|
||||||
class MSVCCompiler(Compiler):
|
|
||||||
"""Microsoft Visual C++ compiler implementation."""
|
|
||||||
|
|
||||||
def __init__(self, executable: str = "cl"):
|
|
||||||
"""
|
|
||||||
Initialize MSVC compiler.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
executable: Compiler executable name ("cl")
|
|
||||||
"""
|
|
||||||
super().__init__("MSVC", 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 MSVC.
|
|
||||||
|
|
||||||
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 (not used by MSVC)
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
CompileResult with object file path
|
|
||||||
|
|
||||||
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 output file (MSVC uses /Fo)
|
|
||||||
cmd.extend(self.get_output_flag(output))
|
|
||||||
|
|
||||||
# Add source file
|
|
||||||
cmd.append(str(source))
|
|
||||||
|
|
||||||
# Run compilation
|
|
||||||
run(cmd) # type: ignore
|
|
||||||
|
|
||||||
return CompileResult(
|
|
||||||
object_file=output,
|
|
||||||
dependency_file=None, # MSVC doesn't generate .d files
|
|
||||||
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 MSVC.
|
|
||||||
|
|
||||||
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 output file (MSVC uses /Fe)
|
|
||||||
cmd.append(f"/Fe{output}")
|
|
||||||
|
|
||||||
# Add linker flags
|
|
||||||
if flags:
|
|
||||||
cmd.extend(flags)
|
|
||||||
|
|
||||||
# Add library directories
|
|
||||||
if library_dirs:
|
|
||||||
cmd.extend([f"/LIBPATH:{lib_dir}" for lib_dir in library_dirs])
|
|
||||||
|
|
||||||
# Add libraries (MSVC uses .lib extension)
|
|
||||||
if libraries:
|
|
||||||
for lib in libraries:
|
|
||||||
# Add .lib if not present
|
|
||||||
lib_name = lib if lib.endswith('.lib') else f"{lib}.lib"
|
|
||||||
cmd.append(lib_name)
|
|
||||||
|
|
||||||
# Run linker
|
|
||||||
run(cmd) # type: ignore
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
def get_object_extension(self) -> str:
|
|
||||||
"""Get object file extension for MSVC."""
|
|
||||||
return ".obj"
|
|
||||||
|
|
||||||
def get_dependency_extension(self) -> str:
|
|
||||||
"""Get dependency file extension for MSVC."""
|
|
||||||
return ".d" # Not actually used by MSVC
|
|
||||||
|
|
||||||
def supports_dependency_generation(self) -> bool:
|
|
||||||
"""MSVC does not support automatic dependency generation like GCC."""
|
|
||||||
return False
|
|
||||||
|
|
||||||
def get_define_flag(self, define: str) -> str:
|
|
||||||
"""Get the MSVC flag for a preprocessor define."""
|
|
||||||
return f"/D{define}"
|
|
||||||
|
|
||||||
def get_include_flag(self, include_dir: Path) -> str:
|
|
||||||
"""Get the MSVC flag for an include directory."""
|
|
||||||
return f"/I{include_dir}"
|
|
||||||
|
|
||||||
def get_output_flag(self, output: Path) -> List[str]:
|
|
||||||
"""Get the MSVC flag for specifying output file."""
|
|
||||||
return [f"/Fo{output}"]
|
|
||||||
|
|
||||||
def get_compile_only_flag(self) -> str:
|
|
||||||
"""Get the MSVC flag to compile without linking."""
|
|
||||||
return "/c"
|
|
||||||
|
|
||||||
def get_version(self) -> Optional[str]:
|
|
||||||
"""
|
|
||||||
Get the MSVC version string.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
Version string if available, None otherwise
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
result = subprocess.run(
|
|
||||||
[self.executable],
|
|
||||||
capture_output=True,
|
|
||||||
text=True,
|
|
||||||
check=False
|
|
||||||
)
|
|
||||||
# MSVC prints version info to stderr when called with no args
|
|
||||||
if result.stderr:
|
|
||||||
lines = result.stderr.strip().split('\n')
|
|
||||||
for line in lines:
|
|
||||||
if "Microsoft" in line or "Version" in line:
|
|
||||||
return line.strip()
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def detect_msvc_compiler() -> Optional[MSVCCompiler]:
|
|
||||||
"""
|
|
||||||
Detect and return an available MSVC compiler.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
MSVCCompiler instance if found, None otherwise
|
|
||||||
"""
|
|
||||||
from build_system.utils import which
|
|
||||||
|
|
||||||
# Try to find MSVC
|
|
||||||
if which("cl"):
|
|
||||||
return MSVCCompiler()
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def check_msvc_environment() -> bool:
|
|
||||||
"""
|
|
||||||
Check if MSVC environment is properly set up.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if MSVC is available and environment is configured, False otherwise
|
|
||||||
"""
|
|
||||||
from build_system.utils import check_tool
|
|
||||||
|
|
||||||
if check_tool("cl"):
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
print("Make sure to run from a Visual Studio Developer Command Prompt")
|
|
||||||
print("or run vcvarsall.bat to set up the environment.")
|
|
||||||
return False
|
|
||||||
|
|
@ -1,180 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
RISC-V GCC compiler implementation for embedded targets.
|
|
||||||
Used primarily for ESP32-C3 and other RISC-V microcontrollers.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List, Optional
|
|
||||||
from .base_gcc import BaseGCCCompiler
|
|
||||||
from .base import CompileResult
|
|
||||||
from build_system.utils import run
|
|
||||||
|
|
||||||
|
|
||||||
class RISCVGCCCompiler(BaseGCCCompiler):
|
|
||||||
"""RISC-V GCC compiler for embedded targets."""
|
|
||||||
|
|
||||||
def __init__(self, executable: str = "riscv32-esp-elf-gcc", arch: str = "rv32imc", abi: str = "ilp32"):
|
|
||||||
"""
|
|
||||||
Initialize RISC-V GCC compiler.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
executable: Compiler executable name
|
|
||||||
arch: Target architecture (e.g., "rv32imc", "rv32imac")
|
|
||||||
abi: Target ABI (e.g., "ilp32", "ilp32f")
|
|
||||||
"""
|
|
||||||
super().__init__("RISC-V GCC", executable)
|
|
||||||
self.arch = arch
|
|
||||||
self.abi = abi
|
|
||||||
|
|
||||||
def _get_arch_flags(self) -> List[str]:
|
|
||||||
"""
|
|
||||||
Get architecture-specific flags.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
List of architecture-specific compiler flags
|
|
||||||
"""
|
|
||||||
return [
|
|
||||||
f"-march={self.arch}",
|
|
||||||
f"-mabi={self.abi}"
|
|
||||||
]
|
|
||||||
|
|
||||||
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 RISC-V GCC.
|
|
||||||
|
|
||||||
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
|
|
||||||
"""
|
|
||||||
# Prepend architecture-specific flags to user flags
|
|
||||||
arch_flags = self._get_arch_flags()
|
|
||||||
combined_flags = arch_flags + (flags or [])
|
|
||||||
|
|
||||||
# Call parent compile with combined flags
|
|
||||||
return super().compile(
|
|
||||||
source=source,
|
|
||||||
output=output,
|
|
||||||
flags=combined_flags,
|
|
||||||
defines=defines,
|
|
||||||
include_dirs=include_dirs,
|
|
||||||
dependency_file=dependency_file
|
|
||||||
)
|
|
||||||
|
|
||||||
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 RISC-V GCC.
|
|
||||||
|
|
||||||
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
|
|
||||||
"""
|
|
||||||
# Prepend architecture-specific flags to user flags
|
|
||||||
arch_flags = self._get_arch_flags()
|
|
||||||
combined_flags = arch_flags + (flags or [])
|
|
||||||
|
|
||||||
# Call parent link with combined flags
|
|
||||||
return super().link(
|
|
||||||
objects=objects,
|
|
||||||
output=output,
|
|
||||||
flags=combined_flags,
|
|
||||||
libraries=libraries,
|
|
||||||
library_dirs=library_dirs
|
|
||||||
)
|
|
||||||
|
|
||||||
def set_arch(self, arch: str) -> None:
|
|
||||||
"""
|
|
||||||
Set the target architecture.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
arch: Target architecture (e.g., "rv32imc", "rv32imac")
|
|
||||||
"""
|
|
||||||
self.arch = arch
|
|
||||||
|
|
||||||
def set_abi(self, abi: str) -> None:
|
|
||||||
"""
|
|
||||||
Set the target ABI.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
abi: Target ABI (e.g., "ilp32", "ilp32f")
|
|
||||||
"""
|
|
||||||
self.abi = abi
|
|
||||||
|
|
||||||
|
|
||||||
def detect_riscv_gcc_compiler() -> Optional[RISCVGCCCompiler]:
|
|
||||||
"""
|
|
||||||
Detect and return an available RISC-V GCC compiler.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
RISCVGCCCompiler instance if found, None otherwise
|
|
||||||
"""
|
|
||||||
from build_system.utils import which
|
|
||||||
|
|
||||||
# Try to find RISC-V GCC (ESP32 toolchain first, then generic)
|
|
||||||
compilers = [
|
|
||||||
"riscv32-esp-elf-gcc", # ESP-IDF toolchain
|
|
||||||
"riscv32-unknown-elf-gcc", # Generic RISC-V toolchain
|
|
||||||
"riscv64-unknown-elf-gcc" # 64-bit RISC-V toolchain
|
|
||||||
]
|
|
||||||
|
|
||||||
for compiler in compilers:
|
|
||||||
if which(compiler):
|
|
||||||
return RISCVGCCCompiler(compiler)
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def check_riscv_toolchain() -> bool:
|
|
||||||
"""
|
|
||||||
Check if RISC-V toolchain is available.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
True if RISC-V toolchain is found, False otherwise
|
|
||||||
"""
|
|
||||||
from build_system.utils import check_tool
|
|
||||||
|
|
||||||
# Check for ESP32-C3 toolchain first
|
|
||||||
if check_tool("riscv32-esp-elf-gcc"):
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Check for generic RISC-V toolchain
|
|
||||||
if check_tool("riscv32-unknown-elf-gcc"):
|
|
||||||
return True
|
|
||||||
|
|
||||||
print("ERROR: RISC-V toolchain not found. Install one of:")
|
|
||||||
print(" ESP32-C3: Install ESP-IDF (https://docs.espressif.com/projects/esp-idf/)")
|
|
||||||
print(" Generic RISC-V:")
|
|
||||||
print(" Ubuntu/Debian: sudo apt install gcc-riscv64-unknown-elf")
|
|
||||||
print(" macOS: brew tap riscv/riscv && brew install riscv-tools")
|
|
||||||
|
|
||||||
return False
|
|
||||||
Loading…
Reference in New Issue