MSVC: Restore amalgamated compiler functionality (#46678)
Right now the Spack %msvc compiler is inherently a hybrid compiler that uses Intel's oneAPI fortran compiler. This was addressed in Spacks MSVC compiler class, but detection has since stopped using the compiler class, so this PR moves the logic into the `msvc` compiler package (does not delete the original code because that is handled in #45189). This includes a change to the general detection logic to deprioritize paths that include a symlink anywhere in the path, in order to prefer "2025.0/bin" over "latest/bin" for the oneAPI compiler.
This commit is contained in:
parent
e2c6914dfe
commit
69b7c32b5d
@ -7,6 +7,7 @@
|
||||
import collections
|
||||
import concurrent.futures
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
import traceback
|
||||
@ -15,6 +16,7 @@
|
||||
|
||||
import llnl.util.filesystem
|
||||
import llnl.util.lang
|
||||
import llnl.util.symlink
|
||||
import llnl.util.tty
|
||||
|
||||
import spack.error
|
||||
@ -70,13 +72,21 @@ def dedupe_paths(paths: List[str]) -> List[str]:
|
||||
"""Deduplicate paths based on inode and device number. In case the list contains first a
|
||||
symlink and then the directory it points to, the symlink is replaced with the directory path.
|
||||
This ensures that we pick for example ``/usr/bin`` over ``/bin`` if the latter is a symlink to
|
||||
the former`."""
|
||||
the former."""
|
||||
seen: Dict[Tuple[int, int], str] = {}
|
||||
|
||||
linked_parent_check = lambda x: any(
|
||||
[llnl.util.symlink.islink(str(y)) for y in pathlib.Path(x).parents]
|
||||
)
|
||||
|
||||
for path in paths:
|
||||
identifier = file_identifier(path)
|
||||
if identifier not in seen:
|
||||
seen[identifier] = path
|
||||
elif not os.path.islink(path):
|
||||
# we also want to deprioritize paths if they contain a symlink in any parent
|
||||
# (not just the basedir): e.g. oneapi has "latest/bin",
|
||||
# where "latest" is a symlink to 2025.0"
|
||||
elif not (llnl.util.symlink.islink(path) or linked_parent_check(path)):
|
||||
seen[identifier] = path
|
||||
return list(seen.values())
|
||||
|
||||
|
@ -6,6 +6,17 @@
|
||||
import spack.compiler
|
||||
from spack.package import *
|
||||
|
||||
FC_PATH: Dict[str, str] = dict()
|
||||
|
||||
|
||||
def get_latest_valid_fortran_pth():
|
||||
"""Assign maximum available fortran compiler version"""
|
||||
# TODO (johnwparent): validate compatibility w/ try compiler
|
||||
# functionality when added
|
||||
sort_fn = lambda fc_ver: Version(fc_ver)
|
||||
sort_fc_ver = sorted(list(FC_PATH.keys()), key=sort_fn)
|
||||
return FC_PATH[sort_fc_ver[-1]] if sort_fc_ver else None
|
||||
|
||||
|
||||
class Msvc(Package, CompilerPackage):
|
||||
"""
|
||||
@ -20,9 +31,11 @@ def install(self, spec, prefix):
|
||||
"detected on a system where they are externally installed"
|
||||
)
|
||||
|
||||
compiler_languages = ["c", "cxx"]
|
||||
compiler_languages = ["c", "cxx", "fortran"]
|
||||
c_names = ["cl"]
|
||||
cxx_names = ["cl"]
|
||||
fortran_names = ["ifx", "ifort"]
|
||||
|
||||
compiler_version_argument = ""
|
||||
compiler_version_regex = r"([1-9][0-9]*\.[0-9]*\.[0-9]*)"
|
||||
|
||||
@ -30,11 +43,14 @@ def install(self, spec, prefix):
|
||||
def determine_version(cls, exe):
|
||||
# MSVC compiler does not have a proper version argument
|
||||
# Errors out and prints version info with no args
|
||||
is_ifx = "ifx.exe" in str(exe)
|
||||
match = re.search(
|
||||
cls.compiler_version_regex,
|
||||
spack.compiler.get_compiler_version_output(exe, version_arg=None, ignore_errors=True),
|
||||
)
|
||||
if match:
|
||||
if is_ifx:
|
||||
FC_PATH[match.group(1)] = str(exe)
|
||||
return match.group(1)
|
||||
|
||||
@classmethod
|
||||
@ -42,6 +58,16 @@ def determine_variants(cls, exes, version_str):
|
||||
# MSVC uses same executable for both languages
|
||||
spec, extras = super().determine_variants(exes, version_str)
|
||||
extras["compilers"]["c"] = extras["compilers"]["cxx"]
|
||||
# This depends on oneapi being processed before msvc
|
||||
# which is guarunteed from detection behavior.
|
||||
# Processing oneAPI tracks oneAPI installations within
|
||||
# this module, which are then used to populate compatible
|
||||
# MSVC version's fortran compiler spots
|
||||
|
||||
# TODO: remove this once #45189 lands
|
||||
# TODO: interrogate intel and msvc for compatibility after
|
||||
# #45189 lands
|
||||
extras["compilers"]["fortran"] = get_latest_valid_fortran_pth()
|
||||
return spec, extras
|
||||
|
||||
@property
|
||||
|
Loading…
Reference in New Issue
Block a user