Conversation
|
Can't wait to test this on packages like boost and PyTorch! With the old concretizer, I have to disable half of the variants in PyTorch because they don't exist. |
aeecaf2 to
1724798
Compare
|
@becker33: does this work well at all with the old concretizer? I love this feature but had been thinking it would really suck without a proper solver. I guess we don't have to worry too much longer, as 0.17 will make the new one default. |
|
@tgamblin it seems to work reasonably well with the old concretizer -- it's at least passing all the tests there. I do think it increases the capability to express relationships that the old concretizer can't solve, but it won't break existing packages/variants until someone updates to use it, and at that point I think it's better to model reality well than conform to the old concretizer well, given that the new one will be default soon. |
87652d4 to
2ff0898
Compare
|
Tested this with Click to expand!diff --git a/var/spack/repos/builtin/packages/py-torch/package.py b/var/spack/repos/builtin/packages/py-torch/package.py
index 63c7cac7cc..dc002ae210 100644
--- a/var/spack/repos/builtin/packages/py-torch/package.py
+++ b/var/spack/repos/builtin/packages/py-torch/package.py
@@ -49,51 +49,36 @@ class PyTorch(PythonPackage, CudaPackage):
# All options are defined in CMakeLists.txt.
# Some are listed in setup.py, but not all.
- variant('caffe2', default=True, description='Build Caffe2')
+ variant('caffe2', default=True, when='@1.7:', description='Build Caffe2')
variant('cuda', default=not is_darwin, description='Use CUDA')
- variant('rocm', default=False, description='Use ROCm')
- variant('cudnn', default=not is_darwin, description='Use cuDNN')
- variant('fbgemm', default=True, description='Use FBGEMM (quantized 8-bit server operators)')
- variant('kineto', default=True, description='Use Kineto profiling library')
- variant('magma', default=not is_darwin, description='Use MAGMA')
+ variant('rocm', default=False, when='@1.0:', description='Use ROCm')
+ variant('cudnn', default=not is_darwin, when='@1.0: +cuda', description='Use cuDNN')
+ variant('fbgemm', default=True, when='@1.0:', description='Use FBGEMM (quantized 8-bit server operators)')
+ variant('kineto', default=True, when='@1.8:', description='Use Kineto profiling library')
+ variant('magma', default=not is_darwin, when='+cuda', description='Use MAGMA')
variant('metal', default=is_darwin, description='Use Metal for Caffe2 iOS build')
- variant('nccl', default=not is_darwin, description='Use NCCL')
+ variant('nccl', default=not is_darwin, when='+cuda platform=linux', description='Use NCCL')
+ variant('nccl', default=not is_darwin, when='+cuda platform=cray', description='Use NCCL')
+ variant('nccl', default=not is_darwin, when='+rocm platform=linux', description='Use NCCL')
+ variant('nccl', default=not is_darwin, when='+rocm platform=cray', description='Use NCCL')
variant('nnpack', default=True, description='Use NNPACK')
- variant('numa', default=not is_darwin, description='Use NUMA')
+ variant('numa', default=not is_darwin, when='platform=linux', description='Use NUMA')
+ variant('numa', default=not is_darwin, when='platform=cray', description='Use NUMA')
variant('numpy', default=True, description='Use NumPy')
variant('openmp', default=True, description='Use OpenMP for parallel code')
- variant('qnnpack', default=True, description='Use QNNPACK (quantized 8-bit operators)')
- variant('valgrind', default=not is_darwin, description='Use Valgrind')
- variant('xnnpack', default=True, description='Use XNNPACK')
- variant('mkldnn', default=True, description='Use MKLDNN')
+ variant('qnnpack', default=True, when='@1.0:', description='Use QNNPACK (quantized 8-bit operators)')
+ variant('valgrind', default=not is_darwin, when='@1.8: platform=linux', description='Use Valgrind')
+ variant('valgrind', default=not is_darwin, when='@1.8: platform=cray', description='Use Valgrind')
+ variant('xnnpack', default=True, when='@1.5:', description='Use XNNPACK')
+ variant('mkldnn', default=True, when='@1.0:', description='Use MKLDNN')
variant('distributed', default=not is_darwin, description='Use distributed')
- variant('mpi', default=not is_darwin, description='Use MPI for Caffe2')
- variant('gloo', default=not is_darwin, description='Use Gloo')
- variant('tensorpipe', default=not is_darwin, description='Use TensorPipe')
- variant('onnx_ml', default=True, description='Enable traditional ONNX ML API')
-
- conflicts('+cuda', when='+rocm')
- conflicts('+cudnn', when='~cuda')
- conflicts('+magma', when='~cuda')
- conflicts('+nccl', when='~cuda~rocm')
- conflicts('+nccl', when='platform=darwin')
- conflicts('+numa', when='platform=darwin', msg='Only available on Linux')
- conflicts('+valgrind', when='platform=darwin', msg='Only available on Linux')
- conflicts('+mpi', when='~distributed')
- conflicts('+gloo', when='~distributed')
- conflicts('+tensorpipe', when='~distributed')
- conflicts('+kineto', when='@:1.7.999')
- conflicts('+valgrind', when='@:1.7.999')
- conflicts('~caffe2', when='@0.4.0:1.6.999') # no way to disable caffe2?
- conflicts('+caffe2', when='@:0.3.1') # caffe2 did not yet exist?
- conflicts('+tensorpipe', when='@:1.5.999')
- conflicts('+xnnpack', when='@:1.4.999')
- conflicts('~onnx_ml', when='@:1.4.999') # no way to disable ONNX?
- conflicts('+rocm', when='@:0.4.999')
- conflicts('+cudnn', when='@:0.4.999')
- conflicts('+fbgemm', when='@:0.4.999,1.4.0')
- conflicts('+qnnpack', when='@:0.4.999')
- conflicts('+mkldnn', when='@:0.4.999')
+ variant('mpi', default=not is_darwin, when='+mpi', description='Use MPI for Caffe2')
+ variant('gloo', default=not is_darwin, when='+mpi', description='Use Gloo')
+ variant('tensorpipe', default=not is_darwin, when='@1.6: +mpi', description='Use TensorPipe')
+ variant('onnx_ml', default=True, when='@1.5:', description='Enable traditional ONNX ML API')
+
+ conflicts('+cuda+rocm')
+ conflicts('+fbgemm', when='@1.4.0')
conflicts('cuda_arch=none', when='+cuda',
msg='Must specify CUDA compute capabilities of your GPU, see 'Here is what I observed:
Another idea that would be interesting. Right now there are a lot of packages with something like: if self.spec.satisfies('@1.2:'):
if '+foo' in self.spec:
args.append('--enable-foo')
else:
args.append('--disable-foo')GDAL is a good example of this. I'm wondering if the following would also work if the if '+foo' in self.spec:
args.append('--enable-foo')
elif '~foo' in self.spec:
args.append('--disable-foo') |
|
@adamjstewart thanks for checking this out! This PR extends the when syntax to allow a list of conditions (for could become The reason I did that is because separate defaults per-declaration cannot work without some really substantial work, and I don't want people to try However, as long as only the when-clause is changing, I can probably make that work in the interest of not confusing people who are used to the old syntax. (The new syntax does work for all the other commands that accept when clauses though, so it should catch on well enough for "or"). I'll take a look at making the duplicate variant declarations work for |
Does this work for all directives, not just variant? That's really cool! |
|
Yep, it works for all directives! I don't have tests in for all of them, but I have tests in for Also, multiply defined variants work now as long as you don't try to change the defaults/values/validators. |
e40c5e7 to
421f3dc
Compare
alalazo
left a comment
There was a problem hiding this comment.
Generally this looks great. I tried modifying cp2k and I can make all the CUDA related variants disappear if ~cuda is in the spec. This should give a sensible improvement in readability for complex specs!
The only major thing: I have been a bit puzzled by the extension of the when= argument to accept a list of specs. My first impression is that it is not obvious that this would be an OR and it is effectively syntactic sugar for having two directives with different when= arguments. It also deviates a bit from the declarative nature of directives. I guess I have two questions:
- Is this feature technically necessary to get conditional variants?
- Should we at least check what would be user reactions to it (mine and @adamjstewart seem to be opposite)?
Also, this slight modification:
diff --git a/lib/spack/spack/directives.py b/lib/spack/spack/directives.py
index 45d9fd52d3..9b21e99bb3 100644
--- a/lib/spack/spack/directives.py
+++ b/lib/spack/spack/directives.py
@@ -252,7 +252,7 @@ def _wrapper(*args, **kwargs):
if DirectiveMeta._when_constraints_from_context:
# Check that directives not yet supporting the when= argument
# are not used inside the context manager
- if decorated_function.__name__ in ('version', 'variant'):
+ if decorated_function.__name__ in ('version',):
msg = ('directive "{0}" cannot be used within a "when"'
' context since it does not support a "when=" '
'argument')is needed to make this feature work with the when context manager.
| variant_desc, _ = self.variants[name] | ||
| if set(variant_desc.values) == set((True, False)): |
There was a problem hiding this comment.
If I am reading this correctly here we are treating the absence of a variant as if it was set to False and so we'll emit e.g. a --disable-foo if self.enable_or_disabled('foo') is called. Just wanted to double check this is the semantics we want, rather than just disregarding it.
There was a problem hiding this comment.
I think in this case it would throw an exception on line 443, because it unconditionally gets the variant from a dictionary.
| max(cols, 70) - max_name - max_vals - 14, | ||
| ) | ||
| self.column_widths = (max_name, max_vals, max_description) | ||
| self.column_widths = (max_name, max_when, max_vals, max_description) |
There was a problem hiding this comment.
It would be nice to not display the when column at all if it isn't used by a package.
lib/spack/spack/directives.py
Outdated
| _patch_order_index = 0 | ||
|
|
||
|
|
||
| def make_when_specs(value): |
There was a problem hiding this comment.
The function name is very similar to make_when_spec so maybe we should change it. Also it would probably be good to prepend both names with an underscore to make it clear they are used only in this module.
This is in addition to allowing multiple whens per-definition Multiply defined variants must have the same default/values/validators
e04e94b to
a589faa
Compare
|
The failure on Fedora is happening on many PRs. It is unrelated to changes and possibly due to synchronization issues with upstream when new Fedora releases are pushed. |
This broke in spack#24858
|
Did we ever add support for |
This broke in spack#24858


A common question from users has been how to model variants that are new in new versions of a package, or variants that are dependent on other variants. Our stock answer so far has been an unsatisfying combination of "just have it do nothing in the old versoin" and "tell Spack it conflicts".
This PR enables conditional variants, on any spec condition. The syntax is straightforward, and matches that of previous features.
PR includes tests.
Closes #9740
This is a prereq to addressing #14337