Changed architecture class and added class Target

This commit is contained in:
Mario Melara 2015-10-30 14:46:26 -07:00
parent 38508c5a3f
commit 7ab921ff02

View file

@ -23,11 +23,16 @@
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
############################################################################## ##############################################################################
import os import os
import imp
import platform as py_platform import platform as py_platform
import inspect
from llnl.util.lang import memoized from llnl.util.lang import memoized, list_modules
from llnl.util.filesystem import join_path
import llnl.util.tty as tty
import spack import spack
from spack.util.naming import mod_to_class
import spack.error as serr import spack.error as serr
from spack.version import Version from spack.version import Version
from external import yaml from external import yaml
@ -42,41 +47,55 @@ def __init__(self):
super(NoSysTypeError, self).__init__("Could not determine sys_type for this machine.") super(NoSysTypeError, self).__init__("Could not determine sys_type for this machine.")
class Architecture(object): class Target(object):
""" Architecture class that contains a dictionary of architecture name and compiler search strategy methods. """ This is the processor type e.g. cray-ivybridge """
The idea is to create an object that Spack can interact with and know how to search for the compiler # Front end or back end target. Target needs to know which one this is
If it is on a Cray architecture it should look in modules. If it is anything else search $PATH. # Should autodetect from the machine
""" # features of a target
# - a module name
# -a compiler finding strategy
# -a name
# architecture classes handling the aliasing for front-end, back-end and default
def add_compiler_strategy(self, front,back): def __init__(self,name, module_name=None):
names = [] self.name = name # case of cray "ivybridge but if it's x86_64
names.append(front) self.module_name = module_name # craype-ivybridge
names.append(back)
d = {} def compiler_strategy(self):
for n in names: if self.module_name: # If there is a module_name given then use MODULES
if n: return "MODULES"
if 'cray' in n.lower():
d[n] = "MODULES"
elif 'linux' in n.lower():
d[n] = "PATH"
else: else:
d[n] = 'No Strategy' return "PATH"
return d
def __init__(self, front=None, back=None): class Architecture(object):
""" Constructor for the architecture class. It will create a list from the given arguments and iterate """ Abstract class that each type of Architecture will subclass. Will return a instance of it once it
through that list. It will then create a dictionary of {arch_name : strategy} is returned
Takes in two parameters:
front = None defaults to None. Should be the front-end architecture of the machine
back = None defaults to None. Should be the back-end architecture of the machine
If no arguments are given it will return an empty dictionary
Uses the _add_compiler_strategy(front, back) to create the dictionary
""" """
self.front = front
self.back = back priority = None # Subclass needs to set this number. This controls order in which arch is detected.
self.arch_dict = self.add_compiler_strategy(front, back) front = None
back = None
default_front = None # The default front end target. On cray sandybridge
default_back = None # The default back end target. On cray ivybridge
def __init__(self, name):
self.targets = {}
self.name = name
def add_target(self, name, target):
self.targets[name] = target
@classmethod
def detect(self):
""" Subclass is responsible for implementing this method.
Returns True if the architecture detects if it is the current architecture
and False if it's not.
"""
raise NotImplementedError()
def __str__(self):
return self.name
def get_sys_type_from_spack_globals(): def get_sys_type_from_spack_globals():
@ -84,9 +103,9 @@ def get_sys_type_from_spack_globals():
if not hasattr(spack, "sys_type"): if not hasattr(spack, "sys_type"):
return None return None
elif hasattr(spack.sys_type, "__call__"): elif hasattr(spack.sys_type, "__call__"):
return Architecture(spack.sys_type()) #If in __init__.py there is a sys_type() then call that return spack.sys_type() #If in __init__.py there is a sys_type() then call that
else: else:
return Architecture(spack.sys_type) # Else use the attributed which defaults to None return spack.sys_type # Else use the attributed which defaults to None
# This is livermore dependent. Hard coded for livermore # This is livermore dependent. Hard coded for livermore
@ -102,15 +121,19 @@ def get_mac_sys_type():
mac_ver = py_platform.mac_ver()[0] mac_ver = py_platform.mac_ver()[0]
if not mac_ver: if not mac_ver:
return None return None
return Architecture("macosx_%s_%s" % (Version(mac_ver).up_to(2), py_platform.machine())) return "macosx_%s_%s" % (Version(mac_ver).up_to(2), py_platform.machine())
def get_sys_type_from_uname(): def get_sys_type_from_uname():
""" Returns a sys_type from the uname argument """ Returns a sys_type from the uname argument
Front-end config Front-end config
""" """
return Architecture(os.uname()[0]) try:
arch_proc = subprocess.Popen(['uname', '-i'], stdout = subprocess.PIPE)
arch, _ = arch_proc.communicate()
return arch.strip()
except:
return None
def get_sys_type_from_config_file(): def get_sys_type_from_config_file():
""" Should read in a sys_type from the config yaml file. This should be the first thing looked at since """ Should read in a sys_type from the config yaml file. This should be the first thing looked at since
@ -131,6 +154,24 @@ def get_sys_type_from_config_file():
return None return None
@memoized
def all_architectures():
modules = []
for name in list_modules(spack.arch_path):
mod_name = 'spack.architectures.' + name
path = join_path(spack.arch_path, name) + ".py"
mod = imp.load_source(mod_name, path)
class_name = mod_to_class(name)
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))
modules.append(cls)
return modules
@memoized @memoized
def sys_type(): def sys_type():
"""Priority of gathering sys-type. """Priority of gathering sys-type.
@ -143,22 +184,10 @@ def sys_type():
arch name arch name
""" """
# Try to create an architecture object using the config file FIRST # Try to create an architecture object using the config file FIRST
functions = [get_sys_type_from_config_file, architecture_list = all_architectures()
get_sys_type_from_uname, architecture_list.sort(key = lambda a: a.priority)
get_sys_type_from_spack_globals,
get_mac_sys_type]
sys_type = None for arch in architecture_list:
for func in functions: if arch.detect():
sys_type = func() return arch()
if sys_type:
break
if sys_type is None:
return Architecture("unknown_arch")
if not isinstance(sys_type, Architecture):
raise InvalidSysTypeError(sys_type)
return sys_type