summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Becker <becker33@llnl.gov>2015-09-25 09:25:12 -0700
committerGregory Becker <becker33@llnl.gov>2015-11-10 15:45:22 -0800
commitdb1b21b9aa1bd28ef706f38e982966f7a01f6aca (patch)
treecd66cae73c0607287eb62c5d673cd247ebaf0a8b
parent7989a7f903da149d81f8e6370a9ef8a4f64c45a8 (diff)
downloadspack-db1b21b9aa1bd28ef706f38e982966f7a01f6aca.tar.gz
spack-db1b21b9aa1bd28ef706f38e982966f7a01f6aca.tar.bz2
spack-db1b21b9aa1bd28ef706f38e982966f7a01f6aca.tar.xz
spack-db1b21b9aa1bd28ef706f38e982966f7a01f6aca.zip
reclaimed the = sign. Architectures now specified by +arch= instead. Decided to prepend flag names with + for clarity in spec names and ease of parsing. Also generalized variants, although there is not yet a way to specify a generalized (name=value) variant.
-rw-r--r--lib/spack/spack/spec.py110
-rw-r--r--lib/spack/spack/test/concretize.py2
-rw-r--r--lib/spack/spack/test/multimethod.py10
-rw-r--r--lib/spack/spack/test/spec_dag.py5
-rw-r--r--lib/spack/spack/test/spec_semantics.py26
-rw-r--r--lib/spack/spack/test/spec_syntax.py1
-rw-r--r--lib/spack/spack/variant.py2
-rw-r--r--var/spack/mock_packages/multimethod/package.py8
8 files changed, 104 insertions, 60 deletions
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index 572f13901f..9c95fc2177 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -72,7 +72,7 @@ Here is the EBNF grammar for a spec::
dep_list = { ^ spec }
spec = id [ options ]
options = { @version-list | +variant | -variant | ~variant |
- %compiler | =architecture }
+ %compiler | +arch=architecture | +flag=value}
variant = id
architecture = id
compiler = id [ version-list ]
@@ -297,22 +297,25 @@ class VariantSpec(object):
on the particular package being built, and each named variant can
be enabled or disabled.
"""
- def __init__(self, name, enabled):
+ def __init__(self, name, value):
self.name = name
- self.enabled = enabled
+ self.value = value
def _cmp_key(self):
- return (self.name, self.enabled)
+ return (self.name, self.value)
def copy(self):
- return VariantSpec(self.name, self.enabled)
+ return VariantSpec(self.name, self.value)
def __str__(self):
- out = '+' if self.enabled else '~'
- return out + self.name
+ if self.value in [True,False]:
+ out = '+' if self.value else '~'
+ return out + self.name
+ else:
+ return '+' + self.name + "=" + self.value
class VariantMap(HashableMap):
@@ -323,10 +326,10 @@ class VariantMap(HashableMap):
def satisfies(self, other, strict=False):
if strict or self.spec._concrete:
- return all(k in self and self[k].enabled == other[k].enabled
+ return all(k in self and self[k].value == other[k].value
for k in other)
else:
- return all(self[k].enabled == other[k].enabled
+ return all(self[k].value == other[k].value
for k in other if k in self)
@@ -344,7 +347,7 @@ class VariantMap(HashableMap):
changed = False
for k in other:
if k in self:
- if self[k].enabled != other[k].enabled:
+ if self[k].value != other[k].value:
raise UnsatisfiableVariantSpecError(self[k], other[k])
else:
self[k] = other[k].copy()
@@ -437,12 +440,20 @@ class Spec(object):
self.versions.add(version)
- def _add_variant(self, name, enabled):
+ def _add_variant(self, name, value):
"""Called by the parser to add a variant."""
if name in self.variants: raise DuplicateVariantError(
"Cannot specify variant '%s' twice" % name)
- self.variants[name] = VariantSpec(name, enabled)
+ self.variants[name] = VariantSpec(name, value)
+ def _add_flag(self, name, value):
+ """Called by the parser to add a known flag.
+ Known flags currently include "arch"
+ """
+ if name == 'arch':
+ self._set_architecture(value)
+ else:
+ raise SpecError("Invalid flag specified")
def _set_compiler(self, compiler):
"""Called by the parser to set the compiler."""
@@ -653,7 +664,7 @@ class Spec(object):
def to_node_dict(self):
d = {
'variants' : dict(
- (name,v.enabled) for name, v in self.variants.items()),
+ (name,v.value) for name, v in self.variants.items()),
'arch' : self.architecture,
'dependencies' : dict((d, self.dependencies[d].dag_hash())
for d in sorted(self.dependencies))
@@ -690,8 +701,8 @@ class Spec(object):
else:
spec.compiler = CompilerSpec.from_dict(node)
- for name, enabled in node['variants'].items():
- spec.variants[name] = VariantSpec(name, enabled)
+ for name, value in node['variants'].items():
+ spec.variants[name] = VariantSpec(name, value)
return spec
@@ -804,6 +815,7 @@ class Spec(object):
spec._replace_with(concrete)
changed = True
+
# If there are duplicate providers or duplicate provider deps, this
# consolidates them and merge constraints.
changed |= self.normalize(force=True)
@@ -1138,7 +1150,7 @@ class Spec(object):
"""
other = self._autospec(other)
- if not self.name == other.name:
+ if not (self.name == other.name or self.name == "any-pkg-name" or other.name == "any-pkg-name"):
raise UnsatisfiableSpecNameError(self.name, other.name)
if not self.versions.overlaps(other.versions):
@@ -1146,7 +1158,7 @@ class Spec(object):
for v in other.variants:
if (v in self.variants and
- self.variants[v].enabled != other.variants[v].enabled):
+ self.variants[v].value != other.variants[v].value):
raise UnsatisfiableVariantSpecError(self.variants[v],
other.variants[v])
@@ -1228,7 +1240,10 @@ class Spec(object):
return spec_like
try:
- return spack.spec.Spec(spec_like)
+ spec = spack.spec.Spec(spec_like)
+ if spec.name == "any-pkg-name":
+ raise SpecError("anonymous package -- this will always be handled")
+ return spec
except SpecError:
return parse_anonymous_spec(spec_like, self.name)
@@ -1248,7 +1263,7 @@ class Spec(object):
"""
other = self._autospec(other)
- # A concrete provider can satisfy a virtual dependency.
+ # A concrete provider can satisfy a virtual dependency.
if not self.virtual and other.virtual:
pkg = spack.db.get(self.name)
if pkg.provides(other.name):
@@ -1622,7 +1637,7 @@ class Spec(object):
showid = kwargs.pop('ids', False)
cover = kwargs.pop('cover', 'nodes')
indent = kwargs.pop('indent', 0)
- fmt = kwargs.pop('format', '$_$@$%@$+$=')
+ fmt = kwargs.pop('format', '$_$@$%@$+$+arch=')
prefix = kwargs.pop('prefix', None)
check_kwargs(kwargs, self.tree)
@@ -1707,11 +1722,18 @@ class SpecParser(spack.parse.Parser):
elif self.accept(ON):
specs.append(self.empty_spec())
- specs[-1]._add_variant(self.variant(), True)
+ self.expect(ID)
+ self.check_identifier()
+ name = self.token.value
+ if self.accept(EQ):
+ self.expect(ID)
+ specs[-1]._add_flag(name,self.token.value)
+ else:
+ specs[-1]._add_variant(self.variant(name),True)
elif self.accept(OFF):
specs.append(self.empty_spec())
- specs[-1]._add_variant(self.variant(), False)
+ specs[-1]._add_variant(self.variant(),False)
else:
self.unexpected_token()
@@ -1719,6 +1741,10 @@ class SpecParser(spack.parse.Parser):
except spack.parse.ParseError, e:
raise SpecParseError(e)
+ for top_spec in specs:
+ for spec in top_spec.traverse():
+ if 'arch' in spec.variants:
+ spec.architecture = spec.variants['arch']
return specs
@@ -1763,10 +1789,17 @@ class SpecParser(spack.parse.Parser):
#Should we be able to add cflags eventually?
while self.next:
if self.accept(ON):
- spec._add_variant(self.variant(), True)
+ self.expect(ID)
+ self.check_identifier()
+ name = self.token.value
+ if self.accept(EQ):
+ self.expect(ID)
+ spec._add_flag(name,self.token.value)
+ else:
+ spec._add_variant(self.variant(name),True)
elif self.accept(OFF):
- spec._add_variant(self.variant(), False)
+ spec._add_variant(self.variant(),False)
elif self.accept(PCT):
spec._set_compiler(self.compiler())
@@ -1805,18 +1838,23 @@ class SpecParser(spack.parse.Parser):
spec._add_version(version)
added_version = True
+
elif self.accept(ON):
- spec._add_variant(self.variant(), True)
+ self.expect(ID)
+ self.check_identifier()
+ name = self.token.value
+ if self.accept(EQ):
+ self.expect(ID)
+ spec._add_flag(name,self.token.value)
+ else:
+ spec._add_variant(self.variant(name),True)
elif self.accept(OFF):
- spec._add_variant(self.variant(), False)
+ spec._add_variant(self.variant(),False)
elif self.accept(PCT):
spec._set_compiler(self.compiler())
- elif self.accept(EQ):
- spec._set_architecture(self.architecture())
-
else:
break
@@ -1827,13 +1865,17 @@ class SpecParser(spack.parse.Parser):
return spec
- def variant(self):
- self.expect(ID)
- self.check_identifier()
- return self.token.value
-
+ def variant(self,name=None):
+ #TODO: Make generalized variants possible
+ if name:
+ return name
+ else:
+ self.expect(ID)
+ self.check_identifier()
+ return self.token.value
def architecture(self):
+ #TODO: Make this work properly as a subcase of variant (includes adding names to grammar)
self.expect(ID)
return self.token.value
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index b3a77d076a..a651e29718 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -38,7 +38,7 @@ class ConcretizeTest(MockPackagesTest):
for name in abstract.variants:
avariant = abstract.variants[name]
cvariant = concrete.variants[name]
- self.assertEqual(avariant.enabled, cvariant.enabled)
+ self.assertEqual(avariant.value, cvariant.value)
for name in abstract.package.variants:
self.assertTrue(name in concrete.variants)
diff --git a/lib/spack/spack/test/multimethod.py b/lib/spack/spack/test/multimethod.py
index cd5d9e625e..ead3010512 100644
--- a/lib/spack/spack/test/multimethod.py
+++ b/lib/spack/spack/test/multimethod.py
@@ -92,19 +92,19 @@ class MultiMethodTest(MockPackagesTest):
def test_architecture_match(self):
- pkg = spack.db.get('multimethod=x86_64')
+ pkg = spack.db.get('multimethod+arch=x86_64')
self.assertEqual(pkg.different_by_architecture(), 'x86_64')
- pkg = spack.db.get('multimethod=ppc64')
+ pkg = spack.db.get('multimethod+arch=ppc64')
self.assertEqual(pkg.different_by_architecture(), 'ppc64')
- pkg = spack.db.get('multimethod=ppc32')
+ pkg = spack.db.get('multimethod+arch=ppc32')
self.assertEqual(pkg.different_by_architecture(), 'ppc32')
- pkg = spack.db.get('multimethod=arm64')
+ pkg = spack.db.get('multimethod+arch=arm64')
self.assertEqual(pkg.different_by_architecture(), 'arm64')
- pkg = spack.db.get('multimethod=macos')
+ pkg = spack.db.get('multimethod+arch=macos')
self.assertRaises(NoSuchMethodError, pkg.different_by_architecture)
diff --git a/lib/spack/spack/test/spec_dag.py b/lib/spack/spack/test/spec_dag.py
index 549f829d3e..9d6e7bd2a4 100644
--- a/lib/spack/spack/test/spec_dag.py
+++ b/lib/spack/spack/test/spec_dag.py
@@ -241,8 +241,8 @@ class SpecDagTest(MockPackagesTest):
def test_unsatisfiable_architecture(self):
- set_pkg_dep('mpileaks', 'mpich=bgqos_0')
- spec = Spec('mpileaks ^mpich=sles_10_ppc64 ^callpath ^dyninst ^libelf ^libdwarf')
+ set_pkg_dep('mpileaks', 'mpich+arch=bgqos_0')
+ spec = Spec('mpileaks ^mpich+arch=sles_10_ppc64 ^callpath ^dyninst ^libelf ^libdwarf')
self.assertRaises(spack.spec.UnsatisfiableArchitectureSpecError, spec.normalize)
@@ -426,6 +426,7 @@ class SpecDagTest(MockPackagesTest):
orig.concretize()
copy = orig.copy()
+ print orig
self.check_links(copy)
self.assertEqual(orig, copy)
diff --git a/lib/spack/spack/test/spec_semantics.py b/lib/spack/spack/test/spec_semantics.py
index 6666dbbb52..5b2cebddef 100644
--- a/lib/spack/spack/test/spec_semantics.py
+++ b/lib/spack/spack/test/spec_semantics.py
@@ -111,11 +111,11 @@ class SpecSematicsTest(MockPackagesTest):
def test_satisfies_architecture(self):
- self.check_satisfies('foo=chaos_5_x86_64_ib', '=chaos_5_x86_64_ib')
- self.check_satisfies('foo=bgqos_0', '=bgqos_0')
+ self.check_satisfies('foo+arch=chaos_5_x86_64_ib', '+arch=chaos_5_x86_64_ib')
+ self.check_satisfies('foo+arch=bgqos_0', '+arch=bgqos_0')
- self.check_unsatisfiable('foo=bgqos_0', '=chaos_5_x86_64_ib')
- self.check_unsatisfiable('foo=chaos_5_x86_64_ib', '=bgqos_0')
+ self.check_unsatisfiable('foo+arch=bgqos_0', '+arch=chaos_5_x86_64_ib')
+ self.check_unsatisfiable('foo+arch=chaos_5_x86_64_ib', '+arch=bgqos_0')
def test_satisfies_dependencies(self):
@@ -267,13 +267,13 @@ class SpecSematicsTest(MockPackagesTest):
def test_constrain_arch(self):
- self.check_constrain('libelf=bgqos_0', 'libelf=bgqos_0', 'libelf=bgqos_0')
- self.check_constrain('libelf=bgqos_0', 'libelf', 'libelf=bgqos_0')
+ self.check_constrain('libelf+arch=bgqos_0', 'libelf+arch=bgqos_0', 'libelf+arch=bgqos_0')
+ self.check_constrain('libelf+arch=bgqos_0', 'libelf', 'libelf+arch=bgqos_0')
def test_constrain_compiler(self):
- self.check_constrain('libelf=bgqos_0', 'libelf=bgqos_0', 'libelf=bgqos_0')
- self.check_constrain('libelf=bgqos_0', 'libelf', 'libelf=bgqos_0')
+ self.check_constrain('libelf+arch=bgqos_0', 'libelf+arch=bgqos_0', 'libelf+arch=bgqos_0')
+ self.check_constrain('libelf+arch=bgqos_0', 'libelf', 'libelf+arch=bgqos_0')
def test_invalid_constraint(self):
@@ -283,7 +283,7 @@ class SpecSematicsTest(MockPackagesTest):
self.check_invalid_constraint('libelf+debug', 'libelf~debug')
self.check_invalid_constraint('libelf+debug~foo', 'libelf+debug+foo')
- self.check_invalid_constraint('libelf=bgqos_0', 'libelf=x86_54')
+ self.check_invalid_constraint('libelf+arch=bgqos_0', 'libelf+arch=x86_54')
def test_constrain_changed(self):
@@ -293,7 +293,7 @@ class SpecSematicsTest(MockPackagesTest):
self.check_constrain_changed('libelf%gcc', '%gcc@4.5')
self.check_constrain_changed('libelf', '+debug')
self.check_constrain_changed('libelf', '~debug')
- self.check_constrain_changed('libelf', '=bgqos_0')
+ self.check_constrain_changed('libelf', '+arch=bgqos_0')
def test_constrain_not_changed(self):
@@ -304,7 +304,7 @@ class SpecSematicsTest(MockPackagesTest):
self.check_constrain_not_changed('libelf%gcc@4.5', '%gcc@4.5')
self.check_constrain_not_changed('libelf+debug', '+debug')
self.check_constrain_not_changed('libelf~debug', '~debug')
- self.check_constrain_not_changed('libelf=bgqos_0', '=bgqos_0')
+ self.check_constrain_not_changed('libelf+arch=bgqos_0', '+arch=bgqos_0')
self.check_constrain_not_changed('libelf^foo', 'libelf^foo')
self.check_constrain_not_changed('libelf^foo^bar', 'libelf^foo^bar')
@@ -316,7 +316,7 @@ class SpecSematicsTest(MockPackagesTest):
self.check_constrain_changed('libelf^foo%gcc', 'libelf^foo%gcc@4.5')
self.check_constrain_changed('libelf^foo', 'libelf^foo+debug')
self.check_constrain_changed('libelf^foo', 'libelf^foo~debug')
- self.check_constrain_changed('libelf^foo', 'libelf^foo=bgqos_0')
+ self.check_constrain_changed('libelf^foo', 'libelf^foo+arch=bgqos_0')
def test_constrain_dependency_not_changed(self):
@@ -326,5 +326,5 @@ class SpecSematicsTest(MockPackagesTest):
self.check_constrain_not_changed('libelf^foo%gcc@4.5', 'libelf^foo%gcc@4.5')
self.check_constrain_not_changed('libelf^foo+debug', 'libelf^foo+debug')
self.check_constrain_not_changed('libelf^foo~debug', 'libelf^foo~debug')
- self.check_constrain_not_changed('libelf^foo=bgqos_0', 'libelf^foo=bgqos_0')
+ self.check_constrain_not_changed('libelf^foo+arch=bgqos_0', 'libelf^foo+arch=bgqos_0')
diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py
index 404f38906e..4ad4d99d97 100644
--- a/lib/spack/spack/test/spec_syntax.py
+++ b/lib/spack/spack/test/spec_syntax.py
@@ -70,6 +70,7 @@ class SpecSyntaxTest(unittest.TestCase):
spec = expected
output = spack.spec.parse(spec)
parsed = (" ".join(str(spec) for spec in output))
+ print output, parsed
self.assertEqual(expected, parsed)
diff --git a/lib/spack/spack/variant.py b/lib/spack/spack/variant.py
index 3d3e2b0f6d..c572560206 100644
--- a/lib/spack/spack/variant.py
+++ b/lib/spack/spack/variant.py
@@ -32,5 +32,5 @@ currently variants are just flags.
class Variant(object):
"""Represents a variant on a build. Can be either on or off."""
def __init__(self, default, description):
- self.default = bool(default)
+ self.default = default
self.description = str(description)
diff --git a/var/spack/mock_packages/multimethod/package.py b/var/spack/mock_packages/multimethod/package.py
index 75b1606ffc..dc8dfc9cfb 100644
--- a/var/spack/mock_packages/multimethod/package.py
+++ b/var/spack/mock_packages/multimethod/package.py
@@ -103,19 +103,19 @@ class Multimethod(Package):
#
# Make sure we can switch methods on different architectures
#
- @when('=x86_64')
+ @when('+arch=x86_64')
def different_by_architecture(self):
return 'x86_64'
- @when('=ppc64')
+ @when('+arch=ppc64')
def different_by_architecture(self):
return 'ppc64'
- @when('=ppc32')
+ @when('+arch=ppc32')
def different_by_architecture(self):
return 'ppc32'
- @when('=arm64')
+ @when('+arch=arm64')
def different_by_architecture(self):
return 'arm64'