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.
This commit is contained in:
parent
7f4f42894d
commit
7e8415a3a6
5 changed files with 77 additions and 4 deletions
|
@ -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.
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -809,12 +809,22 @@ def solve(self, setup, specs, reuse=None, output=None, control=None, allow_depre
|
|||
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 @@ def condition(
|
|||
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.
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in a new issue