summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJohn W. Parent <45471568+johnwparent@users.noreply.github.com>2024-05-02 03:05:03 -0400
committerGitHub <noreply@github.com>2024-05-02 01:05:03 -0600
commit7e8415a3a6b2cf7d5644c46b6e8a7d5ef70c0ed6 (patch)
tree9686deeabbb9c80e6733dca324f372491533287a /lib
parent7f4f42894d024880f8010db71b0e189cc5ed4bb0 (diff)
downloadspack-7e8415a3a6b2cf7d5644c46b6e8a7d5ef70c0ed6.tar.gz
spack-7e8415a3a6b2cf7d5644c46b6e8a7d5ef70c0ed6.tar.bz2
spack-7e8415a3a6b2cf7d5644c46b6e8a7d5ef70c0ed6.tar.xz
spack-7e8415a3a6b2cf7d5644c46b6e8a7d5ef70c0ed6.zip
Windows: auto-add WGL/SDK as externals (#43752)
Adds a pre-concretization check for the Windows SDK and WGL (Windows GL) packages as non-buildable externals. This is a redo of https://github.com/spack/spack/pull/43459, but makes sure to modify the configuration scope outside of the bootstrap scope: whichever is highest-precedence in the user's environment at the time the concretization runs, which should either be an env scope or the ~ scope. Adds pytest fixture mocking the check for WGL and WSDK as if they were present.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/docs/getting_started.rst3
-rw-r--r--lib/spack/spack/bootstrap/core.py35
-rw-r--r--lib/spack/spack/cmd/unit_test.py2
-rw-r--r--lib/spack/spack/solver/asp.py11
-rw-r--r--lib/spack/spack/test/conftest.py30
5 files changed, 77 insertions, 4 deletions
diff --git a/lib/spack/docs/getting_started.rst b/lib/spack/docs/getting_started.rst
index ab9c274e01..25dfc95ee5 100644
--- a/lib/spack/docs/getting_started.rst
+++ b/lib/spack/docs/getting_started.rst
@@ -1572,6 +1572,8 @@ Microsoft Visual Studio
"""""""""""""""""""""""
Microsoft Visual Studio provides the only Windows C/C++ compiler that is currently supported by Spack.
+Spack additionally requires that the Windows SDK (including WGL) to be installed as part of your
+visual studio installation as it is required to build many packages from source.
We require several specific components to be included in the Visual Studio installation.
One is the C/C++ toolset, which can be selected as "Desktop development with C++" or "C++ build tools,"
@@ -1579,6 +1581,7 @@ depending on installation type (Professional, Build Tools, etc.) The other requ
"C++ CMake tools for Windows," which can be selected from among the optional packages.
This provides CMake and Ninja for use during Spack configuration.
+
If you already have Visual Studio installed, you can make sure these components are installed by
rerunning the installer. Next to your installation, select "Modify" and look at the
"Installation details" pane on the right.
diff --git a/lib/spack/spack/bootstrap/core.py b/lib/spack/spack/bootstrap/core.py
index 52d396ba9d..1b8c4d5f18 100644
--- a/lib/spack/spack/bootstrap/core.py
+++ b/lib/spack/spack/bootstrap/core.py
@@ -538,6 +538,41 @@ def ensure_patchelf_in_path_or_raise() -> spack.util.executable.Executable:
)
+def ensure_winsdk_external_or_raise() -> None:
+ """Ensure the Windows SDK + WGL are available on system
+ If both of these package are found, the Spack user or bootstrap
+ configuration (depending on where Spack is running)
+ will be updated to include all versions and variants detected.
+ If either the WDK or WSDK are not found, this method will raise
+ a RuntimeError.
+
+ **NOTE:** This modifies the Spack config in the current scope,
+ either user or environment depending on the calling context.
+ This is different from all other current bootstrap dependency
+ checks.
+ """
+ if set(["win-sdk", "wgl"]).issubset(spack.config.get("packages").keys()):
+ return
+ externals = spack.detection.by_path(["win-sdk", "wgl"])
+ if not set(["win-sdk", "wgl"]) == externals.keys():
+ missing_packages_lst = []
+ if "wgl" not in externals:
+ missing_packages_lst.append("wgl")
+ if "win-sdk" not in externals:
+ missing_packages_lst.append("win-sdk")
+ missing_packages = " & ".join(missing_packages_lst)
+ raise RuntimeError(
+ f"Unable to find the {missing_packages}, please install these packages \
+via the Visual Studio installer \
+before proceeding with Spack or provide the path to a non standard install with \
+'spack external find --path'"
+ )
+ # wgl/sdk are not required for bootstrapping Spack, but
+ # are required for building anything non trivial
+ # add to user config so they can be used by subsequent Spack ops
+ spack.detection.update_configuration(externals, buildable=False)
+
+
def ensure_core_dependencies() -> None:
"""Ensure the presence of all the core dependencies."""
if sys.platform.lower() == "linux":
diff --git a/lib/spack/spack/cmd/unit_test.py b/lib/spack/spack/cmd/unit_test.py
index db0c7ff0e5..c46012d5dc 100644
--- a/lib/spack/spack/cmd/unit_test.py
+++ b/lib/spack/spack/cmd/unit_test.py
@@ -214,8 +214,6 @@ def unit_test(parser, args, unknown_args):
# Ensure clingo is available before switching to the
# mock configuration used by unit tests
- # Note: skip on windows here because for the moment,
- # clingo is wholly unsupported from bootstrap
with spack.bootstrap.ensure_bootstrap_configuration():
spack.bootstrap.ensure_core_dependencies()
if pytest is None:
diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py
index e56fe92b57..362efc289a 100644
--- a/lib/spack/spack/solver/asp.py
+++ b/lib/spack/spack/solver/asp.py
@@ -809,12 +809,22 @@ class PyclingoDriver:
A tuple of the solve result, the timer for the different phases of the
solve, and the internal statistics from clingo.
"""
+ # avoid circular import
+ import spack.bootstrap
+
output = output or DEFAULT_OUTPUT_CONFIGURATION
timer = spack.util.timer.Timer()
# Initialize the control object for the solver
self.control = control or default_clingo_control()
+ # ensure core deps are present on Windows
+ # needs to modify active config scope, so cannot be run within
+ # bootstrap config scope
+ if sys.platform == "win32":
+ tty.debug("Ensuring basic dependencies {win-sdk, wgl} available")
+ spack.bootstrap.core.ensure_winsdk_external_or_raise()
+
timer.start("setup")
asp_problem = setup.setup(specs, reuse=reuse, allow_deprecated=allow_deprecated)
if output.out is not None:
@@ -1403,7 +1413,6 @@ class SpackSolverSetup:
raise ValueError(f"Must provide a name for anonymous condition: '{required_spec}'")
with spec_with_name(required_spec, name):
-
# Check if we can emit the requirements before updating the condition ID counter.
# In this way, if a condition can't be emitted but the exception is handled in the
# caller, we won't emit partial facts.
diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py
index 35dfff5193..59d6171e3d 100644
--- a/lib/spack/spack/test/conftest.py
+++ b/lib/spack/spack/test/conftest.py
@@ -763,6 +763,28 @@ def mutable_empty_config(tmpdir_factory, configuration_dir):
yield cfg
+# From https://github.com/pytest-dev/pytest/issues/363#issuecomment-1335631998
+# Current suggested implementation from issue compatible with pytest >= 6.2
+# this may be subject to change as new versions of Pytest are released
+# and update the suggested solution
+@pytest.fixture(scope="session")
+def monkeypatch_session():
+ with pytest.MonkeyPatch.context() as monkeypatch:
+ yield monkeypatch
+
+
+@pytest.fixture(scope="session", autouse=True)
+def mock_wsdk_externals(monkeypatch_session):
+ """Skip check for required external packages on Windows during testing
+ Note: In general this should cover this behavior for all tests,
+ however any session scoped fixture involving concretization should
+ include this fixture
+ """
+ monkeypatch_session.setattr(
+ spack.bootstrap.core, "ensure_winsdk_external_or_raise", _return_none
+ )
+
+
@pytest.fixture(scope="function")
def concretize_scope(mutable_config, tmpdir):
"""Adds a scope for concretization preferences"""
@@ -842,7 +864,13 @@ def _store_dir_and_cache(tmpdir_factory):
@pytest.fixture(scope="session")
-def mock_store(tmpdir_factory, mock_repo_path, mock_configuration_scopes, _store_dir_and_cache):
+def mock_store(
+ tmpdir_factory,
+ mock_wsdk_externals,
+ mock_repo_path,
+ mock_configuration_scopes,
+ _store_dir_and_cache,
+):
"""Creates a read-only mock database with some packages installed note
that the ref count for dyninst here will be 3, as it's recycled
across each install.