summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMassimiliano Culpo <massimiliano.culpo@googlemail.com>2017-09-12 01:20:49 +0200
committerscheibelp <scheibel1@llnl.gov>2017-09-11 16:20:49 -0700
commit32117c22deb97c0be06ef073c432e45569b138c3 (patch)
tree8e359659cac3965b7bfc0bcde94ad680e1c150a4 /lib
parentf502de47252ec8388339e2e72321779c57581d9a (diff)
downloadspack-32117c22deb97c0be06ef073c432e45569b138c3.tar.gz
spack-32117c22deb97c0be06ef073c432e45569b138c3.tar.bz2
spack-32117c22deb97c0be06ef073c432e45569b138c3.tar.xz
spack-32117c22deb97c0be06ef073c432e45569b138c3.zip
'with_or_without' accepts bool variants
Fixes #4112 This commit extends the support of the AutotoolsPackage methods `with_or_without` and `enable_or_disable` to bool-valued variants. It also defines for those functions a convenience short-cut if the activation parameter is the prefix of a spec (like in `--with-{pkg}={prefix}`). This commit also includes: * Updates to viennarna and adios accordingly: they have been modified to use `enable_or_disable` and `with_or_without` * Improved docstrings in `autotools.py`. Raise `KeyError` if name is not a variant.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/build_systems/autotools.py160
-rw-r--r--lib/spack/spack/test/build_systems.py27
2 files changed, 151 insertions, 36 deletions
diff --git a/lib/spack/spack/build_systems/autotools.py b/lib/spack/spack/build_systems/autotools.py
index afabb90820..b78d3ed026 100644
--- a/lib/spack/spack/build_systems/autotools.py
+++ b/lib/spack/spack/build_systems/autotools.py
@@ -291,49 +291,161 @@ class AutotoolsPackage(PackageBase):
self._if_make_target_execute('test')
self._if_make_target_execute('check')
- def _activate_or_not(self, active, inactive, name, active_parameters=None):
+ def _activate_or_not(
+ self,
+ name,
+ activation_word,
+ deactivation_word,
+ activation_value=None
+ ):
+ """This function contains the current implementation details of
+ :py:meth:`~.AutotoolsPackage.with_or_without` and
+ :py:meth:`~.AutotoolsPackage.enable_or_disable`.
+
+ Args:
+ name (str): name of the variant that is being processed
+ activation_word (str): the default activation word ('with' in the
+ case of ``with_or_without``)
+ deactivation_word (str): the default deactivation word ('without'
+ in the case of ``with_or_without``)
+ activation_value (callable): callable that accepts a single
+ value. This value is either one of the allowed values for a
+ multi-valued variant or the name of a bool-valued variant.
+ Returns the parameter to be used when the value is activated.
+
+ The special value 'prefix' can also be assigned and will return
+ ``spec[name].prefix`` as activation parameter.
+
+ Examples:
+
+ Given a package with:
+
+ .. code-block:: python
+
+ variant('foo', values=('x', 'y'), description='')
+ variant('bar', default=True, description='')
+
+ calling this function like:
+
+ .. code-block:: python
+
+ _activate_or_not(
+ 'foo', 'with', 'without', activation_value='prefix'
+ )
+ _activate_or_not('bar', 'with', 'without')
+
+ will generate the following configuration options:
+
+ .. code-block:: console
+
+ --with-x=<prefix-to-x> --without-y --with-bar
+
+ for ``<spec-name> foo=x +bar``
+
+ Returns:
+ list of strings that corresponds to the activation/deactivation
+ of the variant that has been processed
+
+ Raises:
+ KeyError: if name is not among known variants
+ """
spec = self.spec
args = []
+
+ if activation_value == 'prefix':
+ activation_value = lambda x: spec[x].prefix
+
+ # Defensively look that the name passed as argument is among
+ # variants
+ if name not in self.variants:
+ msg = '"{0}" is not a variant of "{1}"'
+ raise KeyError(msg.format(name, self.name))
+
+ # Create a list of pairs. Each pair includes a configuration
+ # option and whether or not that option is activated
+ if set(self.variants[name].values) == set((True, False)):
+ # BoolValuedVariant carry information about a single option.
+ # Nonetheless, for uniformity of treatment we'll package them
+ # in an iterable of one element.
+ condition = '+{name}'.format(name=name)
+ options = [(name, condition in spec)]
+ else:
+ condition = '{name}={value}'
+ options = [
+ (value, condition.format(name=name, value=value) in spec)
+ for value in self.variants[name].values
+ ]
+
# For each allowed value in the list of values
- for value in self.variants[name].values:
- # Check if the value is active in the current spec
- condition = '{name}={value}'.format(name=name, value=value)
- activated = condition in spec
+ for option_value, activated in options:
# Search for an override in the package for this value
- override_name = '{0}_or_{1}_{2}'.format(active, inactive, value)
+ override_name = '{0}_or_{1}_{2}'.format(
+ activation_word, deactivation_word, option_value
+ )
line_generator = getattr(self, override_name, None)
# If not available use a sensible default
if line_generator is None:
def _default_generator(is_activated):
if is_activated:
- line = '--{0}-{1}'.format(active, value)
- if active_parameters is not None and active_parameters(value): # NOQA=ignore=E501
- line += '={0}'.format(active_parameters(value))
+ line = '--{0}-{1}'.format(
+ activation_word, option_value
+ )
+ if activation_value is not None and activation_value(option_value): # NOQA=ignore=E501
+ line += '={0}'.format(
+ activation_value(option_value)
+ )
return line
- return '--{0}-{1}'.format(inactive, value)
+ return '--{0}-{1}'.format(deactivation_word, option_value)
line_generator = _default_generator
args.append(line_generator(activated))
return args
- def with_or_without(self, name, active_parameters=None):
- """Inspects the multi-valued variant 'name' and returns the configure
- arguments that activate / deactivate the selected feature.
+ def with_or_without(self, name, activation_value=None):
+ """Inspects a variant and returns the arguments that activate
+ or deactivate the selected feature(s) for the configure options.
+
+ This function works on all type of variants. For bool-valued variants
+ it will return by default ``--with-{name}`` or ``--without-{name}``.
+ For other kinds of variants it will cycle over the allowed values and
+ return either ``--with-{value}`` or ``--without-{value}``.
+
+ If activation_value is given, then for each possible value of the
+ variant, the option ``--with-{value}=activation_value(value)`` or
+ ``--without-{value}`` will be added depending on whether or not
+ ``variant=value`` is in the spec.
- :param str name: name of a valid multi-valued variant
- :param callable active_parameters: if present accepts a single value
- and returns the parameter to be used leading to an entry of the
- type '--with-{name}={parameter}
+ Args:
+ name (str): name of a valid multi-valued variant
+ activation_value (callable): callable that accepts a single
+ value and returns the parameter to be used leading to an entry
+ of the type ``--with-{name}={parameter}``.
+
+ The special value 'prefix' can also be assigned and will return
+ ``spec[name].prefix`` as activation parameter.
+
+ Returns:
+ list of arguments to configure
"""
- return self._activate_or_not(
- 'with', 'without', name, active_parameters
- )
+ return self._activate_or_not(name, 'with', 'without', activation_value)
+
+ def enable_or_disable(self, name, activation_value=None):
+ """Same as :py:meth:`~.AutotoolsPackage.with_or_without` but substitute
+ ``with`` with ``enable`` and ``without`` with ``disable``.
+
+ Args:
+ name (str): name of a valid multi-valued variant
+ activation_value (callable): if present accepts a single value
+ and returns the parameter to be used leading to an entry of the
+ type ``--enable-{name}={parameter}``
+
+ The special value 'prefix' can also be assigned and will return
+ ``spec[name].prefix`` as activation parameter.
- def enable_or_disable(self, name, active_parameters=None):
- """Inspects the multi-valued variant 'name' and returns the configure
- arguments that activate / deactivate the selected feature.
+ Returns:
+ list of arguments to configure
"""
return self._activate_or_not(
- 'enable', 'disable', name, active_parameters
+ name, 'enable', 'disable', activation_value
)
run_after('install')(PackageBase._run_default_install_time_test_callbacks)
diff --git a/lib/spack/spack/test/build_systems.py b/lib/spack/spack/test/build_systems.py
index 114497bccd..9960966e2f 100644
--- a/lib/spack/spack/test/build_systems.py
+++ b/lib/spack/spack/test/build_systems.py
@@ -53,20 +53,23 @@ class TestAutotoolsPackage(object):
pkg = spack.repo.get(s)
# Called without parameters
- l = pkg.with_or_without('foo')
- assert '--with-bar' in l
- assert '--without-baz' in l
- assert '--no-fee' in l
+ options = pkg.with_or_without('foo')
+ assert '--with-bar' in options
+ assert '--without-baz' in options
+ assert '--no-fee' in options
def activate(value):
return 'something'
- l = pkg.with_or_without('foo', active_parameters=activate)
- assert '--with-bar=something' in l
- assert '--without-baz' in l
- assert '--no-fee' in l
+ options = pkg.with_or_without('foo', activation_value=activate)
+ assert '--with-bar=something' in options
+ assert '--without-baz' in options
+ assert '--no-fee' in options
- l = pkg.enable_or_disable('foo')
- assert '--enable-bar' in l
- assert '--disable-baz' in l
- assert '--disable-fee' in l
+ options = pkg.enable_or_disable('foo')
+ assert '--enable-bar' in options
+ assert '--disable-baz' in options
+ assert '--disable-fee' in options
+
+ options = pkg.with_or_without('bvv')
+ assert '--with-bvv' in options