95 lines
3.0 KiB
Python
95 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Intel oneAPI Fortran discovery helpers for no-Abaqus validation."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import shutil
|
|
import subprocess
|
|
from pathlib import Path
|
|
from typing import Iterable
|
|
|
|
|
|
COMPILER_CANDIDATES = ("ifx", "ifort")
|
|
ONEAPI_VARS_CANDIDATES = [
|
|
Path(r"C:\Program Files (x86)\Intel\oneAPI\compiler\latest\env\vars.bat"),
|
|
Path(r"C:\Program Files\Intel\oneAPI\compiler\latest\env\vars.bat"),
|
|
Path(r"C:\Program Files (x86)\Intel\oneAPI\setvars.bat"),
|
|
Path(r"C:\Program Files\Intel\oneAPI\setvars.bat"),
|
|
]
|
|
|
|
|
|
class FortranToolchain:
|
|
def __init__(self, *, name: str, executable: str, env_script: Path | None):
|
|
self.name = name
|
|
self.executable = executable
|
|
self.env_script = env_script
|
|
|
|
|
|
def compiler_candidates(preference: str | None = None) -> list[str]:
|
|
preference = (preference or os.environ.get("HARNESS_FORTRAN_COMPILER") or "auto").lower()
|
|
if preference == "auto":
|
|
return list(COMPILER_CANDIDATES)
|
|
if preference not in COMPILER_CANDIDATES:
|
|
raise ValueError(f"Unsupported HARNESS_FORTRAN_COMPILER: {preference}")
|
|
return [preference]
|
|
|
|
|
|
def discover_oneapi_env_script(env: dict[str, str] | None = None) -> Path | None:
|
|
env = env or os.environ
|
|
configured = env.get("HARNESS_ONEAPI_VARS_BAT")
|
|
if configured:
|
|
path = Path(configured)
|
|
return path if path.exists() else None
|
|
|
|
for path in ONEAPI_VARS_CANDIDATES:
|
|
if path.exists():
|
|
return path
|
|
return None
|
|
|
|
|
|
def resolve_toolchain(env: dict[str, str] | None = None) -> FortranToolchain | None:
|
|
env = env or os.environ
|
|
candidates = compiler_candidates(env.get("HARNESS_FORTRAN_COMPILER"))
|
|
for compiler in candidates:
|
|
resolved = shutil.which(compiler)
|
|
if resolved:
|
|
return FortranToolchain(name=compiler, executable=resolved, env_script=None)
|
|
|
|
env_script = discover_oneapi_env_script(env)
|
|
if env_script is None:
|
|
return None
|
|
|
|
compiler = candidates[0]
|
|
return FortranToolchain(name=compiler, executable=compiler, env_script=env_script)
|
|
|
|
|
|
def shell_join(args: Iterable[str | Path]) -> str:
|
|
return subprocess.list2cmdline([str(arg) for arg in args])
|
|
|
|
|
|
def quote_path(path: str | Path) -> str:
|
|
return shell_join([path])
|
|
|
|
|
|
def cmd_executable(env: dict[str, str] | None = None) -> str:
|
|
env = env or os.environ
|
|
return env.get("ComSpec") or shutil.which("cmd.exe") or shutil.which("cmd") or "cmd"
|
|
|
|
|
|
def cmd_minimal_path(env: dict[str, str] | None = None) -> str:
|
|
env = env or os.environ
|
|
system_root = env.get("SystemRoot") or r"C:\Windows"
|
|
return f"{system_root}\\System32;{system_root}"
|
|
|
|
|
|
def wrap_command(toolchain: FortranToolchain, args: list[str | Path]) -> str:
|
|
command = shell_join(args)
|
|
if toolchain.env_script is None:
|
|
return command
|
|
|
|
env_script = quote_path(toolchain.env_script)
|
|
cmd = quote_path(cmd_executable())
|
|
path = cmd_minimal_path()
|
|
return f'{cmd} /d /s /c "set "PATH={path}" && call {env_script} intel64 >nul && {command}"'
|