summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorGregory Becker <becker33@llnl.gov>2016-05-23 16:57:54 -0700
committerGregory Becker <becker33@llnl.gov>2016-05-23 16:57:54 -0700
commitd438ea088032429722f3945d5f6567f090ed1e9e (patch)
treeeb86a4970f96efcb42784415a0312b1728687544 /lib
parent6c352132d0dd2c0f05270fa7888d47ca37547674 (diff)
parentd7612e7aaace3b0fa483f17840e20cde5b28f430 (diff)
downloadspack-d438ea088032429722f3945d5f6567f090ed1e9e.tar.gz
spack-d438ea088032429722f3945d5f6567f090ed1e9e.tar.bz2
spack-d438ea088032429722f3945d5f6567f090ed1e9e.tar.xz
spack-d438ea088032429722f3945d5f6567f090ed1e9e.zip
'Ugly merge because I mishandled git
Merge branch 'save' into features/newarch
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/architecture.py78
-rw-r--r--lib/spack/spack/concretize.py23
-rw-r--r--lib/spack/spack/spec.py81
-rw-r--r--lib/spack/spack/test/architecture.py2
-rw-r--r--lib/spack/spack/test/concretize.py4
-rw-r--r--lib/spack/spack/test/spec_semantics.py14
-rw-r--r--lib/spack/spack/test/spec_syntax.py3
7 files changed, 162 insertions, 43 deletions
diff --git a/lib/spack/spack/architecture.py b/lib/spack/spack/architecture.py
index 45b4cc228d..05dc969ebe 100644
--- a/lib/spack/spack/architecture.py
+++ b/lib/spack/spack/architecture.py
@@ -157,12 +157,25 @@ class Platform(object):
self.operating_sys = {}
self.name = name
+ def to_dict(self):
+ n = {}
+ n['targets'] = dict((name, target.to_dict()) for (name, target) in self.targets.items())
+ n['operating_systems'] = dict((name, os.to_dict()) for (name, os) in self.operating_sys.items())
+ n['priority'] = self.priority
+ n['default_front_end_target'] = self.front_end
+ n['default_back_end_target'] = self.back_end
+ n['default_target'] = self.default
+ n['default_front_end_os'] = self.front_os
+ n['default_back_end_os'] = self.back_os
+ n['default_os'] = self.default_os
+ return {self.name: n}
+
def add_target(self, name, target):
"""Used by the platform specific subclass to list available targets.
Raises an error if the platform specifies a name
that is reserved by spack as an alias.
"""
- if name in ['front_end', 'fe', 'back_end', 'be', 'default']:
+ if name in ['frontend', 'fe', 'backend', 'be', 'default_target']:
raise ValueError(
"%s is a spack reserved alias "
"and cannot be the name of a target" % name)
@@ -187,6 +200,10 @@ class Platform(object):
""" Add the operating_system class object into the
platform.operating_sys dictionary
"""
+ if name in ['frontend', 'fe', 'backend', 'be', 'default_os']:
+ raise ValueError(
+ "%s is a spack reserved alias "
+ "and cannot be the name of an OS" % name)
self.operating_sys[name] = os_class
def operating_system(self, name):
@@ -336,15 +353,18 @@ class OperatingSystem(object):
class Arch(object):
"Architecture is now a class to help with setting attributes"
- def __init__(self, platform_os=None, target=None):
- self.platform = sys_type()
- if platform_os:
- platform_os = self.platform.operating_system(platform_os)
+ def __init__(self, platform=None, platform_os=None, target=None):
+ self.platform = platform
+ if platform and platform_os:
+ platform_os = self.platform.operating_system(platform_os)
self.platform_os = platform_os
- if target:
+ if platform and target:
target = self.platform.target(target)
self.target = target
+ # Hooks for parser to use when platform is set after target or os
+ self.target_string = None
+ self.os_string = None
@property
def concrete(self):
@@ -354,16 +374,19 @@ class Arch(object):
def __str__(self):
- if self.platform.name == 'darwin':
- os_name = self.platform_os.name
+ if self.platform or self.platform_os or self.target:
+ if self.platform.name == 'darwin':
+ os_name = self.platform_os.name
+ else:
+ os_name = str(self.platform_os)
+
+ return (str(self.platform) +"-"+
+ os_name + "-" + str(self.target))
else:
- os_name = str(self.platform_os)
-
- return (str(self.platform) +"-"+
- os_name + "-" + str(self.target))
+ return ''
def _cmp_key(self):
- platform = self.platform.name
+ platform = self.platform.name if isinstance(self.platform, Platform) else self.platform
os = self.platform_os.name if isinstance(self.platform_os, OperatingSystem) else self.platform_os
target = self.target.name if isinstance(self.target, Target) else self.target
return (platform, os, target)
@@ -374,7 +397,7 @@ class Arch(object):
platform_os = self.platform_os
target = self.target
- d['platform'] = self.platform.name
+ d['platform'] = self.platform.to_dict() if self.platform else None
d['platform_os'] = self.platform_os.to_dict() if self.platform_os else None
d['target'] = self.target.to_dict() if self.target else None
@@ -402,6 +425,27 @@ def _operating_system_from_dict(os_dict):
operating_system.version = os_dict['version']
return operating_system
+def _platform_from_dict(platform_dict):
+ """ Constructs a platform from a dictionary. """
+ platform = Platform.__new__(Platform)
+ name, p_dict = platform_dict.items()[0]
+ platform.name = name
+ platform.targets = {}
+ for name, t_dict in p_dict['targets'].items():
+ platform.add_target(name, _target_from_dict(t_dict))
+ platform.operating_sys = {}
+ for name, o_dict in p_dict['operating_systems'].items():
+ platform.add_operating_system(name, _operating_system_from_dict(o_dict))
+ platform.priority = p_dict['priority']
+ platform.front_end = p_dict['default_front_end_target']
+ platform.back_end = p_dict['default_back_end_target']
+ platform.default = p_dict['default_target']
+ platform.front_os = p_dict['default_front_end_os']
+ platform.back_os = p_dict['default_back_end_os']
+ platform.default_os = p_dict['default_os']
+
+ return platform
+
def arch_from_dict(d):
""" Uses _platform_from_dict, _operating_system_from_dict, _target_from_dict
helper methods to recreate the arch tuple from the dictionary read from
@@ -411,14 +455,20 @@ def arch_from_dict(d):
if d is None:
return None
+ platform_dict = d['platform']
os_dict = d['platform_os']
target_dict = d['target']
+ platform = _platform_from_dict(platform_dict) if platform_dict else None
target = _target_from_dict(target_dict) if os_dict else None
platform_os = _operating_system_from_dict(os_dict) if os_dict else None
+ arch.platform = platform
arch.target = target
arch.platform_os = platform_os
+ arch.os_string = None
+ arch.target_string = None
+
return arch
@memoized
diff --git a/lib/spack/spack/concretize.py b/lib/spack/spack/concretize.py
index 1c451296c6..7ea8ea6928 100644
--- a/lib/spack/spack/concretize.py
+++ b/lib/spack/spack/concretize.py
@@ -198,7 +198,7 @@ class DefaultConcretizer(object):
spec.architecture.platform_os = spec.root.architecture.platform_os
else:
spec.architecture.platform_os = spec.architecture.platform.operating_system('default_os')
- return True #changed
+ return True #changed
def _concretize_target(self, spec):
platform = spec.architecture.platform
@@ -210,7 +210,19 @@ class DefaultConcretizer(object):
spec.architecture.target = spec.root.architecture.target
else:
spec.architecture.target = spec.architecture.platform.target('default_target')
- return True #changed
+ print spec.architecture, spec.architecture.platform, spec.architecture.platform_os, spec.architecture.target
+ return True #changed
+
+ def _concretize_platform(self, spec):
+ if spec.architecture.platform is not None and isinstance(
+ spec.architecture.platform, spack.architecture.Platform):
+ return False
+ if spec.root.architecture and spec.root.architecture.platform:
+ if isinstance(spec.root.architecture.platform,spack.architecture.Platform):
+ spec.architecture.platform = spec.root.architecture.platform
+ else:
+ spec.architecture.platform = spack.architecture.sys_type()
+ return True #changed?
def concretize_architecture(self, spec):
"""If the spec is empty provide the defaults of the platform. If the
@@ -227,10 +239,11 @@ class DefaultConcretizer(object):
# Set the architecture to all defaults
spec.architecture = spack.architecture.Arch()
return True
-
+
# Concretize the operating_system and target based of the spec
- ret = any((self._concretize_operating_system(spec),
- self._concretize_target(spec)))
+ ret = any((self._concretize_platform(spec),
+ self._concretize_operating_system(spec),
+ self._concretize_target(spec)))
return ret
diff --git a/lib/spack/spack/spec.py b/lib/spack/spack/spec.py
index f88475d1c8..d15598405f 100644
--- a/lib/spack/spack/spec.py
+++ b/lib/spack/spack/spec.py
@@ -99,6 +99,7 @@ import sys
import itertools
import hashlib
import base64
+import imp
from StringIO import StringIO
from operator import attrgetter
import yaml
@@ -107,6 +108,7 @@ from yaml.error import MarkedYAMLError
import llnl.util.tty as tty
from llnl.util.lang import *
from llnl.util.tty.color import *
+from llnl.util.filesystem import join_path
import spack
import spack.architecture
@@ -119,6 +121,7 @@ from spack.cmd.find import display_specs
from spack.version import *
from spack.util.string import *
from spack.util.prefix import Prefix
+from spack.util.naming import mod_to_class
from spack.virtual import ProviderIndex
from spack.build_environment import get_path_from_module, load_module
@@ -535,10 +538,24 @@ class Spec(object):
Known flags currently include "arch"
"""
valid_flags = FlagMap.valid_compiler_flags()
- if name == 'os' or name == 'operating_system':
- self._set_os(value)
+# if name == 'arch' or name == 'architecture':
+# platform, op_sys, target = value.split('-')
+# print platform, op_sys, target, '+++++++'
+# self._set_platform(platform)
+# self._set_os(op_sys)
+# self._set_target(target)
+ if name == 'platform':
+ self._set_platform(value)
+ elif name == 'os' or name == 'operating_system':
+ if self.architecture.platform:
+ self._set_os(value)
+ else:
+ self.architecture.os_string = value
elif name == 'target':
- self._set_target(value)
+ if self.architecture.platform:
+ self._set_target(value)
+ else:
+ self.architecture.target_string = value
elif name in valid_flags:
assert(self.compiler_flags is not None)
self.compiler_flags[name] = value.split()
@@ -551,6 +568,39 @@ class Spec(object):
"Spec for '%s' cannot have two compilers." % self.name)
self.compiler = compiler
+ def _set_platform(self, value):
+ """Called by the parser to set the architecture platform"""
+ if isinstance(value, basestring):
+ mod_path = spack.platform_path
+ mod_string = 'spack.platformss'
+ names = list_modules(mod_path)
+ if value in names:
+ # Create a platform object from the name
+ mod_name = mod_string + value
+ path = join_path(mod_path, value) + '.py'
+ mod = imp.load_source(mod_name, path)
+ class_name = mod_to_class(value)
+ if not hasattr(mod, class_name):
+ tty.die('No class %s defined in %s' % (class_name, mod_name))
+ cls = getattr(mod, class_name)
+ if not inspect.isclass(cls):
+ tty.die('%s.%s is not a class' % (mod_name, class_name))
+ platform = cls()
+ else:
+ tty.die("No platform class %s defined." % value)
+ else:
+ # The value is a platform
+ platform = value
+
+ self.architecture.platform = platform
+
+ # Set os and target if we previously got strings for them
+ if self.architecture.os_string:
+ self._set_os(self.architecture.os_string)
+ self.architecture.os_string = None
+ if self.architecture.target_string:
+ self._set_target(self.architecture.target_string)
+ self.architecture.target_string = None
def _set_os(self, value):
"""Called by the parser to set the architecture operating system"""
@@ -1016,6 +1066,7 @@ class Spec(object):
changed = True
spec.dependencies = DependencyMap()
replacement.dependencies = DependencyMap()
+ replacement.architecture = self.architecture
# TODO: could this and the stuff in _dup be cleaned up?
def feq(cfield, sfield):
@@ -1426,7 +1477,6 @@ class Spec(object):
other.variants[v])
# TODO: Check out the logic here
- print self.architecture, other.architecture, "^^^^^^^^^^^^^^^^^^^^^^^"
if self.architecture is not None and other.architecture is not None:
if self.architecture.platform is not None and other.architecture.platform is not None:
if self.architecture.platform != other.architecture.platform:
@@ -1831,8 +1881,7 @@ class Spec(object):
self.variants,
self.architecture,
self.compiler,
- self.compiler_flags,
- self.dag_hash())
+ self.compiler_flags)
def eq_node(self, other):
@@ -1946,7 +1995,7 @@ class Spec(object):
if self.variants:
write(fmt % str(self.variants), c)
elif c == '=':
- if self.architecture:
+ if self.architecture and str(self.architecture):
write(fmt % (' arch' + c + str(self.architecture)), c)
elif c == '#':
out.write('-' + fmt % (self.dag_hash(7)))
@@ -2004,7 +2053,7 @@ class Spec(object):
if self.variants:
write(fmt % str(self.variants), '+')
elif named_str == 'ARCHITECTURE':
- if self.architecture:
+ if self.architecture and str(self.architecture):
write(fmt % str(self.architecture), ' arch=')
elif named_str == 'SHA1':
if self.dependencies:
@@ -2054,13 +2103,13 @@ class Spec(object):
self.variants, other.variants)
#Target
- if self.target != other.target:
- return spack.pkgsort.target_compare(pkgname,
- self.target, other.target)
+ if self.architecture != other.architecture:
+ return spack.pkgsort.architecture_compare(pkgname,
+ self.architecture, other.architecture)
#Dependency is not configurable
- if self.dep_hash() != other.dep_hash():
- return -1 if self.dep_hash() < other.dep_hash() else 1
+ if self.dependencies != other.dependencies:
+ return -1 if self.dependencies < other.dependencies else 1
#Equal specs
return 0
@@ -2181,6 +2230,11 @@ class SpecParser(spack.parse.Parser):
raise SpecParseError(e)
+ # If the spec has an os or a target and no platform, give it the default platform
+ for spec in specs:
+ for s in spec.traverse():
+ if s.architecture.os_string or s.architecture.target_string:
+ s._set_platform(spack.architecture.sys_type())
return specs
@@ -2401,7 +2455,6 @@ class SpecError(spack.error.SpackError):
def __init__(self, message):
super(SpecError, self).__init__(message)
-
class SpecParseError(SpecError):
"""Wrapper for ParseError for when we're parsing specs."""
def __init__(self, parse_error):
diff --git a/lib/spack/spack/test/architecture.py b/lib/spack/spack/test/architecture.py
index 2927e468a0..f5b1068435 100644
--- a/lib/spack/spack/test/architecture.py
+++ b/lib/spack/spack/test/architecture.py
@@ -26,12 +26,14 @@ class ArchitectureTest(MockPackagesTest):
def test_dict_functions_for_architecture(self):
arch = Arch()
+ arch.platform = spack.architecture.sys_type()
arch.platform_os = arch.platform.operating_system('default_os')
arch.target = arch.platform.target('default_target')
d = arch.to_dict()
new_arch = spack.architecture.arch_from_dict(d)
+
self.assertEqual(arch, new_arch)
self.assertTrue( isinstance(arch, Arch) )
diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py
index 49281b9a0c..963481054e 100644
--- a/lib/spack/spack/test/concretize.py
+++ b/lib/spack/spack/test/concretize.py
@@ -55,8 +55,8 @@ class ConcretizeTest(MockPackagesTest):
if abstract.compiler and abstract.compiler.concrete:
self.assertEqual(abstract.compiler, concrete.compiler)
- if abstract.architecture and abstract.architecture.target.concrete:
- self.assertEqual(abstract.target, concrete.target)
+ if abstract.architecture and abstract.architecture.concrete:
+ self.assertEqual(abstract.architecture, concrete.architecture)
def check_concretize(self, abstract_spec):
diff --git a/lib/spack/spack/test/spec_semantics.py b/lib/spack/spack/test/spec_semantics.py
index 9bd32a3d10..45c89100d4 100644
--- a/lib/spack/spack/test/spec_semantics.py
+++ b/lib/spack/spack/test/spec_semantics.py
@@ -383,14 +383,14 @@ class SpecSematicsTest(MockPackagesTest):
def test_invalid_constraint(self):
-# self.check_invalid_constraint('libelf@0:2.0', 'libelf@2.1:3')
-# self.check_invalid_constraint('libelf@0:2.5%gcc@4.8:4.9', 'libelf@2.1:3%gcc@4.5:4.7')
+ self.check_invalid_constraint('libelf@0:2.0', 'libelf@2.1:3')
+ self.check_invalid_constraint('libelf@0:2.5%gcc@4.8:4.9', 'libelf@2.1:3%gcc@4.5:4.7')
-# self.check_invalid_constraint('libelf+debug', 'libelf~debug')
-# self.check_invalid_constraint('libelf+debug~foo', 'libelf+debug+foo')
-# self.check_invalid_constraint('libelf debug=2', 'libelf debug=1')
+ self.check_invalid_constraint('libelf+debug', 'libelf~debug')
+ self.check_invalid_constraint('libelf+debug~foo', 'libelf+debug+foo')
+ self.check_invalid_constraint('libelf debug=2', 'libelf debug=1')
-# self.check_invalid_constraint('libelf cppflags="-O3"', 'libelf cppflags="-O2"')
+ self.check_invalid_constraint('libelf cppflags="-O3"', 'libelf cppflags="-O2"')
platform = spack.architecture.sys_type()
if len(platform.operating_sys.keys()) > 1 or len(platform.targets.keys()) > 1:
os1 = platform.operating_sys.keys()[0]
@@ -439,9 +439,9 @@ 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')
+
platform = spack.architecture.sys_type()
default_target = platform.target('default_target').name
- print default_target
self.check_constrain_changed('libelf^foo', 'libelf^foo target='+default_target)
diff --git a/lib/spack/spack/test/spec_syntax.py b/lib/spack/spack/test/spec_syntax.py
index c4e4c9cdfe..4a534d7b5c 100644
--- a/lib/spack/spack/test/spec_syntax.py
+++ b/lib/spack/spack/test/spec_syntax.py
@@ -58,7 +58,7 @@ class SpecSyntaxTest(unittest.TestCase):
# ================================================================================
# Parse checks
# ================================================================================
- def check_parse(self, expected, spec=None):
+ def check_parse(self, expected, spec=None, remove_arch=True):
"""Assert that the provided spec is able to be parsed.
If this is called with one argument, it assumes that the string is
canonical (i.e., no spaces and ~ instead of - for variants) and that it
@@ -70,6 +70,7 @@ class SpecSyntaxTest(unittest.TestCase):
if spec is None:
spec = expected
output = spack.spec.parse(spec)
+
parsed = (" ".join(str(spec) for spec in output))
self.assertEqual(expected, parsed)