concretizer: swap priority of selecting provider and default variant (#20182)
refers #20040 Before this PR optimization rules would have selected default providers at a higher priority than default variants. Here we swap this priority and we consider variants that are forced by any means (root spec or spec in depends_on clause) the same as if they were with a default value. This prevents the solver from avoiding expected configurations just because they contain directives like: depends_on('pkg+foo') and `+foo` is not the default variant value for pkg.
This commit is contained in:
		 Massimiliano Culpo
					Massimiliano Culpo
				
			
				
					committed by
					
						 Tamara Dahlgren
						Tamara Dahlgren
					
				
			
			
				
	
			
			
			 Tamara Dahlgren
						Tamara Dahlgren
					
				
			
						parent
						
							96283867d6
						
					
				
				
					commit
					22d7937c50
				
			| @@ -194,6 +194,7 @@ variant_value(Package, Variant, Value) | |||||||
| variant_not_default(Package, Variant, Value, 1) | variant_not_default(Package, Variant, Value, 1) | ||||||
|  :- variant_value(Package, Variant, Value), |  :- variant_value(Package, Variant, Value), | ||||||
|     not variant_default_value(Package, Variant, Value), |     not variant_default_value(Package, Variant, Value), | ||||||
|  |     not variant_set(Package, Variant, Value), | ||||||
|     node(Package). |     node(Package). | ||||||
|  |  | ||||||
| variant_not_default(Package, Variant, Value, 0) | variant_not_default(Package, Variant, Value, 0) | ||||||
| @@ -201,6 +202,12 @@ variant_not_default(Package, Variant, Value, 0) | |||||||
|     variant_default_value(Package, Variant, Value), |     variant_default_value(Package, Variant, Value), | ||||||
|     node(Package). |     node(Package). | ||||||
|  |  | ||||||
|  | variant_not_default(Package, Variant, Value, 0) | ||||||
|  |  :- variant_value(Package, Variant, Value), | ||||||
|  |     variant_set(Package, Variant, Value), | ||||||
|  |     node(Package). | ||||||
|  |  | ||||||
|  |  | ||||||
| % The default value for a variant in a package is what is written | % The default value for a variant in a package is what is written | ||||||
| % in the package.py file, unless some preference is set in packages.yaml | % in the package.py file, unless some preference is set in packages.yaml | ||||||
| variant_default_value(Package, Variant, Value) | variant_default_value(Package, Variant, Value) | ||||||
| @@ -508,28 +515,24 @@ root(Dependency, 1) :- not root(Dependency), node(Dependency). | |||||||
|     : provider_weight(Provider, Weight), root(Provider) |     : provider_weight(Provider, Weight), root(Provider) | ||||||
| }. | }. | ||||||
|  |  | ||||||
| % Next, we want to minimize the weights of the providers |  | ||||||
| % i.e. use as much as possible the most preferred providers |  | ||||||
| #minimize{ |  | ||||||
|     Weight@11,Provider |  | ||||||
|     : provider_weight(Provider, Weight), not root(Provider) |  | ||||||
| }. |  | ||||||
|  |  | ||||||
| % For external packages it's more important than for others | % For external packages it's more important than for others | ||||||
| % to match the compiler with their parent node | % to match the compiler with their parent node | ||||||
| #maximize{ | #maximize{ | ||||||
|     Weight@10,Package |     Weight@12,Package | ||||||
|     : compiler_version_match(Package, Weight), external(Package) |     : compiler_version_match(Package, Weight), external(Package) | ||||||
| }. | }. | ||||||
|  |  | ||||||
| % Then try to use as much as possible: | % Try to use default variants or variants that have been set | ||||||
| % 1. Default variants |  | ||||||
| % 2. Latest versions |  | ||||||
| % of all the other nodes in the DAG |  | ||||||
| #minimize { | #minimize { | ||||||
|     Weight@9,Package,Variant,Value |     Weight@11,Package,Variant,Value | ||||||
|     : variant_not_default(Package, Variant, Value, Weight), not root(Package) |     : variant_not_default(Package, Variant, Value, Weight), not root(Package) | ||||||
| }. | }. | ||||||
|  | % Minimize the weights of the providers, i.e. use as much as | ||||||
|  | % possible the most preferred providers | ||||||
|  | #minimize{ | ||||||
|  |     Weight@9,Provider | ||||||
|  |     : provider_weight(Provider, Weight), not root(Provider) | ||||||
|  | }. | ||||||
| % If the value is a multivalued variant there could be multiple | % If the value is a multivalued variant there could be multiple | ||||||
| % values set as default. Since a default value has a weight of 0 we | % values set as default. Since a default value has a weight of 0 we | ||||||
| % need to maximize their number below to ensure they're all set | % need to maximize their number below to ensure they're all set | ||||||
|   | |||||||
| @@ -943,3 +943,14 @@ def test_compiler_match_is_preferred_to_newer_version(self): | |||||||
|     def test_target_ranges_in_conflicts(self): |     def test_target_ranges_in_conflicts(self): | ||||||
|         with pytest.raises(spack.error.SpackError): |         with pytest.raises(spack.error.SpackError): | ||||||
|             Spec('impossible-concretization').concretized() |             Spec('impossible-concretization').concretized() | ||||||
|  | 
 | ||||||
|  |     @pytest.mark.regression('20040') | ||||||
|  |     def test_variant_not_default(self): | ||||||
|  |         s = Spec('ecp-viz-sdk').concretized() | ||||||
|  | 
 | ||||||
|  |         # Check default variant value for the package | ||||||
|  |         assert '+dep' in s['conditional-constrained-dependencies'] | ||||||
|  | 
 | ||||||
|  |         # Check that non-default variant values are forced on the dependency | ||||||
|  |         d = s['dep-with-variants'] | ||||||
|  |         assert '+foo+bar+baz' in d | ||||||
|   | |||||||
| @@ -0,0 +1,16 @@ | |||||||
|  | # Copyright 2013-2020 Lawrence Livermore National Security, LLC and other | ||||||
|  | # Spack Project Developers. See the top-level COPYRIGHT file for details. | ||||||
|  | # | ||||||
|  | # SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||||||
|  | class ConditionalConstrainedDependencies(Package): | ||||||
|  |     """Package that has a variant which adds a dependency forced to | ||||||
|  |     use non default values. | ||||||
|  |     """ | ||||||
|  |     homepage = "https://dev.null" | ||||||
|  | 
 | ||||||
|  |     version('1.0') | ||||||
|  | 
 | ||||||
|  |     # This variant is on by default and attaches a dependency | ||||||
|  |     # with a lot of variants set at their non-default values | ||||||
|  |     variant('dep', default=True, description='nope') | ||||||
|  |     depends_on('dep-with-variants+foo+bar+baz', when='+dep') | ||||||
| @@ -0,0 +1,15 @@ | |||||||
|  | # Copyright 2013-2020 Lawrence Livermore National Security, LLC and other | ||||||
|  | # Spack Project Developers. See the top-level COPYRIGHT file for details. | ||||||
|  | # | ||||||
|  | # SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||||||
|  | class DepWithVariants(Package): | ||||||
|  |     """Package that has a variant which adds a dependency forced to | ||||||
|  |     use non default values. | ||||||
|  |     """ | ||||||
|  |     homepage = "https://dev.null" | ||||||
|  | 
 | ||||||
|  |     version('1.0') | ||||||
|  | 
 | ||||||
|  |     variant('foo', default=False, description='nope') | ||||||
|  |     variant('bar', default=False, description='nope') | ||||||
|  |     variant('baz', default=False, description='nope') | ||||||
							
								
								
									
										14
									
								
								var/spack/repos/builtin.mock/packages/ecp-viz-sdk/package.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								var/spack/repos/builtin.mock/packages/ecp-viz-sdk/package.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | |||||||
|  | # Copyright 2013-2020 Lawrence Livermore National Security, LLC and other | ||||||
|  | # Spack Project Developers. See the top-level COPYRIGHT file for details. | ||||||
|  | # | ||||||
|  | # SPDX-License-Identifier: (Apache-2.0 OR MIT) | ||||||
|  | class EcpVizSdk(Package): | ||||||
|  |     """Package that has a dependency with a variant which | ||||||
|  |     adds a transitive dependency forced to use non default | ||||||
|  |     values. | ||||||
|  |     """ | ||||||
|  |     homepage = "https://dev.null" | ||||||
|  | 
 | ||||||
|  |     version('1.0') | ||||||
|  | 
 | ||||||
|  |     depends_on('conditional-constrained-dependencies') | ||||||
		Reference in New Issue
	
	Block a user