summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/spec.py16
-rw-r--r--lib/spack/spack/test/spec_syntax.py17
2 files changed, 25 insertions, 8 deletions
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index 641ad1f5e9..eb6c81a9ae 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -1640,23 +1640,23 @@ class Spec:
self.add_dependency_edge(spec, depflag=depflag, virtuals=virtuals)
return
- # Keep the intersection of constraints when a dependency is added
- # multiple times. Currently, we only allow identical edge types.
+ # Keep the intersection of constraints when a dependency is added multiple times.
+ # The only restriction, currently, is keeping the same dependency type
orig = self._dependencies[spec.name]
try:
dspec = next(dspec for dspec in orig if depflag == dspec.depflag)
except StopIteration:
- current_deps = ", ".join(
- dt.flag_to_chars(x.depflag) + " " + x.spec.short_spec for x in orig
- )
+ edge_attrs = f"deptypes={dt.flag_to_chars(depflag).strip()}"
+ required_dep_str = f"^[{edge_attrs}] {str(spec)}"
+
raise DuplicateDependencyError(
- f"{self.short_spec} cannot depend on '{spec.short_spec}' multiple times.\n"
- f"\tRequired: {dt.flag_to_chars(depflag)}\n"
- f"\tDependency: {current_deps}"
+ f"{spec.name} is a duplicate dependency, with conflicting dependency types\n"
+ f"\t'{str(self)}' cannot depend on '{required_dep_str}'"
)
try:
dspec.spec.constrain(spec)
+ dspec.update_virtuals(virtuals=virtuals)
except spack.error.UnsatisfiableSpecError:
raise DuplicateDependencyError(
f"Cannot depend on incompatible specs '{dspec.spec}' and '{spec}'"
diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py
index c421494ce8..49f6de3b65 100644
--- a/lib/spack/spack/test/spec_syntax.py
+++ b/lib/spack/spack/test/spec_syntax.py
@@ -523,6 +523,23 @@ def specfile_for(default_mock_concretization):
],
"^[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",
[