Merge virtuals=
from duplicate dependencies (#42281)
Previously, for abstract specs like: ``` foo ^[virtuals=a] bar ^[virtuals=b] bar ``` the second requirement was silently discarded on concretization. Now they're merged, and the abstract spec is equivalent to: ``` foo ^[virtuals=a,b] bar ```
This commit is contained in:
parent
4c7a1f541c
commit
19df8e45ec
@ -1640,23 +1640,23 @@ def _add_dependency(self, spec: "Spec", *, depflag: dt.DepFlag, virtuals: Tuple[
|
|||||||
self.add_dependency_edge(spec, depflag=depflag, virtuals=virtuals)
|
self.add_dependency_edge(spec, depflag=depflag, virtuals=virtuals)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Keep the intersection of constraints when a dependency is added
|
# Keep the intersection of constraints when a dependency is added multiple times.
|
||||||
# multiple times. Currently, we only allow identical edge types.
|
# The only restriction, currently, is keeping the same dependency type
|
||||||
orig = self._dependencies[spec.name]
|
orig = self._dependencies[spec.name]
|
||||||
try:
|
try:
|
||||||
dspec = next(dspec for dspec in orig if depflag == dspec.depflag)
|
dspec = next(dspec for dspec in orig if depflag == dspec.depflag)
|
||||||
except StopIteration:
|
except StopIteration:
|
||||||
current_deps = ", ".join(
|
edge_attrs = f"deptypes={dt.flag_to_chars(depflag).strip()}"
|
||||||
dt.flag_to_chars(x.depflag) + " " + x.spec.short_spec for x in orig
|
required_dep_str = f"^[{edge_attrs}] {str(spec)}"
|
||||||
)
|
|
||||||
raise DuplicateDependencyError(
|
raise DuplicateDependencyError(
|
||||||
f"{self.short_spec} cannot depend on '{spec.short_spec}' multiple times.\n"
|
f"{spec.name} is a duplicate dependency, with conflicting dependency types\n"
|
||||||
f"\tRequired: {dt.flag_to_chars(depflag)}\n"
|
f"\t'{str(self)}' cannot depend on '{required_dep_str}'"
|
||||||
f"\tDependency: {current_deps}"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dspec.spec.constrain(spec)
|
dspec.spec.constrain(spec)
|
||||||
|
dspec.update_virtuals(virtuals=virtuals)
|
||||||
except spack.error.UnsatisfiableSpecError:
|
except spack.error.UnsatisfiableSpecError:
|
||||||
raise DuplicateDependencyError(
|
raise DuplicateDependencyError(
|
||||||
f"Cannot depend on incompatible specs '{dspec.spec}' and '{spec}'"
|
f"Cannot depend on incompatible specs '{dspec.spec}' and '{spec}'"
|
||||||
|
@ -523,6 +523,23 @@ def _specfile_for(spec_str, filename):
|
|||||||
],
|
],
|
||||||
"^[virtuals=mpi] openmpi",
|
"^[virtuals=mpi] openmpi",
|
||||||
),
|
),
|
||||||
|
# Allow merging attributes, if deptypes match
|
||||||
|
(
|
||||||
|
"^[virtuals=mpi] openmpi+foo ^[virtuals=lapack] openmpi+bar",
|
||||||
|
[
|
||||||
|
Token(TokenType.START_EDGE_PROPERTIES, value="^["),
|
||||||
|
Token(TokenType.KEY_VALUE_PAIR, value="virtuals=mpi"),
|
||||||
|
Token(TokenType.END_EDGE_PROPERTIES, value="]"),
|
||||||
|
Token(TokenType.UNQUALIFIED_PACKAGE_NAME, value="openmpi"),
|
||||||
|
Token(TokenType.BOOL_VARIANT, value="+foo"),
|
||||||
|
Token(TokenType.START_EDGE_PROPERTIES, value="^["),
|
||||||
|
Token(TokenType.KEY_VALUE_PAIR, value="virtuals=lapack"),
|
||||||
|
Token(TokenType.END_EDGE_PROPERTIES, value="]"),
|
||||||
|
Token(TokenType.UNQUALIFIED_PACKAGE_NAME, value="openmpi"),
|
||||||
|
Token(TokenType.BOOL_VARIANT, value="+bar"),
|
||||||
|
],
|
||||||
|
"^[virtuals=lapack,mpi] openmpi+bar+foo",
|
||||||
|
),
|
||||||
(
|
(
|
||||||
"^[deptypes=link,build] zlib",
|
"^[deptypes=link,build] zlib",
|
||||||
[
|
[
|
||||||
|
Loading…
Reference in New Issue
Block a user