diff --git a/var/spack/repos/spack_repo/builtin/packages/msvc/package.py b/var/spack/repos/spack_repo/builtin/packages/msvc/package.py index ae24fde197d..f976fce4ef3 100644 --- a/var/spack/repos/spack_repo/builtin/packages/msvc/package.py +++ b/var/spack/repos/spack_repo/builtin/packages/msvc/package.py @@ -158,6 +158,39 @@ def init_msvc(self): ) self.vcvars_call = VCVarsInvocation(vcvars_script_path, arch, msvc_version) env_cmds.append(self.vcvars_call) + + def get_oneapi_root(pth: str): + """From within a prefix known to be a oneAPI path + determine the oneAPI root path from arbitrary point + under root + + Args: + pth: path prefixed within oneAPI root + """ + if not pth: + return "" + while os.path.basename(pth) and os.path.basename(pth) != "oneAPI": + pth = os.path.dirname(pth) + return pth + + if self.fortran: + # If this found, it sets all the vars + oneapi_root = get_oneapi_root(self.fortran) + if not oneapi_root: + raise RuntimeError(f"Non-oneAPI Fortran compiler {self.fortran} assigned to MSVC") + oneapi_root_setvars = os.path.join(oneapi_root, "setvars.bat") + # some oneAPI exes return a version more precise than their + # install paths specify, so we determine path from + # the install path rather than the fc executable itself + numver = r"\d+\.\d+(?:\.\d+)?" + pattern = f"((?:{numver})|(?:latest))" + version_from_path = re.search(pattern, self.fortran).group(1) + oneapi_version_setvars = os.path.join( + oneapi_root, "compiler", version_from_path, "env", "vars.bat" + ) + env_cmds.extend( + [VarsInvocation(oneapi_version_setvars), VarsInvocation(oneapi_root_setvars)] + ) self.msvc_compiler_environment = CmdCall(*env_cmds) def _standard_flag(self, *, language: str, standard: str) -> str: