Fix SPACK-40: Finish adding variant directive.
- Variants are now declarable in packages using the variant() directive. - Variants are checked - you can't just ask for a random variant, it has to be declared. - conditional logic (@when, if, '+debug' in spec, etc.) still required in package to implement variant.
This commit is contained in:
parent
c105a8d42a
commit
3b1898b8e4
@ -22,12 +22,22 @@
|
|||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
import textwrap
|
||||||
from llnl.util.tty.colify import *
|
from llnl.util.tty.colify import *
|
||||||
import spack
|
import spack
|
||||||
import spack.fetch_strategy as fs
|
import spack.fetch_strategy as fs
|
||||||
|
|
||||||
description = "Get detailed information on a particular package"
|
description = "Get detailed information on a particular package"
|
||||||
|
|
||||||
|
def padder(str_list, extra=0):
|
||||||
|
"""Return a function to pad elements of a list."""
|
||||||
|
length = max(len(str(s)) for s in str_list) + extra
|
||||||
|
def pad(string):
|
||||||
|
string = str(string)
|
||||||
|
padding = max(0, length - len(string))
|
||||||
|
return string + (padding * ' ')
|
||||||
|
return pad
|
||||||
|
|
||||||
|
|
||||||
def setup_parser(subparser):
|
def setup_parser(subparser):
|
||||||
subparser.add_argument('name', metavar="PACKAGE", help="Name of package to get info for.")
|
subparser.add_argument('name', metavar="PACKAGE", help="Name of package to get info for.")
|
||||||
@ -42,13 +52,24 @@ def print_text_info(pkg):
|
|||||||
print "Safe versions: "
|
print "Safe versions: "
|
||||||
|
|
||||||
if not pkg.versions:
|
if not pkg.versions:
|
||||||
print("None.")
|
print("None")
|
||||||
else:
|
else:
|
||||||
maxlen = max(len(str(v)) for v in pkg.versions)
|
pad = padder(pkg.versions, 4)
|
||||||
fmt = "%%-%ss" % maxlen
|
|
||||||
for v in reversed(sorted(pkg.versions)):
|
for v in reversed(sorted(pkg.versions)):
|
||||||
f = fs.for_package_version(pkg, v)
|
f = fs.for_package_version(pkg, v)
|
||||||
print " " + (fmt % v) + " " + str(f)
|
print " %s%s" % (pad(v), str(f))
|
||||||
|
|
||||||
|
print
|
||||||
|
print "Variants:"
|
||||||
|
if not pkg.variants:
|
||||||
|
print "None"
|
||||||
|
else:
|
||||||
|
pad = padder(pkg.variants, 4)
|
||||||
|
for name in sorted(pkg.variants):
|
||||||
|
v = pkg.variants[name]
|
||||||
|
print " %s%s" % (
|
||||||
|
pad(('+' if v.default else '-') + name + ':'),
|
||||||
|
"\n".join(textwrap.wrap(v.description)))
|
||||||
|
|
||||||
print
|
print
|
||||||
print "Dependencies:"
|
print "Dependencies:"
|
||||||
|
@ -58,6 +58,7 @@ class OpenMpi(Package):
|
|||||||
import spack.url
|
import spack.url
|
||||||
from spack.version import Version
|
from spack.version import Version
|
||||||
from spack.patch import Patch
|
from spack.patch import Patch
|
||||||
|
from spack.variant import Variant
|
||||||
from spack.spec import Spec, parse_anonymous_spec
|
from spack.spec import Spec, parse_anonymous_spec
|
||||||
|
|
||||||
|
|
||||||
@ -240,17 +241,17 @@ def patch(pkg, url_or_filename, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
@directive(dicts='variants')
|
@directive(dicts='variants')
|
||||||
def variant(pkg, name, description=""):
|
def variant(pkg, name, **kwargs):
|
||||||
"""Define a variant for the package. Allows the user to supply
|
"""Define a variant for the package. Packager can specify a default
|
||||||
+variant/-variant in a spec. You can optionally supply an
|
value (on or off) as well as a text description."""
|
||||||
initial + or - to make the variant enabled or disabled by defaut.
|
|
||||||
"""
|
|
||||||
if not re.match(r'^[-~+]?[A-Za-z0-9_][A-Za-z0-9_.-]*$', name):
|
|
||||||
raise DirectiveError("Invalid variant name in %s: '%s'"
|
|
||||||
% (pkg.name, name))
|
|
||||||
|
|
||||||
enabled = re.match(r'+', name)
|
default = bool(kwargs.get('default', False))
|
||||||
pkg.variants[name] = enabled
|
description = str(kwargs.get('description', "")).strip()
|
||||||
|
|
||||||
|
if not re.match(spack.spec.identifier_re, name):
|
||||||
|
raise DirectiveError("Invalid variant name in %s: '%s'" % (pkg.name, name))
|
||||||
|
|
||||||
|
pkg.variants[name] = Variant(default, description)
|
||||||
|
|
||||||
|
|
||||||
class DirectiveError(spack.error.SpackError):
|
class DirectiveError(spack.error.SpackError):
|
||||||
|
@ -110,6 +110,9 @@
|
|||||||
from spack.util.prefix import Prefix
|
from spack.util.prefix import Prefix
|
||||||
from spack.virtual import ProviderIndex
|
from spack.virtual import ProviderIndex
|
||||||
|
|
||||||
|
# Valid pattern for an identifier in Spack
|
||||||
|
identifier_re = r'\w[\w-]*'
|
||||||
|
|
||||||
# Convenient names for color formats so that other things can use them
|
# Convenient names for color formats so that other things can use them
|
||||||
compiler_color = '@g'
|
compiler_color = '@g'
|
||||||
version_color = '@c'
|
version_color = '@c'
|
||||||
@ -893,6 +896,11 @@ def validate_names(self):
|
|||||||
if not compilers.supported(spec.compiler):
|
if not compilers.supported(spec.compiler):
|
||||||
raise UnsupportedCompilerError(spec.compiler.name)
|
raise UnsupportedCompilerError(spec.compiler.name)
|
||||||
|
|
||||||
|
# Ensure that variants all exist.
|
||||||
|
for vname, variant in spec.variants.items():
|
||||||
|
if vname not in spec.package.variants:
|
||||||
|
raise UnknownVariantError(spec.name, vname)
|
||||||
|
|
||||||
|
|
||||||
def constrain(self, other, **kwargs):
|
def constrain(self, other, **kwargs):
|
||||||
other = self._autospec(other)
|
other = self._autospec(other)
|
||||||
@ -1354,6 +1362,8 @@ def __init__(self):
|
|||||||
(r'\~', lambda scanner, val: self.token(OFF, val)),
|
(r'\~', lambda scanner, val: self.token(OFF, val)),
|
||||||
(r'\%', lambda scanner, val: self.token(PCT, val)),
|
(r'\%', lambda scanner, val: self.token(PCT, val)),
|
||||||
(r'\=', lambda scanner, val: self.token(EQ, val)),
|
(r'\=', lambda scanner, val: self.token(EQ, val)),
|
||||||
|
# This is more liberal than identifier_re (see above).
|
||||||
|
# Checked by check_identifier() for better error messages.
|
||||||
(r'\w[\w.-]*', lambda scanner, val: self.token(ID, val)),
|
(r'\w[\w.-]*', lambda scanner, val: self.token(ID, val)),
|
||||||
(r'\s+', lambda scanner, val: None)])
|
(r'\s+', lambda scanner, val: None)])
|
||||||
|
|
||||||
@ -1580,6 +1590,13 @@ def __init__(self, compiler_name):
|
|||||||
"The '%s' compiler is not yet supported." % compiler_name)
|
"The '%s' compiler is not yet supported." % compiler_name)
|
||||||
|
|
||||||
|
|
||||||
|
class UnknownVariantError(SpecError):
|
||||||
|
"""Raised when the same variant occurs in a spec twice."""
|
||||||
|
def __init__(self, pkg, variant):
|
||||||
|
super(UnknownVariantError, self).__init__(
|
||||||
|
"Package %s has no variant %s!" % (pkg, variant))
|
||||||
|
|
||||||
|
|
||||||
class DuplicateArchitectureError(SpecError):
|
class DuplicateArchitectureError(SpecError):
|
||||||
"""Raised when the same architecture occurs in a spec twice."""
|
"""Raised when the same architecture occurs in a spec twice."""
|
||||||
def __init__(self, message):
|
def __init__(self, message):
|
||||||
|
@ -30,6 +30,9 @@ class Mpich(Package):
|
|||||||
list_url = "http://www.mpich.org/static/downloads/"
|
list_url = "http://www.mpich.org/static/downloads/"
|
||||||
list_depth = 2
|
list_depth = 2
|
||||||
|
|
||||||
|
variant('debug', default=False,
|
||||||
|
description="Compile MPICH with debug flags.")
|
||||||
|
|
||||||
version('3.0.4', '9c5d5d4fe1e17dd12153f40bc5b6dbc0')
|
version('3.0.4', '9c5d5d4fe1e17dd12153f40bc5b6dbc0')
|
||||||
version('3.0.3', 'foobarbaz')
|
version('3.0.3', 'foobarbaz')
|
||||||
version('3.0.2', 'foobarbaz')
|
version('3.0.2', 'foobarbaz')
|
||||||
|
Loading…
Reference in New Issue
Block a user