Apply dev specs for dependencies of roots (#30909)
Currently, develop specs that are not roots and are not explicitly listed dependencies of the roots are not applied. - [x] ensure dev specs are applied. Co-authored-by: Todd Gamblin <tgamblin@llnl.gov>
This commit is contained in:
parent
8fb8381b6f
commit
a30b60f9a6
@ -102,7 +102,15 @@ def getter(node):
|
|||||||
ast_sym = ast_getter("symbol", "term")
|
ast_sym = ast_getter("symbol", "term")
|
||||||
|
|
||||||
#: Order of precedence for version origins. Topmost types are preferred.
|
#: Order of precedence for version origins. Topmost types are preferred.
|
||||||
version_origin_fields = ["spec", "external", "packages_yaml", "package_py", "installed"]
|
version_origin_fields = [
|
||||||
|
"spec",
|
||||||
|
"dev_spec",
|
||||||
|
"external",
|
||||||
|
"packages_yaml",
|
||||||
|
"package_py",
|
||||||
|
"installed",
|
||||||
|
]
|
||||||
|
|
||||||
#: Look up version precedence strings by enum id
|
#: Look up version precedence strings by enum id
|
||||||
version_origin_str = {i: name for i, name in enumerate(version_origin_fields)}
|
version_origin_str = {i: name for i, name in enumerate(version_origin_fields)}
|
||||||
|
|
||||||
@ -1489,7 +1497,7 @@ class Body(object):
|
|||||||
|
|
||||||
return clauses
|
return clauses
|
||||||
|
|
||||||
def build_version_dict(self, possible_pkgs, specs):
|
def build_version_dict(self, possible_pkgs):
|
||||||
"""Declare any versions in specs not declared in packages."""
|
"""Declare any versions in specs not declared in packages."""
|
||||||
self.declared_versions = collections.defaultdict(list)
|
self.declared_versions = collections.defaultdict(list)
|
||||||
self.possible_versions = collections.defaultdict(set)
|
self.possible_versions = collections.defaultdict(set)
|
||||||
@ -1530,6 +1538,8 @@ def key_fn(item):
|
|||||||
DeclaredVersion(version=ver, idx=idx, origin=version_provenance.packages_yaml)
|
DeclaredVersion(version=ver, idx=idx, origin=version_provenance.packages_yaml)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def add_concrete_versions_from_specs(self, specs, origin):
|
||||||
|
"""Add concrete versions to possible versions from lists of CLI/dev specs."""
|
||||||
for spec in specs:
|
for spec in specs:
|
||||||
for dep in spec.traverse():
|
for dep in spec.traverse():
|
||||||
if not dep.versions.concrete:
|
if not dep.versions.concrete:
|
||||||
@ -1553,7 +1563,7 @@ def key_fn(item):
|
|||||||
# about*, add it to the known versions. Use idx=0, which is the
|
# about*, add it to the known versions. Use idx=0, which is the
|
||||||
# best possible, so they're guaranteed to be used preferentially.
|
# best possible, so they're guaranteed to be used preferentially.
|
||||||
self.declared_versions[dep.name].append(
|
self.declared_versions[dep.name].append(
|
||||||
DeclaredVersion(version=dep.version, idx=0, origin=version_provenance.spec)
|
DeclaredVersion(version=dep.version, idx=0, origin=origin)
|
||||||
)
|
)
|
||||||
self.possible_versions[dep.name].add(dep.version)
|
self.possible_versions[dep.name].add(dep.version)
|
||||||
|
|
||||||
@ -1944,11 +1954,28 @@ def setup(self, driver, specs, reuse=None):
|
|||||||
# rules to generate an ASP program.
|
# rules to generate an ASP program.
|
||||||
self.gen = driver
|
self.gen = driver
|
||||||
|
|
||||||
|
# Calculate develop specs
|
||||||
|
# they will be used in addition to command line specs
|
||||||
|
# in determining known versions/targets/os
|
||||||
|
dev_specs = ()
|
||||||
|
env = ev.active_environment()
|
||||||
|
if env:
|
||||||
|
dev_specs = tuple(
|
||||||
|
spack.spec.Spec(info["spec"]).constrained(
|
||||||
|
"dev_path=%s"
|
||||||
|
% spack.util.path.canonicalize_path(info["path"], default_wd=env.path)
|
||||||
|
)
|
||||||
|
for name, info in env.dev_specs.items()
|
||||||
|
)
|
||||||
|
specs = tuple(specs) # ensure compatible types to add
|
||||||
|
|
||||||
# get possible compilers
|
# get possible compilers
|
||||||
self.possible_compilers = self.generate_possible_compilers(specs)
|
self.possible_compilers = self.generate_possible_compilers(specs)
|
||||||
|
|
||||||
# traverse all specs and packages to build dict of possible versions
|
# traverse all specs and packages to build dict of possible versions
|
||||||
self.build_version_dict(possible, specs)
|
self.build_version_dict(possible)
|
||||||
|
self.add_concrete_versions_from_specs(specs, version_provenance.spec)
|
||||||
|
self.add_concrete_versions_from_specs(dev_specs, version_provenance.dev_spec)
|
||||||
|
|
||||||
self.gen.h1("Concrete input spec definitions")
|
self.gen.h1("Concrete input spec definitions")
|
||||||
self.define_concrete_input_specs(specs, possible)
|
self.define_concrete_input_specs(specs, possible)
|
||||||
@ -1966,8 +1993,8 @@ def setup(self, driver, specs, reuse=None):
|
|||||||
|
|
||||||
# architecture defaults
|
# architecture defaults
|
||||||
self.platform_defaults()
|
self.platform_defaults()
|
||||||
self.os_defaults(specs)
|
self.os_defaults(specs + dev_specs)
|
||||||
self.target_defaults(specs)
|
self.target_defaults(specs + dev_specs)
|
||||||
|
|
||||||
self.virtual_providers()
|
self.virtual_providers()
|
||||||
self.provider_defaults()
|
self.provider_defaults()
|
||||||
@ -1984,11 +2011,8 @@ def setup(self, driver, specs, reuse=None):
|
|||||||
self.target_preferences(pkg)
|
self.target_preferences(pkg)
|
||||||
|
|
||||||
# Inject dev_path from environment
|
# Inject dev_path from environment
|
||||||
env = ev.active_environment()
|
for ds in dev_specs:
|
||||||
if env:
|
self.condition(spack.spec.Spec(ds.name), ds, msg="%s is a develop spec" % ds.name)
|
||||||
for spec in sorted(specs):
|
|
||||||
for dep in spec.traverse():
|
|
||||||
_develop_specs_from_env(dep, env)
|
|
||||||
|
|
||||||
self.gen.h1("Spec Constraints")
|
self.gen.h1("Spec Constraints")
|
||||||
self.literal_specs(specs)
|
self.literal_specs(specs)
|
||||||
@ -2311,8 +2335,7 @@ def _develop_specs_from_env(spec, env):
|
|||||||
"Internal Error: The dev_path for spec {name} is not connected to a valid environment"
|
"Internal Error: The dev_path for spec {name} is not connected to a valid environment"
|
||||||
"path. Please note that develop specs can only be used inside an environment"
|
"path. Please note that develop specs can only be used inside an environment"
|
||||||
"These paths should be the same:\n\tdev_path:{dev_path}\n\tenv_based_path:{env_path}"
|
"These paths should be the same:\n\tdev_path:{dev_path}\n\tenv_based_path:{env_path}"
|
||||||
)
|
).format(name=spec.name, dev_path=spec.variants["dev_path"], env_path=path)
|
||||||
error_msg.format(name=spec.name, dev_path=spec.variants["dev_path"], env_path=path)
|
|
||||||
|
|
||||||
assert spec.variants["dev_path"].value == path, error_msg
|
assert spec.variants["dev_path"].value == path, error_msg
|
||||||
else:
|
else:
|
||||||
|
@ -254,13 +254,18 @@ def test_dev_build_env_version_mismatch(
|
|||||||
def test_dev_build_multiple(
|
def test_dev_build_multiple(
|
||||||
tmpdir, mock_packages, install_mockery, mutable_mock_env_path, mock_fetch
|
tmpdir, mock_packages, install_mockery, mutable_mock_env_path, mock_fetch
|
||||||
):
|
):
|
||||||
"""Test spack install with multiple developer builds"""
|
"""Test spack install with multiple developer builds
|
||||||
|
|
||||||
|
Test that only the root needs to be specified in the environment
|
||||||
|
Test that versions known only from the dev specs are included in the solve,
|
||||||
|
even if they come from a non-root
|
||||||
|
"""
|
||||||
# setup dev-build-test-install package for dev build
|
# setup dev-build-test-install package for dev build
|
||||||
# Wait to concretize inside the environment to set dev_path on the specs;
|
# Wait to concretize inside the environment to set dev_path on the specs;
|
||||||
# without the environment, the user would need to set dev_path for both the
|
# without the environment, the user would need to set dev_path for both the
|
||||||
# root and dependency if they wanted a dev build for both.
|
# root and dependency if they wanted a dev build for both.
|
||||||
leaf_dir = tmpdir.mkdir("leaf")
|
leaf_dir = tmpdir.mkdir("leaf")
|
||||||
leaf_spec = spack.spec.Spec("dev-build-test-install@0.0.0")
|
leaf_spec = spack.spec.Spec("dev-build-test-install@1.0.0")
|
||||||
leaf_pkg_cls = spack.repo.path.get_pkg_class(leaf_spec.name)
|
leaf_pkg_cls = spack.repo.path.get_pkg_class(leaf_spec.name)
|
||||||
with leaf_dir.as_cwd():
|
with leaf_dir.as_cwd():
|
||||||
with open(leaf_pkg_cls.filename, "w") as f:
|
with open(leaf_pkg_cls.filename, "w") as f:
|
||||||
@ -283,13 +288,12 @@ def test_dev_build_multiple(
|
|||||||
"""\
|
"""\
|
||||||
env:
|
env:
|
||||||
specs:
|
specs:
|
||||||
- dev-build-test-install@0.0.0
|
|
||||||
- dev-build-test-dependent@0.0.0
|
- dev-build-test-dependent@0.0.0
|
||||||
|
|
||||||
develop:
|
develop:
|
||||||
dev-build-test-install:
|
dev-build-test-install:
|
||||||
path: %s
|
path: %s
|
||||||
spec: dev-build-test-install@0.0.0
|
spec: dev-build-test-install@1.0.0
|
||||||
dev-build-test-dependent:
|
dev-build-test-dependent:
|
||||||
spec: dev-build-test-dependent@0.0.0
|
spec: dev-build-test-dependent@0.0.0
|
||||||
path: %s
|
path: %s
|
||||||
@ -300,6 +304,7 @@ def test_dev_build_multiple(
|
|||||||
env("create", "test", "./spack.yaml")
|
env("create", "test", "./spack.yaml")
|
||||||
with ev.read("test"):
|
with ev.read("test"):
|
||||||
# Do concretization inside environment for dev info
|
# Do concretization inside environment for dev info
|
||||||
|
# These specs are the source of truth to compare against the installs
|
||||||
leaf_spec.concretize()
|
leaf_spec.concretize()
|
||||||
root_spec.concretize()
|
root_spec.concretize()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user