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:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						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)
 | 
			
		||||
            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}'"
 | 
			
		||||
 
 | 
			
		||||
@@ -523,6 +523,23 @@ def _specfile_for(spec_str, filename):
 | 
			
		||||
            ],
 | 
			
		||||
            "^[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",
 | 
			
		||||
            [
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user