diff options
-rw-r--r-- | lib/spack/spack/platforms/cray.py | 109 |
1 files changed, 67 insertions, 42 deletions
diff --git a/lib/spack/spack/platforms/cray.py b/lib/spack/spack/platforms/cray.py index 0059b49ff1..9138ad7afe 100644 --- a/lib/spack/spack/platforms/cray.py +++ b/lib/spack/spack/platforms/cray.py @@ -8,37 +8,21 @@ from spack.operating_systems.linux_distro import LinuxDistro from spack.operating_systems.cnl import Cnl from llnl.util.filesystem import join_path -# Craype- module prefixes that are not valid CPU targets. -NON_TARGETS = ('hugepages', 'network', 'target', 'accel', 'xtpe') - - -def _target_from_clean_env(name): - '''Return the default back_end target as loaded in a clean login session. - - A bash subshell is launched with a wiped environment and the list of loaded - modules is parsed for the first acceptable CrayPE target. - ''' - # Based on the incantation: - # echo "$(env - USER=$USER /bin/bash -l -c 'module list -lt')" - targets = [] - if name != 'front_end': - env = which('env') - env.add_default_arg('-') - # CAUTION - $USER is generally needed to initialize the environment. - # There may be other variables needed for general success. - output = env('USER=%s' % os.environ['USER'], - '/bin/bash', '--noprofile', '--norc', '-c', - '. /etc/profile; module list -lt', - output=str, error=str) - default_modules = [i for i in output.splitlines() - if len(i.split()) == 1] - tty.debug("Found default modules:", - *[" " + mod for mod in default_modules]) - pattern = 'craype-(?!{0})(\S*)'.format('|'.join(NON_TARGETS)) - for mod in default_modules: - if 'craype-' in mod: - targets.extend(re.findall(pattern, mod)) - return targets[0] if targets else None + +def _get_modules_in_modulecmd_output(output): + '''Return list of valid modules parsed from modulecmd output string.''' + return [i for i in output.splitlines() + if len(i.split()) == 1] + + +def _fill_craype_targets_from_modules(targets, modules): + '''Extend CrayPE CPU targets list with those found in list of modules.''' + # Craype- module prefixes that are not valid CPU targets. + non_targets = ('hugepages', 'network', 'target', 'accel', 'xtpe') + pattern = r'craype-(?!{0})(\S*)'.format('|'.join(non_targets)) + for mod in modules: + if 'craype-' in mod: + targets.extend(re.findall(pattern, mod)) class Cray(Platform): @@ -56,7 +40,12 @@ class Cray(Platform): ''' super(Cray, self).__init__('cray') - # Get targets from config or make best guess from environment: + # Make all craype targets available. + for target in self._avail_targets(): + name = target.replace('-', '_') + self.add_target(name, Target(name, 'craype-%s' % target)) + + # Get aliased targets from config or best guess from environment: conf = spack.config.get_config('targets') for name in ('front_end', 'back_end'): _target = getattr(self, name, None) @@ -64,18 +53,16 @@ class Cray(Platform): _target = os.environ.get('SPACK_' + name.upper()) if _target is None: _target = conf.get(name) - if _target is None: - _target = _target_from_clean_env(name) - setattr(self, name, _target) - + if _target is None and name == 'back_end': + _target = self._default_target_from_env() if _target is not None: - self.add_target(name, Target(_target, 'craype-' + _target)) - self.add_target(_target, Target(_target, 'craype-' + _target)) + safe_name = _target.replace('-', '_') + setattr(self, name, safe_name) + self.add_target(name, self.targets[safe_name]) if self.back_end is not None: self.default = self.back_end - self.add_target( - 'default', Target(self.default, 'craype-' + self.default)) + self.add_target('default', self.targets[self.back_end]) else: raise NoPlatformError() @@ -90,7 +77,7 @@ class Cray(Platform): self.add_operating_system(self.front_os, front_distro) @classmethod - def setup_platform_environment(self, pkg, env): + def setup_platform_environment(cls, pkg, env): """ Change the linker to default dynamic to be more similar to linux/standard linker behavior """ @@ -101,5 +88,43 @@ class Cray(Platform): env.prepend_path('SPACK_ENV_PATH', cray_wrapper_names) @classmethod - def detect(self): + def detect(cls): return os.environ.get('CRAYPE_VERSION') is not None + + def _default_target_from_env(self): + '''Set and return the default CrayPE target loaded in a clean login + session. + + A bash subshell is launched with a wiped environment and the list of + loaded modules is parsed for the first acceptable CrayPE target. + ''' + # Based on the incantation: + # echo "$(env - USER=$USER /bin/bash -l -c 'module list -lt')" + if getattr(self, 'default', None) is None: + env = which('env') + env.add_default_arg('-') + # CAUTION - $USER is generally needed in the sub-environment. + # There may be other variables needed for general success. + output = env('USER=%s' % os.environ['USER'], + 'HOME=%s' % os.environ['HOME'], + '/bin/bash', '--noprofile', '--norc', '-c', + '. /etc/profile; module list -lt', + output=str, error=str) + self._defmods = _get_modules_in_modulecmd_output(output) + targets = [] + _fill_craype_targets_from_modules(targets, self._defmods) + self.default = targets[0] if targets else None + tty.debug("Found default modules:", + *[" %s" % mod for mod in self._defmods]) + return self.default + + def _avail_targets(self): + '''Return a list of available CrayPE CPU targets.''' + if getattr(self, '_craype_targets', None) is None: + module = which('modulecmd', required=True) + module.add_default_arg('python') + output = module('avail', '-t', 'craype-', output=str, error=str) + craype_modules = _get_modules_in_modulecmd_output(output) + self._craype_targets = targets = [] + _fill_craype_targets_from_modules(targets, craype_modules) + return self._craype_targets |