Multi-valued variants: better support for combinations (#9481)

This enforces conventions that allow for correct handling of
multi-valued variants where specifying no value is an option,
and adds convenience functionality for specifying multi-valued
variants with conflicting sets of values. This also adds a notion
of "feature values" for variants, which are those that are understood
by the build system (e.g. those that would appear as configure
options). In more detail:

* Add documentation on variants to the packaging guide
* Forbid usage of '' or None as a possible variant value, in
  particular as a default. To indicate choosing no value, the user
  must explicitly define an option like 'none'. Without this,
  multi-valued variants with default set to None were not parsable
  from the command line (Fixes #6314)
* Add "disjoint_sets" function to support the declaration of
  multi-valued variants with conflicting sets of options. For example
  a variant "foo" with possible values "a", "b", and "c" where "c"
  is exclusive of the other values ("foo=a,b" and "foo=c" are
  valid but "foo=a,c" is not).
* Add "any_combination_of" function to support the declaration of
  multi-valued variants where it is valid to choose none of the
  values. This automatically defines "none" as an option (exclusive
  with all other choices); this value does not appear when iterating
  over the variant's values, for example in "with_or_without" (which
  constructs autotools option strings from variant values).
* The "disjoint_sets" and "any_combination_of" methods return an
  object which tracks the possible values. It is also possible to
  indicate that some of these values do not correspond to options
  understood by the package's build system, such that methods like
  "with_or_without" will not define options for those values (this
  occurs automatically for "none")
* Add documentation for usage of new functions for specifying
  multi-valued variants
This commit is contained in:
Massimiliano Culpo
2019-01-05 04:02:34 +01:00
committed by Peter Scheibel
parent 051057caa3
commit c4521535e7
24 changed files with 587 additions and 91 deletions

View File

@@ -16,11 +16,8 @@ class A(AutotoolsPackage):
version('2.0', '2.0_a_hash')
variant(
'foo',
values=('bar', 'baz', 'fee'),
default='bar',
description='',
multi=True
'foo', description='',
values=any_combination_of('bar', 'baz', 'fee').with_default('bar'),
)
variant(

View File

@@ -17,10 +17,8 @@ class MultivalueVariant(Package):
variant('debug', default=False, description='Debug variant')
variant(
'foo',
description='Multi-valued variant',
values=('bar', 'baz', 'barbaz'),
multi=True
'foo', description='Multi-valued variant',
values=any_combination_of('bar', 'baz', 'barbaz'),
)
variant(

View File

@@ -61,10 +61,7 @@ class Adios(AutotoolsPackage):
variant('netcdf', default=False, description='Enable netcdf support')
variant(
'staging',
default=None,
values=('flexpath', 'dataspaces'),
multi=True,
'staging', values=any_combination_of('flexpath', 'dataspaces'),
description='Enable dataspaces and/or flexpath staging transports'
)

View File

@@ -7,7 +7,7 @@
from spack.error import SpackError
def async_api_validator(values):
def async_api_validator(pkg_name, variant_name, values):
if 'none' in values and len(values) != 1:
raise SpackError("The value 'none' is not usable"
" with other async_api values.")

View File

@@ -34,10 +34,7 @@ class Glib(AutotoolsPackage):
variant('libmount', default=False, description='Build with libmount support')
variant(
'tracing',
default='',
values=('dtrace', 'systemtap'),
multi=True,
'tracing', values=any_combination_of('dtrace', 'systemtap'),
description='Enable tracing support'
)

View File

@@ -71,7 +71,7 @@ class Kokkos(Package):
# Host architecture variant
variant(
'host_arch',
default=None,
default='none',
values=('AMDAVX', 'ARMv80', 'ARMv81', 'ARMv8-ThunderX',
'Power7', 'Power8', 'Power9',
'WSM', 'SNB', 'HSW', 'BDW', 'SKX', 'KNC', 'KNL'),
@@ -81,7 +81,7 @@ class Kokkos(Package):
# GPU architecture variant
variant(
'gpu_arch',
default=None,
default='none',
values=gpu_values,
description='Set the GPU architecture to use'
)
@@ -159,9 +159,9 @@ def install(self, spec, prefix):
host_arch = spec.variants['host_arch'].value
# GPU architectures
gpu_arch = spec.variants['gpu_arch'].value
if host_arch:
if host_arch != 'none':
arch_args.append(host_arch)
if gpu_arch:
if gpu_arch != 'none':
arch_args.append(gpu_arch)
# Combined architecture flags
if arch_args:

View File

@@ -35,7 +35,7 @@ class Matlab(Package):
variant(
'key',
default='',
default='<installation-key-here>',
values=lambda x: True, # Anything goes as a key
description='The file installation key to use'
)

View File

@@ -6,14 +6,6 @@
import sys
from spack import *
from spack.error import SpackError
def _process_manager_validator(values):
if len(values) > 1 and 'slurm' in values:
raise SpackError(
'slurm cannot be activated along with other process managers'
)
class Mvapich2(AutotoolsPackage):
@@ -70,9 +62,12 @@ class Mvapich2(AutotoolsPackage):
variant(
'process_managers',
description='List of the process managers to activate',
values=('slurm', 'hydra', 'gforker', 'remshell'),
multi=True,
validator=_process_manager_validator
values=disjoint_sets(
('auto',), ('slurm',), ('hydra', 'gforker', 'remshell')
).prohibit_empty_set().with_error(
"'slurm' or 'auto' cannot be activated along with "
"other process managers"
).with_default('auto').with_non_feature_values('auto'),
)
variant(
@@ -94,8 +89,7 @@ class Mvapich2(AutotoolsPackage):
variant(
'file_systems',
description='List of the ROMIO file systems to activate',
values=('lustre', 'gpfs', 'nfs', 'ufs'),
multi=True
values=auto_or_any_combination_of('lustre', 'gpfs', 'nfs', 'ufs'),
)
depends_on('findutils', type='build')

View File

@@ -3,8 +3,6 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack import *
class OmegaH(CMakePackage):
"""Omega_h is a C++11 library providing data structures and algorithms
@@ -28,8 +26,7 @@ class OmegaH(CMakePackage):
variant('shared', default=True, description='Build shared libraries')
variant('mpi', default=True, description='Activates MPI support')
variant('zlib', default=True, description='Activates ZLib support')
variant('trilinos', default=False, description='Use Teuchos and Kokkos')
variant('build_type', default='')
variant('trilinos', default=True, description='Use Teuchos and Kokkos')
variant('throw', default=False, description='Errors throw exceptions instead of abort')
variant('examples', default=False, description='Compile examples')
variant('optimize', default=True, description='Compile C++ with optimization')

View File

@@ -38,8 +38,8 @@ class Openblas(MakefilePackage):
variant('ilp64', default=False, description='64 bit integers')
variant('pic', default=True, description='Build position independent code')
variant('cpu_target', default='',
description='Set CPU target architecture (leave empty for '
variant('cpu_target', default='auto',
description='Set CPU target architecture (leave empty for '
'autodetection; GENERIC, SSE_GENERIC, NEHALEM, ...)')
variant(
@@ -150,7 +150,7 @@ def make_defs(self):
'NUM_THREADS=64', # OpenBLAS stores present no of CPUs as max
]
if self.spec.variants['cpu_target'].value:
if self.spec.variants['cpu_target'].value != 'auto':
make_defs += [
'TARGET={0}'.format(self.spec.variants['cpu_target'].value)
]

View File

@@ -7,8 +7,6 @@
import os
import sys
from spack import *
def _verbs_dir():
"""Try to find the directory where the OpenFabrics verbs package is
@@ -180,20 +178,17 @@ class Openmpi(AutotoolsPackage):
patch('btl_vader.patch', when='@3.1.0:3.1.2')
fabrics = ('psm', 'psm2', 'verbs', 'mxm', 'ucx', 'libfabric')
variant(
'fabrics',
default=None if _verbs_dir() is None else 'verbs',
'fabrics', values=auto_or_any_combination_of(*fabrics).with_default(
'auto' if _verbs_dir() is None else 'verbs'
),
description="List of fabrics that are enabled",
values=fabrics,
multi=True
)
schedulers = ('alps', 'lsf', 'tm', 'slurm', 'sge', 'loadleveler')
variant(
'schedulers',
description='List of schedulers for which support is enabled',
values=('alps', 'lsf', 'tm', 'slurm', 'sge', 'loadleveler'),
multi=True
'schedulers', values=auto_or_any_combination_of(*schedulers),
description='List of schedulers for which support is enabled'
)
# Additional support options

View File

@@ -3,8 +3,6 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
from spack import *
class PyPatsy(PythonPackage):
"""A Python package for describing statistical models and for
@@ -15,7 +13,7 @@ class PyPatsy(PythonPackage):
version('0.4.1', '9445f29e3426d1ed30d683a1e1453f84')
variant('splines', description="Offers spline related functions")
variant('splines', default=False, description="Offers spline related functions")
depends_on('py-setuptools', type='build')
depends_on('py-numpy', type=('build', 'run'))

View File

@@ -25,8 +25,10 @@ class Regcm(AutotoolsPackage):
# producing a so-called fat binary. Unfortunately, gcc builds only the last
# architecture provided (in the configure), so we allow a single arch.
extensions = ('knl', 'skl', 'bdw', 'nhl')
variant('extension', default=None, values=extensions, multi=True,
description='Build extensions for a specific Intel architecture.')
variant(
'extension', values=any_combination_of(extensions),
description='Build extensions for a specific Intel architecture.'
)
depends_on('netcdf')
depends_on('netcdf-fortran')

View File

@@ -47,7 +47,7 @@ class Scr(CMakePackage):
variant('scr_config', default='scr.conf',
description='Location for SCR to find its system config file. '
'May be either absolute or relative to the install prefix')
variant('copy_config', default=None,
variant('copy_config', default='none',
description='Location from which to copy SCR system config file. '
'Must be an absolute path.')
@@ -130,7 +130,7 @@ def cmake_args(self):
@run_after('install')
def copy_config(self):
spec = self.spec
if spec.variants['copy_config'].value:
if spec.variants['copy_config'].value != 'none':
dest_path = self.get_abs_path_rel_prefix(
spec.variants['scr_config'].value)
install(spec.variants['copy_config'].value, dest_path)

View File

@@ -26,19 +26,13 @@ class Yambo(AutotoolsPackage):
variant('dp', default=False, description='Enable double precision')
variant(
'profile',
values=('time', 'memory'),
default='',
description='Activate profiling of specific sections',
multi=True
'profile', values=any_combination_of('time', 'memory'),
description='Activate profiling of specific sections'
)
variant(
'io',
values=('iotk', 'etsf-io'),
default='',
'io', values=any_combination_of('iotk', 'etsf-io'),
description='Activate support for different io formats (requires network access)', # noqa
multi=True
)
# MPI + OpenMP parallelism