diff --git a/.ci/env b/.ci/env
index e9328370248..5c0b654b90a 100644
--- a/.ci/env
+++ b/.ci/env
@@ -1,2 +1,2 @@
-SPACK_CHECKOUT_VERSION=84cb7ff86b42e7fa45476750b6729144c58f70dc
+SPACK_CHECKOUT_VERSION=df98ad4289a7234bd9a443151d70c3f75668fdcf
SPACK_CHECKOUT_REPO=spack/spack
diff --git a/.ci/gitlab/.gitlab-ci.yml b/.ci/gitlab/.gitlab-ci.yml
index 748612ea3b5..67de4ae21f8 100644
--- a/.ci/gitlab/.gitlab-ci.yml
+++ b/.ci/gitlab/.gitlab-ci.yml
@@ -116,6 +116,7 @@ default:
- mkdir "${CI_PROJECT_DIR}/jobs_scratch_dir/${SPACK_CI_STACK_NAME}"
- spack
config blame > "${CI_PROJECT_DIR}/jobs_scratch_dir/${SPACK_CI_STACK_NAME}/spack.yaml.blame"
+ # - spack solve --show all > "${CI_PROJECT_DIR}/jobs_scratch_dir/${SPACK_CI_STACK_NAME}/solve.out"
- spack -v --color=always
ci generate --check-index-only -j ${SPACK_CONCRETIZE_JOBS}
--forward-variable SPACK_CHECKOUT_VERSION
diff --git a/repos/spack_repo/builtin/packages/compiler_wrapper/package.py b/repos/spack_repo/builtin/packages/compiler_wrapper/package.py
index eef1d7e1ad5..151673ba724 100644
--- a/repos/spack_repo/builtin/packages/compiler_wrapper/package.py
+++ b/repos/spack_repo/builtin/packages/compiler_wrapper/package.py
@@ -6,11 +6,14 @@
import sys
from spack_repo.builtin.build_systems.generic import Package
+from spack_repo.builtin.build_systems.nmake import NMakeBuilder, NMakePackage
from spack.package import *
+IS_WINDOWS = sys.platform == "win32"
-class CompilerWrapper(Package):
+
+class CompilerWrapper(Package, NMakePackage):
"""Spack compiler wrapper script.
Compiler commands go through this compiler wrapper in Spack builds.
@@ -26,125 +29,75 @@ class CompilerWrapper(Package):
3. It provides a mechanism to inject flags from specs
"""
- homepage = "https://github.com/spack/spack"
- url = "https://github.com/spack/compiler-wrapper/releases/download/v1.0/compiler-wrapper-1.0.tar.gz"
+ homepage_nix = "https://github.com/spack/spack"
+ url_nix = "https://github.com/spack/compiler-wrapper/releases/download/v1.0/compiler-wrapper-1.0.tar.gz"
+
+ homepage_win = "https://github.com/spack/msvc-wrapper"
+ url_win = "https://github.com/spack/msvc-wrapper/archive/refs/tags/v0.1.0.tar.gz"
+ git_win = "https://github.com/spack/msvc-wrapper.git"
+
+ homepage = homepage_win if IS_WINDOWS else homepage_nix
+ url = url_win if IS_WINDOWS else url_nix
+ if IS_WINDOWS:
+ git = git_win
# FIXME (compiler as nodes): use a different tag, since this is only to exclude
# this node from auto-generated rules
tags = ["runtime"]
- maintainers("haampie")
+ maintainers("haampie", "johnwparent")
license("Apache-2.0 OR MIT")
- if sys.platform != "win32":
+ default_builder = "nmake" if IS_WINDOWS else "generic"
+ build_system("generic", conditional("nmake", when="platform=windows"), default=default_builder)
+
+ if not IS_WINDOWS:
version("1.1.0", sha256="a07b35081d14b0729090bc1e5790a5dda2d5b997e064c62da39a1224ee249b2a")
version("1.0", sha256="ac876f7600fa6cb0c74ae172ef1c61661aacff03a6befbc7d87e092e2f2233f9")
else:
- version("1.0")
- has_code = False
+ # version("develop", branch="main")
+ version("1.0", commit="51358dd5c37a77b9a5816b6f9c8e3e4f6e07fb78")
+
+ depends_on("msvc", when="platform=windows", type=("build", "run"))
def bin_dir(self) -> pathlib.Path:
# This adds an extra "spack" subdir, so that the script and symlinks don't get
# their way to the default view
return pathlib.Path(str(self.prefix)) / "libexec" / "spack"
- def install(self, spec, prefix):
- if sys.platform == "win32":
- placeholder = self.bin_dir() / "placeholder-wrapper"
- placeholder.parent.mkdir(parents=True)
- placeholder.write_text(
- "This file is a placeholder for the compiler wrapper on Windows."
- )
- return
+ def setup_dependent_package(self, module, dependent_spec):
+ def _spack_compiler_attribute(*, language: str) -> str:
+ compiler_pkg = dependent_spec[language].package
+ return str(self.bin_dir() / compiler_pkg.compiler_wrapper_link_paths[language])
- cc_script = pathlib.Path(self.stage.source_path) / "cc.sh"
- bin_dir = self.bin_dir()
+ if dependent_spec.has_virtual_dependency("c"):
+ setattr(module, "spack_cc", _spack_compiler_attribute(language="c"))
- # Copy the script
- bin_dir.mkdir(parents=True)
- installed_script = bin_dir / "cc"
- shutil.copy(cc_script, str(installed_script))
- set_executable(installed_script)
+ if dependent_spec.has_virtual_dependency("cxx"):
+ setattr(module, "spack_cxx", _spack_compiler_attribute(language="cxx"))
- # Create links to use the script under different names
- for name in (
- "ld.lld",
- "ld.gold",
- "ld",
- "ftn",
- "fc",
- "f95",
- "f90",
- "f77",
- "cpp",
- "c99",
- "c89",
- "c++",
- ):
- (bin_dir / name).symlink_to(installed_script)
+ if dependent_spec.has_virtual_dependency("fortran"):
+ setattr(module, "spack_fc", _spack_compiler_attribute(language="fortran"))
+ setattr(module, "spack_f77", _spack_compiler_attribute(language="fortran"))
- for subdir, name in (
- ("aocc", "clang"),
- ("aocc", "clang++"),
- ("aocc", "flang"),
- ("arm", "armclang"),
- ("arm", "armclang++"),
- ("arm", "armflang"),
- ("case-insensitive", "CC"),
- ("cce", "cc"),
- ("cce", "craycc"),
- ("cce", "crayftn"),
- ("cce", "ftn"),
- ("clang", "clang"),
- ("clang", "clang++"),
- ("clang", "flang"),
- ("fj", "fcc"),
- ("fj", "frt"),
- ("gcc", "gcc"),
- ("gcc", "g++"),
- ("gcc", "gfortran"),
- ("intel", "icc"),
- ("intel", "icpc"),
- ("intel", "ifort"),
- ("nag", "nagfor"),
- ("nvhpc", "nvc"),
- ("nvhpc", "nvc++"),
- ("nvhpc", "nvfortran"),
- ("oneapi", "icx"),
- ("oneapi", "icpx"),
- ("oneapi", "ifx"),
- ("rocmcc", "amdclang"),
- ("rocmcc", "amdclang++"),
- ("rocmcc", "amdflang"),
- ("xl", "xlc"),
- ("xl", "xlc++"),
- ("xl", "xlf"),
- ("xl", "xlf90"),
- ("xl_r", "xlc_r"),
- ("xl_r", "xlc++_r"),
- ("xl_r", "xlf_r"),
- ("xl_r", "xlf90_r"),
- ):
- (bin_dir / subdir).mkdir(exist_ok=True)
- (bin_dir / subdir / name).symlink_to(installed_script)
+ @property
+ def disable_new_dtags(self) -> str:
+ if self.spec.satisfies("platform=darwin"):
+ return ""
+ return "--disable-new-dtags"
- # Extra symlinks for Cray
- cray_dir = bin_dir / "cce" / "case-insensitive"
- cray_dir.mkdir(exist_ok=True)
- (cray_dir / "crayCC").symlink_to(installed_script)
- (cray_dir / "CC").symlink_to(installed_script)
+ @property
+ def enable_new_dtags(self) -> str:
+ if self.spec.satisfies("platform=darwin"):
+ return ""
+ return "--enable-new-dtags"
- # Extra symlink for Fujitsu
- fj_dir = bin_dir / "fj" / "case-insensitive"
- fj_dir.mkdir(exist_ok=True)
- (fj_dir / "FCC").symlink_to(installed_script)
+class EnvironmentSetup:
def setup_dependent_build_environment(
self, env: EnvironmentModifications, dependent_spec: Spec
) -> None:
- if sys.platform == "win32":
- return
_var_list = []
if dependent_spec.has_virtual_dependency("c"):
@@ -156,12 +109,11 @@ def setup_dependent_build_environment(
if dependent_spec.has_virtual_dependency("fortran"):
_var_list.append(("fortran", "fortran", "F77", "SPACK_F77"))
_var_list.append(("fortran", "fortran", "FC", "SPACK_FC"))
-
# The package is not used as a compiler, so skip this setup
if not _var_list:
return
- bin_dir = self.bin_dir()
+ bin_dir = self.pkg.bin_dir()
implicit_rpaths, env_paths = [], []
extra_rpaths = []
for language, attr_name, wrapper_var_name, spack_var_name in _var_list:
@@ -172,6 +124,9 @@ def setup_dependent_build_environment(
compiler = getattr(compiler_pkg, attr_name)
env.set(spack_var_name, compiler)
+ if hasattr(compiler_pkg, "ld"):
+ env.set("SPACK_LD", compiler_pkg.ld)
+
# -frandom-seed= is needed for deterministic builds with GCC
if compiler_pkg.name == "gcc" and self.spec.satisfies("@1.1:"):
env.set(f"SPACK_{wrapper_var_name}_HAS_FRANDOM_SEED", "1")
@@ -229,45 +184,122 @@ def setup_dependent_build_environment(
extra_rpaths = dedupe(extra_rpaths)
env.set("SPACK_COMPILER_EXTRA_RPATHS", ":".join(extra_rpaths))
- env.set("SPACK_ENABLE_NEW_DTAGS", self.enable_new_dtags)
- env.set("SPACK_DISABLE_NEW_DTAGS", self.disable_new_dtags)
+ env.set("SPACK_ENABLE_NEW_DTAGS", self.pkg.enable_new_dtags)
+ env.set("SPACK_DISABLE_NEW_DTAGS", self.pkg.disable_new_dtags)
for item in env_paths:
env.prepend_path("SPACK_COMPILER_WRAPPER_PATH", item)
- def setup_dependent_package(self, module, dependent_spec):
- def _spack_compiler_attribute(*, language: str) -> str:
- compiler_pkg = dependent_spec[language].package
- if sys.platform != "win32":
- # On non-Windows we return the appropriate path to the compiler wrapper
- return str(self.bin_dir() / compiler_pkg.compiler_wrapper_link_paths[language])
-
- # On Windows we return the real compiler
- if language == "c":
- return compiler_pkg.cc
- elif language == "cxx":
- return compiler_pkg.cxx
- elif language == "fortran":
- return compiler_pkg.fortran
+ env.set("SPACK_CONTEXT_ROOT", dependent_spec.package.stage.source_path)
+ if IS_WINDOWS:
+ env.set("SPACK_DEBUG_WRAPPER", "ON")
- if dependent_spec.has_virtual_dependency("c"):
- setattr(module, "spack_cc", _spack_compiler_attribute(language="c"))
- if dependent_spec.has_virtual_dependency("cxx"):
- setattr(module, "spack_cxx", _spack_compiler_attribute(language="cxx"))
+class GenericBuilder(GenericBuilder, EnvironmentSetup):
+ def install(self, pkg, spec, prefix):
+ cc_script = pathlib.Path(self.stage.source_path) / "cc.sh"
+ bin_dir = pkg.bin_dir()
- if dependent_spec.has_virtual_dependency("fortran"):
- setattr(module, "spack_fc", _spack_compiler_attribute(language="fortran"))
- setattr(module, "spack_f77", _spack_compiler_attribute(language="fortran"))
+ # Copy the script
+ bin_dir.mkdir(parents=True)
+ installed_script = bin_dir / "cc"
+ shutil.copy(cc_script, str(installed_script))
+ set_executable(installed_script)
- @property
- def disable_new_dtags(self) -> str:
- if self.spec.satisfies("platform=darwin"):
- return ""
- return "--disable-new-dtags"
+ # Create links to use the script under different names
+ for name in (
+ "ld.lld",
+ "ld.gold",
+ "ld",
+ "ftn",
+ "fc",
+ "f95",
+ "f90",
+ "f77",
+ "cpp",
+ "c99",
+ "c89",
+ "c++",
+ ):
+ (bin_dir / name).symlink_to(installed_script)
- @property
- def enable_new_dtags(self) -> str:
- if self.spec.satisfies("platform=darwin"):
- return ""
- return "--enable-new-dtags"
+ for subdir, name in (
+ ("aocc", "clang"),
+ ("aocc", "clang++"),
+ ("aocc", "flang"),
+ ("arm", "armclang"),
+ ("arm", "armclang++"),
+ ("arm", "armflang"),
+ ("case-insensitive", "CC"),
+ ("cce", "cc"),
+ ("cce", "craycc"),
+ ("cce", "crayftn"),
+ ("cce", "ftn"),
+ ("clang", "clang"),
+ ("clang", "clang++"),
+ ("clang", "flang"),
+ ("fj", "fcc"),
+ ("fj", "frt"),
+ ("gcc", "gcc"),
+ ("gcc", "g++"),
+ ("gcc", "gfortran"),
+ ("intel", "icc"),
+ ("intel", "icpc"),
+ ("intel", "ifort"),
+ ("nag", "nagfor"),
+ ("nvhpc", "nvc"),
+ ("nvhpc", "nvc++"),
+ ("nvhpc", "nvfortran"),
+ ("oneapi", "icx"),
+ ("oneapi", "icpx"),
+ ("oneapi", "ifx"),
+ ("rocmcc", "amdclang"),
+ ("rocmcc", "amdclang++"),
+ ("rocmcc", "amdflang"),
+ ("xl", "xlc"),
+ ("xl", "xlc++"),
+ ("xl", "xlf"),
+ ("xl", "xlf90"),
+ ("xl_r", "xlc_r"),
+ ("xl_r", "xlc++_r"),
+ ("xl_r", "xlf_r"),
+ ("xl_r", "xlf90_r"),
+ ):
+ (bin_dir / subdir).mkdir(exist_ok=True)
+ (bin_dir / subdir / name).symlink_to(installed_script)
+
+ # Extra symlinks for Cray
+ cray_dir = bin_dir / "cce" / "case-insensitive"
+ cray_dir.mkdir(exist_ok=True)
+ (cray_dir / "crayCC").symlink_to(installed_script)
+ (cray_dir / "CC").symlink_to(installed_script)
+
+ # Extra symlink for Fujitsu
+ fj_dir = bin_dir / "fj" / "case-insensitive"
+ fj_dir.mkdir(exist_ok=True)
+ (fj_dir / "FCC").symlink_to(installed_script)
+
+
+class NMakeBuilder(NMakeBuilder, EnvironmentSetup):
+ install_targets = ["install"]
+ build_targets = ["cl.exe"]
+
+ def install(self, pkg, spec, prefix):
+ bin_dir = pkg.bin_dir()
+ opts = self.std_nmake_args
+ opts.append(self.define("PREFIX", str(bin_dir)))
+ with working_dir(self.build_directory):
+ nmake(*opts, *self.install_targets, ignore_quotes=self.ignore_quotes)
+
+ # Create links to use the script under different names
+ for name in ("link", "ftn", "fc", "f95", "f90", "f77", "cpp", "c99", "c89", "c++"):
+ (bin_dir / name).symlink_to(bin_dir / "cl.exe")
+
+ for subdir, name in (
+ ("case-insensitive", "CC.exe"),
+ ("intel", "ifort.exe"),
+ ("oneapi", "ifx.exe"),
+ ("msvc", "cl.exe"),
+ ):
+ (bin_dir / subdir).mkdir(exist_ok=True)
+ (bin_dir / subdir / name).symlink_to(bin_dir / "cl.exe")
diff --git a/repos/spack_repo/builtin/packages/msmpi/ifort_nd_compat.patch b/repos/spack_repo/builtin/packages/msmpi/ifort_nd_compat.patch
index a75c0841b4b..3ef6f842ef9 100644
--- a/repos/spack_repo/builtin/packages/msmpi/ifort_nd_compat.patch
+++ b/repos/spack_repo/builtin/packages/msmpi/ifort_nd_compat.patch
@@ -37,7 +37,7 @@ index 24bd29d..319153d 100644
+ /D _WIN64=1 /D _AMD64_=1 /D AMD64=1
-
-+
++
diff --git a/repos/spack_repo/builtin/packages/msvc/package.py b/repos/spack_repo/builtin/packages/msvc/package.py
index 3f1fe49d72e..c0e7c211f70 100644
--- a/repos/spack_repo/builtin/packages/msvc/package.py
+++ b/repos/spack_repo/builtin/packages/msvc/package.py
@@ -2,6 +2,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os.path
+import pathlib
import re
import subprocess
@@ -46,12 +47,15 @@ def install(self, spec, prefix):
compiler_version_argument = ""
compiler_version_regex = r"([1-9][0-9]*\.[0-9]*\.[0-9]*)"
- # Due to the challenges of supporting compiler wrappers
- # in Windows, we leave these blank, and dynamically compute
- # based on proper versions of MSVC from there
- # pending acceptance of #28117 for full support using
- # compiler wrappers
- compiler_wrapper_link_paths = {"c": "", "cxx": "", "fortran": ""}
+ compiler_wrapper_link_paths = {
+ "c": "msvc\\cl.exe",
+ "cxx": "msvc\\cl.exe",
+ "fortran": "oneapi\\ifx.exe",
+ }
+
+ version("19.39.33523")
+ version("19.16.27054")
+ version("19.16.27051")
provides("c", "cxx", "fortran")
requires("platform=windows", msg="MSVC is only supported on Windows")
@@ -75,6 +79,17 @@ 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"]
+
+ # Spack's msvc compiler wrapper also wraps the linker
+ # to inject rpath-analogous behavior into Windows
+ # binaries. We define the linker so we can
+ # expose it to the run environmnet of the wrapper
+ # similar to how we do CC vs SPACK_CC
+ # the linker is always in the same directory as the compiler
+ extras["compilers"]["ld"] = str(
+ pathlib.Path(extras["compilers"]["cxx"]).parent / "link.exe"
+ )
+
# This depends on oneapi being processed before msvc
# which is guarunteed from detection behavior.
# Processing oneAPI tracks oneAPI installations within
@@ -125,13 +140,10 @@ def setup_dependent_build_environment(
else:
env.set_path(env_var, int_env[env_var].split(os.pathsep))
- if self.cc:
- env.set("CC", self.cc)
- if self.cxx:
- env.set("CXX", self.cxx)
- if self.fortran:
- env.set("FC", self.fortran)
- env.set("F77", self.fortran)
+ def setup_dependent_run_environment(
+ self, env: EnvironmentModifications, dependent_spec: Spec
+ ) -> None:
+ self.setup_dependent_build_environment(env=env, dependent_spec=dependent_spec)
def init_msvc(self):
# To use the MSVC compilers, VCVARS must be invoked
@@ -264,6 +276,17 @@ def platform_toolset_ver(self):
vs22_toolset = Version(toolset_ver) > Version("142")
return toolset_ver if not vs22_toolset else "143"
+ @property
+ def ld(self):
+ assert self.spec.concrete, "cannot retrieve C++ linker, spec is not concrete"
+ assert self.spec.external, (
+ "MSVC is external only, please report this bug to the Spack maintainers"
+ )
+ ld = self.spec.extra_attributes.get("compilers", {}).get("ld", None)
+ if not ld:
+ ld = os.path.join(os.path.dirname(self.cc), "link.exe")
+ return ld
+
class CmdCall:
"""Compose a call to `cmd` for an ordered series of cmd commands/scripts"""
diff --git a/repos/spack_repo/builtin/packages/win_gpg/package.py b/repos/spack_repo/builtin/packages/win_gpg/package.py
index e0aa633ade2..168432988e4 100644
--- a/repos/spack_repo/builtin/packages/win_gpg/package.py
+++ b/repos/spack_repo/builtin/packages/win_gpg/package.py
@@ -25,8 +25,6 @@ class WinGpg(Package):
version("2.4.5", sha256="249ab87bd06abea3140054089bad44d9a5d1531413590576da609142db2673ec")
- depends_on("c", type="build")
-
@classmethod
def determine_version(cls, exe):
output = Executable(exe)("--version", output=str, error=str)