Changed architecture class and added class Target
This commit is contained in:
parent
38508c5a3f
commit
7ab921ff02
1 changed files with 85 additions and 56 deletions
|
@ -23,11 +23,16 @@
|
|||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
##############################################################################
|
||||
import os
|
||||
import imp
|
||||
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
|
||||
from spack.util.naming import mod_to_class
|
||||
import spack.error as serr
|
||||
from spack.version import Version
|
||||
from external import yaml
|
||||
|
@ -42,41 +47,55 @@ def __init__(self):
|
|||
super(NoSysTypeError, self).__init__("Could not determine sys_type for this machine.")
|
||||
|
||||
|
||||
class Architecture(object):
|
||||
""" Architecture class that contains a dictionary of architecture name and compiler search strategy methods.
|
||||
The idea is to create an object that Spack can interact with and know how to search for the compiler
|
||||
If it is on a Cray architecture it should look in modules. If it is anything else search $PATH.
|
||||
"""
|
||||
class Target(object):
|
||||
""" This is the processor type e.g. cray-ivybridge """
|
||||
# Front end or back end target. Target needs to know which one this is
|
||||
# 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):
|
||||
names = []
|
||||
names.append(front)
|
||||
names.append(back)
|
||||
d = {}
|
||||
for n in names:
|
||||
if n:
|
||||
if 'cray' in n.lower():
|
||||
d[n] = "MODULES"
|
||||
elif 'linux' in n.lower():
|
||||
d[n] = "PATH"
|
||||
def __init__(self,name, module_name=None):
|
||||
self.name = name # case of cray "ivybridge but if it's x86_64
|
||||
self.module_name = module_name # craype-ivybridge
|
||||
|
||||
def compiler_strategy(self):
|
||||
if self.module_name: # If there is a module_name given then use MODULES
|
||||
return "MODULES"
|
||||
else:
|
||||
d[n] = 'No Strategy'
|
||||
return d
|
||||
return "PATH"
|
||||
|
||||
def __init__(self, front=None, back=None):
|
||||
""" Constructor for the architecture class. It will create a list from the given arguments and iterate
|
||||
through that list. It will then create a dictionary of {arch_name : strategy}
|
||||
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
|
||||
class Architecture(object):
|
||||
""" Abstract class that each type of Architecture will subclass. Will return a instance of it once it
|
||||
is returned
|
||||
"""
|
||||
self.front = front
|
||||
self.back = back
|
||||
self.arch_dict = self.add_compiler_strategy(front, back)
|
||||
|
||||
priority = None # Subclass needs to set this number. This controls order in which arch is detected.
|
||||
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():
|
||||
|
@ -84,9 +103,9 @@ def get_sys_type_from_spack_globals():
|
|||
if not hasattr(spack, "sys_type"):
|
||||
return None
|
||||
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:
|
||||
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
|
||||
|
@ -102,15 +121,19 @@ def get_mac_sys_type():
|
|||
mac_ver = py_platform.mac_ver()[0]
|
||||
if not mac_ver:
|
||||
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():
|
||||
""" Returns a sys_type from the uname argument
|
||||
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():
|
||||
""" 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
|
||||
|
||||
|
||||
@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
|
||||
def sys_type():
|
||||
"""Priority of gathering sys-type.
|
||||
|
@ -143,22 +184,10 @@ def sys_type():
|
|||
arch name
|
||||
"""
|
||||
# Try to create an architecture object using the config file FIRST
|
||||
functions = [get_sys_type_from_config_file,
|
||||
get_sys_type_from_uname,
|
||||
get_sys_type_from_spack_globals,
|
||||
get_mac_sys_type]
|
||||
architecture_list = all_architectures()
|
||||
architecture_list.sort(key = lambda a: a.priority)
|
||||
|
||||
sys_type = None
|
||||
for func in functions:
|
||||
sys_type = func()
|
||||
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
|
||||
for arch in architecture_list:
|
||||
if arch.detect():
|
||||
return arch()
|
||||
|
||||
|
|
Loading…
Reference in a new issue