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:
		 Massimiliano Culpo
					Massimiliano Culpo
				
			
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			 GitHub
						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) |             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", | ||||||
|             [ |             [ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user