Files
AbaqusSubroutineDev/scripts/fortran_toolchain.py
T
2026-06-11 14:29:20 +09:00

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}"'