lmod : added support for the creation of hierarchical lua module files (#1723)
Includes : - treatment of a generic hierarchy (i.e. lapack + mpi + compiler) - possibility to specify which compilers are to be considered Core - correct treatment of the 'family' directive - unit tests for most new features
This commit is contained in:
parent
efadc0e299
commit
ea446c0f0e
10 changed files with 560 additions and 149 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -12,6 +12,7 @@
|
||||||
/etc/spackconfig
|
/etc/spackconfig
|
||||||
/share/spack/dotkit
|
/share/spack/dotkit
|
||||||
/share/spack/modules
|
/share/spack/modules
|
||||||
|
/share/spack/lmod
|
||||||
/TAGS
|
/TAGS
|
||||||
/htmlcov
|
/htmlcov
|
||||||
.coverage
|
.coverage
|
||||||
|
|
|
@ -69,17 +69,17 @@ def get_cmd_function_name(name):
|
||||||
def get_module(name):
|
def get_module(name):
|
||||||
"""Imports the module for a particular command name and returns it."""
|
"""Imports the module for a particular command name and returns it."""
|
||||||
module_name = "%s.%s" % (__name__, name)
|
module_name = "%s.%s" % (__name__, name)
|
||||||
module = __import__(
|
module = __import__(module_name,
|
||||||
module_name, fromlist=[name, SETUP_PARSER, DESCRIPTION],
|
fromlist=[name, SETUP_PARSER, DESCRIPTION],
|
||||||
level=0)
|
level=0)
|
||||||
|
|
||||||
attr_setdefault(module, SETUP_PARSER, lambda *args: None) # null-op
|
attr_setdefault(module, SETUP_PARSER, lambda *args: None) # null-op
|
||||||
attr_setdefault(module, DESCRIPTION, "")
|
attr_setdefault(module, DESCRIPTION, "")
|
||||||
|
|
||||||
fn_name = get_cmd_function_name(name)
|
fn_name = get_cmd_function_name(name)
|
||||||
if not hasattr(module, fn_name):
|
if not hasattr(module, fn_name):
|
||||||
tty.die("Command module %s (%s) must define function '%s'."
|
tty.die("Command module %s (%s) must define function '%s'." %
|
||||||
% (module.__name__, module.__file__, fn_name))
|
(module.__name__, module.__file__, fn_name))
|
||||||
|
|
||||||
return module
|
return module
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,10 @@
|
||||||
import shutil
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
import llnl.util.filesystem as filesystem
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
import spack.cmd
|
import spack.cmd
|
||||||
import spack.cmd.common.arguments as arguments
|
import spack.cmd.common.arguments as arguments
|
||||||
import llnl.util.filesystem as filesystem
|
|
||||||
from spack.modules import module_types
|
from spack.modules import module_types
|
||||||
|
|
||||||
description = "Manipulate module files"
|
description = "Manipulate module files"
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
"""This package contains modules with hooks for various stages in the
|
"""This package contains modules with hooks for various stages in the
|
||||||
Spack install process. You can add modules here and they'll be
|
Spack install process. You can add modules here and they'll be
|
||||||
executaed by package at various times during the package lifecycle.
|
executed by package at various times during the package lifecycle.
|
||||||
|
|
||||||
Each hook is just a function that takes a package as a parameter.
|
Each hook is just a function that takes a package as a parameter.
|
||||||
Hooks are not executed in any particular order.
|
Hooks are not executed in any particular order.
|
||||||
|
@ -41,9 +41,10 @@
|
||||||
features.
|
features.
|
||||||
"""
|
"""
|
||||||
import imp
|
import imp
|
||||||
from llnl.util.lang import memoized, list_modules
|
|
||||||
from llnl.util.filesystem import join_path
|
|
||||||
import spack
|
import spack
|
||||||
|
from llnl.util.filesystem import join_path
|
||||||
|
from llnl.util.lang import memoized, list_modules
|
||||||
|
|
||||||
|
|
||||||
@memoized
|
@memoized
|
||||||
|
@ -70,12 +71,11 @@ def __call__(self, pkg):
|
||||||
if hasattr(hook, '__call__'):
|
if hasattr(hook, '__call__'):
|
||||||
hook(pkg)
|
hook(pkg)
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Define some functions that can be called to fire off hooks.
|
# Define some functions that can be called to fire off hooks.
|
||||||
#
|
#
|
||||||
pre_install = HookRunner('pre_install')
|
pre_install = HookRunner('pre_install')
|
||||||
post_install = HookRunner('post_install')
|
post_install = HookRunner('post_install')
|
||||||
|
|
||||||
pre_uninstall = HookRunner('pre_uninstall')
|
pre_uninstall = HookRunner('pre_uninstall')
|
||||||
post_uninstall = HookRunner('post_uninstall')
|
post_uninstall = HookRunner('post_uninstall')
|
||||||
|
|
35
lib/spack/spack/hooks/lmodmodule.py
Normal file
35
lib/spack/spack/hooks/lmodmodule.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
##############################################################################
|
||||||
|
# Copyright (c) 2013, Lawrence Livermore National Security, LLC.
|
||||||
|
# Produced at the Lawrence Livermore National Laboratory.
|
||||||
|
#
|
||||||
|
# This file is part of Spack.
|
||||||
|
# Written by Todd Gamblin, tgamblin@llnl.gov, All rights reserved.
|
||||||
|
# LLNL-CODE-647188
|
||||||
|
#
|
||||||
|
# For details, see https://scalability-llnl.github.io/spack
|
||||||
|
# Please also see the LICENSE file for our notice and the LGPL.
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License (as published by
|
||||||
|
# the Free Software Foundation) version 2.1 dated February 1999.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and
|
||||||
|
# conditions of the GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
##############################################################################
|
||||||
|
import spack.modules
|
||||||
|
|
||||||
|
|
||||||
|
def post_install(pkg):
|
||||||
|
dk = spack.modules.LmodModule(pkg.spec)
|
||||||
|
dk.write()
|
||||||
|
|
||||||
|
|
||||||
|
def post_uninstall(pkg):
|
||||||
|
dk = spack.modules.LmodModule(pkg.spec)
|
||||||
|
dk.remove()
|
|
@ -40,6 +40,7 @@
|
||||||
"""
|
"""
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
|
import itertools
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
|
@ -48,6 +49,7 @@
|
||||||
|
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
import spack
|
import spack
|
||||||
|
import spack.compilers # Needed by LmodModules
|
||||||
import spack.config
|
import spack.config
|
||||||
from llnl.util.filesystem import join_path, mkdirp
|
from llnl.util.filesystem import join_path, mkdirp
|
||||||
from spack.build_environment import parent_class_modules
|
from spack.build_environment import parent_class_modules
|
||||||
|
@ -56,7 +58,8 @@
|
||||||
|
|
||||||
__all__ = ['EnvModule', 'Dotkit', 'TclModule']
|
__all__ = ['EnvModule', 'Dotkit', 'TclModule']
|
||||||
|
|
||||||
# Registry of all types of modules. Entries created by EnvModule's metaclass
|
"""Registry of all types of modules. Entries created by EnvModule's
|
||||||
|
metaclass."""
|
||||||
module_types = {}
|
module_types = {}
|
||||||
|
|
||||||
CONFIGURATION = spack.config.get_config('modules')
|
CONFIGURATION = spack.config.get_config('modules')
|
||||||
|
@ -633,3 +636,237 @@ def module_specific_content(self, configuration):
|
||||||
raise SystemExit('Module generation aborted.')
|
raise SystemExit('Module generation aborted.')
|
||||||
line = line.format(**naming_tokens)
|
line = line.format(**naming_tokens)
|
||||||
yield line
|
yield line
|
||||||
|
|
||||||
|
# To construct an arbitrary hierarchy of module files:
|
||||||
|
# 1. Parse the configuration file and check that all the items in
|
||||||
|
# hierarchical_scheme are indeed virtual packages
|
||||||
|
# This needs to be done only once at start-up
|
||||||
|
# 2. Order the stack as `hierarchical_scheme + ['mpi, 'compiler']
|
||||||
|
# 3. Check which of the services are provided by the package
|
||||||
|
# -> may be more than one
|
||||||
|
# 4. Check which of the services are needed by the package
|
||||||
|
# -> this determines where to write the module file
|
||||||
|
# 5. For each combination of services in which we have at least one provider
|
||||||
|
# here add the appropriate conditional MODULEPATH modifications
|
||||||
|
|
||||||
|
|
||||||
|
class LmodModule(EnvModule):
|
||||||
|
name = 'lmod'
|
||||||
|
path = join_path(spack.share_path, "lmod")
|
||||||
|
|
||||||
|
environment_modifications_formats = {
|
||||||
|
PrependPath: 'prepend_path("{name}", "{value}")\n',
|
||||||
|
AppendPath: 'append_path("{name}", "{value}")\n',
|
||||||
|
RemovePath: 'remove_path("{name}", "{value}")\n',
|
||||||
|
SetEnv: 'setenv("{name}", "{value}")\n',
|
||||||
|
UnsetEnv: 'unsetenv("{name}")\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
autoload_format = ('if not isloaded("{module_file}") then\n'
|
||||||
|
' LmodMessage("Autoloading {module_file}")\n'
|
||||||
|
' load("{module_file}")\n'
|
||||||
|
'end\n\n')
|
||||||
|
|
||||||
|
prerequisite_format = 'prereq("{module_file}")\n'
|
||||||
|
|
||||||
|
family_format = 'family("{family}")\n'
|
||||||
|
|
||||||
|
path_part_with_hash = join_path('{token.name}', '{token.version}-{token.hash}') # NOQA: ignore=E501
|
||||||
|
path_part_without_hash = join_path('{token.name}', '{token.version}')
|
||||||
|
|
||||||
|
# TODO : Check that extra tokens specified in configuration file
|
||||||
|
# TODO : are actually virtual dependencies
|
||||||
|
configuration = CONFIGURATION.get('lmod', {})
|
||||||
|
hierarchy_tokens = configuration.get('hierarchical_scheme', [])
|
||||||
|
hierarchy_tokens = hierarchy_tokens + ['mpi', 'compiler']
|
||||||
|
|
||||||
|
def __init__(self, spec=None):
|
||||||
|
super(LmodModule, self).__init__(spec)
|
||||||
|
# Sets the root directory for this architecture
|
||||||
|
self.modules_root = join_path(LmodModule.path, self.spec.architecture)
|
||||||
|
# Retrieve core compilers
|
||||||
|
self.core_compilers = self.configuration.get('core_compilers', [])
|
||||||
|
# Keep track of the requirements that this package has in terms
|
||||||
|
# of virtual packages
|
||||||
|
# that participate in the hierarchical structure
|
||||||
|
self.requires = {'compiler': self.spec.compiler}
|
||||||
|
# For each virtual dependency in the hierarchy
|
||||||
|
for x in self.hierarchy_tokens:
|
||||||
|
if x in self.spec and not self.spec.package.provides(
|
||||||
|
x): # if I depend on it
|
||||||
|
self.requires[x] = self.spec[x] # record the actual provider
|
||||||
|
# Check what are the services I need (this will determine where the
|
||||||
|
# module file will be written)
|
||||||
|
self.substitutions = {}
|
||||||
|
self.substitutions.update(self.requires)
|
||||||
|
# TODO : complete substitutions
|
||||||
|
# Check what service I provide to others
|
||||||
|
self.provides = {}
|
||||||
|
# If it is in the list of supported compilers family -> compiler
|
||||||
|
if self.spec.name in spack.compilers.supported_compilers():
|
||||||
|
self.provides['compiler'] = spack.spec.CompilerSpec(str(self.spec))
|
||||||
|
# Special case for llvm
|
||||||
|
if self.spec.name == 'llvm':
|
||||||
|
self.provides['compiler'] = spack.spec.CompilerSpec(str(self.spec))
|
||||||
|
self.provides['compiler'].name = 'clang'
|
||||||
|
|
||||||
|
for x in self.hierarchy_tokens:
|
||||||
|
if self.spec.package.provides(x):
|
||||||
|
self.provides[x] = self.spec[x]
|
||||||
|
|
||||||
|
def _hierarchy_token_combinations(self):
|
||||||
|
"""
|
||||||
|
Yields all the relevant combinations that could appear in the hierarchy
|
||||||
|
"""
|
||||||
|
for ii in range(len(self.hierarchy_tokens) + 1):
|
||||||
|
for item in itertools.combinations(self.hierarchy_tokens, ii):
|
||||||
|
if 'compiler' in item:
|
||||||
|
yield item
|
||||||
|
|
||||||
|
def _hierarchy_to_be_provided(self):
|
||||||
|
"""
|
||||||
|
Filters a list of hierarchy tokens and yields only the one that we
|
||||||
|
need to provide
|
||||||
|
"""
|
||||||
|
for item in self._hierarchy_token_combinations():
|
||||||
|
if any(x in self.provides for x in item):
|
||||||
|
yield item
|
||||||
|
|
||||||
|
def token_to_path(self, name, value):
|
||||||
|
# If we are dealing with a core compiler, return 'Core'
|
||||||
|
if name == 'compiler' and str(value) in self.core_compilers:
|
||||||
|
return 'Core'
|
||||||
|
# CompilerSpec does not have an hash
|
||||||
|
if name == 'compiler':
|
||||||
|
return self.path_part_without_hash.format(token=value)
|
||||||
|
# For virtual providers add a small part of the hash
|
||||||
|
# to distinguish among different variants in a directory hierarchy
|
||||||
|
value.hash = value.dag_hash(length=6)
|
||||||
|
return self.path_part_with_hash.format(token=value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def file_name(self):
|
||||||
|
parts = [self.token_to_path(x, self.requires[x])
|
||||||
|
for x in self.hierarchy_tokens if x in self.requires]
|
||||||
|
hierarchy_name = join_path(*parts)
|
||||||
|
fullname = join_path(self.modules_root, hierarchy_name,
|
||||||
|
self.use_name + '.lua')
|
||||||
|
return fullname
|
||||||
|
|
||||||
|
@property
|
||||||
|
def use_name(self):
|
||||||
|
return self.token_to_path('', self.spec)
|
||||||
|
|
||||||
|
def modulepath_modifications(self):
|
||||||
|
# What is available is what we require plus what we provide
|
||||||
|
entry = ''
|
||||||
|
available = {}
|
||||||
|
available.update(self.requires)
|
||||||
|
available.update(self.provides)
|
||||||
|
available_parts = [self.token_to_path(x, available[x])
|
||||||
|
for x in self.hierarchy_tokens if x in available]
|
||||||
|
# Missing parts
|
||||||
|
missing = [x for x in self.hierarchy_tokens if x not in available]
|
||||||
|
# Direct path we provide on top of compilers
|
||||||
|
modulepath = join_path(self.modules_root, *available_parts)
|
||||||
|
env = EnvironmentModifications()
|
||||||
|
env.prepend_path('MODULEPATH', modulepath)
|
||||||
|
for line in self.process_environment_command(env):
|
||||||
|
entry += line
|
||||||
|
|
||||||
|
def local_variable(x):
|
||||||
|
lower, upper = x.lower(), x.upper()
|
||||||
|
fmt = 'local {lower}_name = os.getenv("LMOD_{upper}_NAME")\n'
|
||||||
|
fmt += 'local {lower}_version = os.getenv("LMOD_{upper}_VERSION")\n' # NOQA: ignore=501
|
||||||
|
return fmt.format(lower=lower, upper=upper)
|
||||||
|
|
||||||
|
def set_variables_for_service(env, x):
|
||||||
|
upper = x.upper()
|
||||||
|
s = self.provides[x]
|
||||||
|
name, version = os.path.split(self.token_to_path(x, s))
|
||||||
|
|
||||||
|
env.set('LMOD_{upper}_NAME'.format(upper=upper), name)
|
||||||
|
env.set('LMOD_{upper}_VERSION'.format(upper=upper), version)
|
||||||
|
|
||||||
|
def conditional_modulepath_modifications(item):
|
||||||
|
entry = 'if '
|
||||||
|
needed = []
|
||||||
|
for x in self.hierarchy_tokens:
|
||||||
|
if x in missing:
|
||||||
|
needed.append('{x}_name '.format(x=x))
|
||||||
|
entry += 'and '.join(needed) + 'then\n'
|
||||||
|
entry += ' local t = pathJoin("{root}"'.format(
|
||||||
|
root=self.modules_root)
|
||||||
|
for x in item:
|
||||||
|
if x in missing:
|
||||||
|
entry += ', {lower}_name, {lower}_version'.format(
|
||||||
|
lower=x.lower())
|
||||||
|
else:
|
||||||
|
entry += ', "{x}"'.format(
|
||||||
|
x=self.token_to_path(x, available[x]))
|
||||||
|
entry += ')\n'
|
||||||
|
entry += ' prepend_path("MODULEPATH", t)\n'
|
||||||
|
entry += 'end\n\n'
|
||||||
|
return entry
|
||||||
|
|
||||||
|
if 'compiler' not in self.provides:
|
||||||
|
# Retrieve variables
|
||||||
|
entry += '\n'
|
||||||
|
for x in missing:
|
||||||
|
entry += local_variable(x)
|
||||||
|
entry += '\n'
|
||||||
|
# Conditional modifications
|
||||||
|
conditionals = [x
|
||||||
|
for x in self._hierarchy_to_be_provided()
|
||||||
|
if any(t in missing for t in x)]
|
||||||
|
for item in conditionals:
|
||||||
|
entry += conditional_modulepath_modifications(item)
|
||||||
|
|
||||||
|
# Set environment variables for the services we provide
|
||||||
|
env = EnvironmentModifications()
|
||||||
|
for x in self.provides:
|
||||||
|
set_variables_for_service(env, x)
|
||||||
|
for line in self.process_environment_command(env):
|
||||||
|
entry += line
|
||||||
|
|
||||||
|
return entry
|
||||||
|
|
||||||
|
@property
|
||||||
|
def header(self):
|
||||||
|
timestamp = datetime.datetime.now()
|
||||||
|
# Header as in
|
||||||
|
# https://www.tacc.utexas.edu/research-development/tacc-projects/lmod/advanced-user-guide/more-about-writing-module-files
|
||||||
|
header = "-- -*- lua -*-\n"
|
||||||
|
header += '-- Module file created by spack (https://github.com/LLNL/spack) on %s\n' % timestamp # NOQA: ignore=E501
|
||||||
|
header += '--\n'
|
||||||
|
header += '-- %s\n' % self.spec.short_spec
|
||||||
|
header += '--\n'
|
||||||
|
|
||||||
|
# Short description -> whatis()
|
||||||
|
if self.short_description:
|
||||||
|
header += "whatis([[Name : {name}]])\n".format(name=self.spec.name)
|
||||||
|
header += "whatis([[Version : {version}]])\n".format(
|
||||||
|
version=self.spec.version)
|
||||||
|
|
||||||
|
# Long description -> help()
|
||||||
|
if self.long_description:
|
||||||
|
doc = re.sub(r'"', '\"', self.long_description)
|
||||||
|
header += "help([[{documentation}]])\n".format(documentation=doc)
|
||||||
|
|
||||||
|
# Certain things need to be done only if we provide a service
|
||||||
|
if self.provides:
|
||||||
|
# Add family directives
|
||||||
|
header += '\n'
|
||||||
|
for x in self.provides:
|
||||||
|
header += self.family_format.format(family=x)
|
||||||
|
header += '\n'
|
||||||
|
header += '-- MODULEPATH modifications\n'
|
||||||
|
header += '\n'
|
||||||
|
# Modify MODULEPATH
|
||||||
|
header += self.modulepath_modifications()
|
||||||
|
# Set environment variables for services we provide
|
||||||
|
header += '\n'
|
||||||
|
header += '-- END MODULEPATH modifications\n'
|
||||||
|
header += '\n'
|
||||||
|
|
||||||
|
return header
|
||||||
|
|
|
@ -139,7 +139,20 @@
|
||||||
'default': [],
|
'default': [],
|
||||||
'items': {
|
'items': {
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'enum': ['tcl', 'dotkit']}},
|
'enum': ['tcl', 'dotkit', 'lmod']}},
|
||||||
|
'lmod': {
|
||||||
|
'allOf': [
|
||||||
|
# Base configuration
|
||||||
|
{'$ref': '#/definitions/module_type_configuration'},
|
||||||
|
{
|
||||||
|
'core_compilers': {
|
||||||
|
'$ref': '#/definitions/array_of_strings'
|
||||||
|
},
|
||||||
|
'hierarchical_scheme': {
|
||||||
|
'$ref': '#/definitions/array_of_strings'
|
||||||
|
}
|
||||||
|
} # Specific lmod extensions
|
||||||
|
]},
|
||||||
'tcl': {
|
'tcl': {
|
||||||
'allOf': [
|
'allOf': [
|
||||||
# Base configuration
|
# Base configuration
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
These tests check the database is functioning properly,
|
These tests check the database is functioning properly,
|
||||||
both in memory and in its file
|
both in memory and in its file
|
||||||
"""
|
"""
|
||||||
import os.path
|
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
import os.path
|
||||||
|
|
||||||
import spack
|
import spack
|
||||||
from llnl.util.filesystem import join_path
|
from llnl.util.filesystem import join_path
|
||||||
|
@ -88,16 +88,16 @@ def test_010_all_install_sanity(self):
|
||||||
# query specs with multiple configurations
|
# query specs with multiple configurations
|
||||||
mpileaks_specs = [s for s in all_specs if s.satisfies('mpileaks')]
|
mpileaks_specs = [s for s in all_specs if s.satisfies('mpileaks')]
|
||||||
callpath_specs = [s for s in all_specs if s.satisfies('callpath')]
|
callpath_specs = [s for s in all_specs if s.satisfies('callpath')]
|
||||||
mpi_specs = [s for s in all_specs if s.satisfies('mpi')]
|
mpi_specs = [s for s in all_specs if s.satisfies('mpi')]
|
||||||
|
|
||||||
self.assertEqual(len(mpileaks_specs), 3)
|
self.assertEqual(len(mpileaks_specs), 3)
|
||||||
self.assertEqual(len(callpath_specs), 3)
|
self.assertEqual(len(callpath_specs), 3)
|
||||||
self.assertEqual(len(mpi_specs), 3)
|
self.assertEqual(len(mpi_specs), 3)
|
||||||
|
|
||||||
# query specs with single configurations
|
# query specs with single configurations
|
||||||
dyninst_specs = [s for s in all_specs if s.satisfies('dyninst')]
|
dyninst_specs = [s for s in all_specs if s.satisfies('dyninst')]
|
||||||
libdwarf_specs = [s for s in all_specs if s.satisfies('libdwarf')]
|
libdwarf_specs = [s for s in all_specs if s.satisfies('libdwarf')]
|
||||||
libelf_specs = [s for s in all_specs if s.satisfies('libelf')]
|
libelf_specs = [s for s in all_specs if s.satisfies('libelf')]
|
||||||
|
|
||||||
self.assertEqual(len(dyninst_specs), 1)
|
self.assertEqual(len(dyninst_specs), 1)
|
||||||
self.assertEqual(len(libdwarf_specs), 1)
|
self.assertEqual(len(libdwarf_specs), 1)
|
||||||
|
@ -163,16 +163,16 @@ def test_050_basic_query(self):
|
||||||
# query specs with multiple configurations
|
# query specs with multiple configurations
|
||||||
mpileaks_specs = self.installed_db.query('mpileaks')
|
mpileaks_specs = self.installed_db.query('mpileaks')
|
||||||
callpath_specs = self.installed_db.query('callpath')
|
callpath_specs = self.installed_db.query('callpath')
|
||||||
mpi_specs = self.installed_db.query('mpi')
|
mpi_specs = self.installed_db.query('mpi')
|
||||||
|
|
||||||
self.assertEqual(len(mpileaks_specs), 3)
|
self.assertEqual(len(mpileaks_specs), 3)
|
||||||
self.assertEqual(len(callpath_specs), 3)
|
self.assertEqual(len(callpath_specs), 3)
|
||||||
self.assertEqual(len(mpi_specs), 3)
|
self.assertEqual(len(mpi_specs), 3)
|
||||||
|
|
||||||
# query specs with single configurations
|
# query specs with single configurations
|
||||||
dyninst_specs = self.installed_db.query('dyninst')
|
dyninst_specs = self.installed_db.query('dyninst')
|
||||||
libdwarf_specs = self.installed_db.query('libdwarf')
|
libdwarf_specs = self.installed_db.query('libdwarf')
|
||||||
libelf_specs = self.installed_db.query('libelf')
|
libelf_specs = self.installed_db.query('libelf')
|
||||||
|
|
||||||
self.assertEqual(len(dyninst_specs), 1)
|
self.assertEqual(len(dyninst_specs), 1)
|
||||||
self.assertEqual(len(libdwarf_specs), 1)
|
self.assertEqual(len(libdwarf_specs), 1)
|
||||||
|
|
|
@ -49,105 +49,10 @@ def mock_open(filename, mode):
|
||||||
handle.close()
|
handle.close()
|
||||||
|
|
||||||
|
|
||||||
configuration_autoload_direct = {
|
# Spec strings that will be used throughout the tests
|
||||||
'enable': ['tcl'],
|
mpich_spec_string = 'mpich@3.0.4'
|
||||||
'tcl': {
|
mpileaks_spec_string = 'mpileaks'
|
||||||
'all': {
|
libdwarf_spec_string = 'libdwarf arch=x64-linux'
|
||||||
'autoload': 'direct'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration_autoload_all = {
|
|
||||||
'enable': ['tcl'],
|
|
||||||
'tcl': {
|
|
||||||
'all': {
|
|
||||||
'autoload': 'all'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration_prerequisites_direct = {
|
|
||||||
'enable': ['tcl'],
|
|
||||||
'tcl': {
|
|
||||||
'all': {
|
|
||||||
'prerequisites': 'direct'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration_prerequisites_all = {
|
|
||||||
'enable': ['tcl'],
|
|
||||||
'tcl': {
|
|
||||||
'all': {
|
|
||||||
'prerequisites': 'all'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration_alter_environment = {
|
|
||||||
'enable': ['tcl'],
|
|
||||||
'tcl': {
|
|
||||||
'all': {
|
|
||||||
'filter': {'environment_blacklist': ['CMAKE_PREFIX_PATH']},
|
|
||||||
'environment': {
|
|
||||||
'set': {'{name}_ROOT': '{prefix}'}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'platform=test target=x86_64': {
|
|
||||||
'environment': {
|
|
||||||
'set': {'FOO': 'foo'},
|
|
||||||
'unset': ['BAR']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'platform=test target=x86_32': {
|
|
||||||
'load': ['foo/bar']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration_blacklist = {
|
|
||||||
'enable': ['tcl'],
|
|
||||||
'tcl': {
|
|
||||||
'whitelist': ['zmpi'],
|
|
||||||
'blacklist': ['callpath', 'mpi'],
|
|
||||||
'all': {
|
|
||||||
'autoload': 'direct'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration_conflicts = {
|
|
||||||
'enable': ['tcl'],
|
|
||||||
'tcl': {
|
|
||||||
'naming_scheme': '{name}/{version}-{compiler.name}',
|
|
||||||
'all': {
|
|
||||||
'conflict': ['{name}', 'intel/14.0.1']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration_wrong_conflicts = {
|
|
||||||
'enable': ['tcl'],
|
|
||||||
'tcl': {
|
|
||||||
'naming_scheme': '{name}/{version}-{compiler.name}',
|
|
||||||
'all': {
|
|
||||||
'conflict': ['{name}/{compiler.name}']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
configuration_suffix = {
|
|
||||||
'enable': ['tcl'],
|
|
||||||
'tcl': {
|
|
||||||
'mpileaks': {
|
|
||||||
'suffixes': {
|
|
||||||
'+debug': 'foo',
|
|
||||||
'~debug': 'bar'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class HelperFunctionsTests(MockPackagesTest):
|
class HelperFunctionsTests(MockPackagesTest):
|
||||||
|
@ -187,44 +92,156 @@ def test_inspect_path(self):
|
||||||
self.assertTrue('CPATH' in names)
|
self.assertTrue('CPATH' in names)
|
||||||
|
|
||||||
|
|
||||||
class TclTests(MockPackagesTest):
|
class ModuleFileGeneratorTests(MockPackagesTest):
|
||||||
|
"""
|
||||||
|
Base class to test module file generators. Relies on child having defined
|
||||||
|
a 'factory' attribute to create an instance of the generator to be tested.
|
||||||
|
"""
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(TclTests, self).setUp()
|
super(ModuleFileGeneratorTests, self).setUp()
|
||||||
self.configuration_obj = spack.modules.CONFIGURATION
|
self.configuration_instance = spack.modules.CONFIGURATION
|
||||||
|
self.module_types_instance = spack.modules.module_types
|
||||||
spack.modules.open = mock_open
|
spack.modules.open = mock_open
|
||||||
# Make sure that a non-mocked configuration will trigger an error
|
# Make sure that a non-mocked configuration will trigger an error
|
||||||
spack.modules.CONFIGURATION = None
|
spack.modules.CONFIGURATION = None
|
||||||
|
spack.modules.module_types = {self.factory.name: self.factory}
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
del spack.modules.open
|
del spack.modules.open
|
||||||
spack.modules.CONFIGURATION = self.configuration_obj
|
spack.modules.module_types = self.module_types_instance
|
||||||
super(TclTests, self).tearDown()
|
spack.modules.CONFIGURATION = self.configuration_instance
|
||||||
|
super(ModuleFileGeneratorTests, self).tearDown()
|
||||||
|
|
||||||
def get_modulefile_content(self, spec):
|
def get_modulefile_content(self, spec):
|
||||||
spec.concretize()
|
spec.concretize()
|
||||||
generator = spack.modules.TclModule(spec)
|
generator = self.factory(spec)
|
||||||
generator.write()
|
generator.write()
|
||||||
content = FILE_REGISTRY[generator.file_name].split('\n')
|
content = FILE_REGISTRY[generator.file_name].split('\n')
|
||||||
return content
|
return content
|
||||||
|
|
||||||
|
|
||||||
|
class TclTests(ModuleFileGeneratorTests):
|
||||||
|
|
||||||
|
factory = spack.modules.TclModule
|
||||||
|
|
||||||
|
configuration_autoload_direct = {
|
||||||
|
'enable': ['tcl'],
|
||||||
|
'tcl': {
|
||||||
|
'all': {
|
||||||
|
'autoload': 'direct'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_autoload_all = {
|
||||||
|
'enable': ['tcl'],
|
||||||
|
'tcl': {
|
||||||
|
'all': {
|
||||||
|
'autoload': 'all'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_prerequisites_direct = {
|
||||||
|
'enable': ['tcl'],
|
||||||
|
'tcl': {
|
||||||
|
'all': {
|
||||||
|
'prerequisites': 'direct'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_prerequisites_all = {
|
||||||
|
'enable': ['tcl'],
|
||||||
|
'tcl': {
|
||||||
|
'all': {
|
||||||
|
'prerequisites': 'all'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_alter_environment = {
|
||||||
|
'enable': ['tcl'],
|
||||||
|
'tcl': {
|
||||||
|
'all': {
|
||||||
|
'filter': {'environment_blacklist': ['CMAKE_PREFIX_PATH']},
|
||||||
|
'environment': {
|
||||||
|
'set': {'{name}_ROOT': '{prefix}'}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'platform=test target=x86_64': {
|
||||||
|
'environment': {
|
||||||
|
'set': {'FOO': 'foo'},
|
||||||
|
'unset': ['BAR']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'platform=test target=x86_32': {
|
||||||
|
'load': ['foo/bar']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_blacklist = {
|
||||||
|
'enable': ['tcl'],
|
||||||
|
'tcl': {
|
||||||
|
'whitelist': ['zmpi'],
|
||||||
|
'blacklist': ['callpath', 'mpi'],
|
||||||
|
'all': {
|
||||||
|
'autoload': 'direct'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_conflicts = {
|
||||||
|
'enable': ['tcl'],
|
||||||
|
'tcl': {
|
||||||
|
'naming_scheme': '{name}/{version}-{compiler.name}',
|
||||||
|
'all': {
|
||||||
|
'conflict': ['{name}', 'intel/14.0.1']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_wrong_conflicts = {
|
||||||
|
'enable': ['tcl'],
|
||||||
|
'tcl': {
|
||||||
|
'naming_scheme': '{name}/{version}-{compiler.name}',
|
||||||
|
'all': {
|
||||||
|
'conflict': ['{name}/{compiler.name}']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_suffix = {
|
||||||
|
'enable': ['tcl'],
|
||||||
|
'tcl': {
|
||||||
|
'mpileaks': {
|
||||||
|
'suffixes': {
|
||||||
|
'+debug': 'foo',
|
||||||
|
'~debug': 'bar'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def test_simple_case(self):
|
def test_simple_case(self):
|
||||||
spack.modules.CONFIGURATION = configuration_autoload_direct
|
spack.modules.CONFIGURATION = self.configuration_autoload_direct
|
||||||
spec = spack.spec.Spec('mpich@3.0.4')
|
spec = spack.spec.Spec(mpich_spec_string)
|
||||||
content = self.get_modulefile_content(spec)
|
content = self.get_modulefile_content(spec)
|
||||||
self.assertTrue('module-whatis "mpich @3.0.4"' in content)
|
self.assertTrue('module-whatis "mpich @3.0.4"' in content)
|
||||||
self.assertRaises(TypeError, spack.modules.dependencies,
|
self.assertRaises(TypeError, spack.modules.dependencies,
|
||||||
spec, 'non-existing-tag')
|
spec, 'non-existing-tag')
|
||||||
|
|
||||||
def test_autoload(self):
|
def test_autoload(self):
|
||||||
spack.modules.CONFIGURATION = configuration_autoload_direct
|
spack.modules.CONFIGURATION = self.configuration_autoload_direct
|
||||||
spec = spack.spec.Spec('mpileaks')
|
spec = spack.spec.Spec(mpileaks_spec_string)
|
||||||
content = self.get_modulefile_content(spec)
|
content = self.get_modulefile_content(spec)
|
||||||
self.assertEqual(len([x for x in content if 'is-loaded' in x]), 2)
|
self.assertEqual(len([x for x in content if 'is-loaded' in x]), 2)
|
||||||
self.assertEqual(len([x for x in content if 'module load ' in x]), 2)
|
self.assertEqual(len([x for x in content if 'module load ' in x]), 2)
|
||||||
|
|
||||||
spack.modules.CONFIGURATION = configuration_autoload_all
|
spack.modules.CONFIGURATION = self.configuration_autoload_all
|
||||||
spec = spack.spec.Spec('mpileaks')
|
spec = spack.spec.Spec(mpileaks_spec_string)
|
||||||
content = self.get_modulefile_content(spec)
|
content = self.get_modulefile_content(spec)
|
||||||
self.assertEqual(len([x for x in content if 'is-loaded' in x]), 5)
|
self.assertEqual(len([x for x in content if 'is-loaded' in x]), 5)
|
||||||
self.assertEqual(len([x for x in content if 'module load ' in x]), 5)
|
self.assertEqual(len([x for x in content if 'module load ' in x]), 5)
|
||||||
|
@ -252,18 +269,18 @@ def test_autoload(self):
|
||||||
self.assertEqual(len([x for x in content if 'module load ' in x]), 2)
|
self.assertEqual(len([x for x in content if 'module load ' in x]), 2)
|
||||||
|
|
||||||
def test_prerequisites(self):
|
def test_prerequisites(self):
|
||||||
spack.modules.CONFIGURATION = configuration_prerequisites_direct
|
spack.modules.CONFIGURATION = self.configuration_prerequisites_direct
|
||||||
spec = spack.spec.Spec('mpileaks arch=x86-linux')
|
spec = spack.spec.Spec('mpileaks arch=x86-linux')
|
||||||
content = self.get_modulefile_content(spec)
|
content = self.get_modulefile_content(spec)
|
||||||
self.assertEqual(len([x for x in content if 'prereq' in x]), 2)
|
self.assertEqual(len([x for x in content if 'prereq' in x]), 2)
|
||||||
|
|
||||||
spack.modules.CONFIGURATION = configuration_prerequisites_all
|
spack.modules.CONFIGURATION = self.configuration_prerequisites_all
|
||||||
spec = spack.spec.Spec('mpileaks arch=x86-linux')
|
spec = spack.spec.Spec('mpileaks arch=x86-linux')
|
||||||
content = self.get_modulefile_content(spec)
|
content = self.get_modulefile_content(spec)
|
||||||
self.assertEqual(len([x for x in content if 'prereq' in x]), 5)
|
self.assertEqual(len([x for x in content if 'prereq' in x]), 5)
|
||||||
|
|
||||||
def test_alter_environment(self):
|
def test_alter_environment(self):
|
||||||
spack.modules.CONFIGURATION = configuration_alter_environment
|
spack.modules.CONFIGURATION = self.configuration_alter_environment
|
||||||
spec = spack.spec.Spec('mpileaks platform=test target=x86_64')
|
spec = spack.spec.Spec('mpileaks platform=test target=x86_64')
|
||||||
content = self.get_modulefile_content(spec)
|
content = self.get_modulefile_content(spec)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
@ -293,7 +310,7 @@ def test_alter_environment(self):
|
||||||
len([x for x in content if 'setenv LIBDWARF_ROOT' in x]), 1)
|
len([x for x in content if 'setenv LIBDWARF_ROOT' in x]), 1)
|
||||||
|
|
||||||
def test_blacklist(self):
|
def test_blacklist(self):
|
||||||
spack.modules.CONFIGURATION = configuration_blacklist
|
spack.modules.CONFIGURATION = self.configuration_blacklist
|
||||||
spec = spack.spec.Spec('mpileaks ^zmpi')
|
spec = spack.spec.Spec('mpileaks ^zmpi')
|
||||||
content = self.get_modulefile_content(spec)
|
content = self.get_modulefile_content(spec)
|
||||||
self.assertEqual(len([x for x in content if 'is-loaded' in x]), 1)
|
self.assertEqual(len([x for x in content if 'is-loaded' in x]), 1)
|
||||||
|
@ -307,7 +324,7 @@ def test_blacklist(self):
|
||||||
self.assertEqual(len([x for x in content if 'module load ' in x]), 1)
|
self.assertEqual(len([x for x in content if 'module load ' in x]), 1)
|
||||||
|
|
||||||
def test_conflicts(self):
|
def test_conflicts(self):
|
||||||
spack.modules.CONFIGURATION = configuration_conflicts
|
spack.modules.CONFIGURATION = self.configuration_conflicts
|
||||||
spec = spack.spec.Spec('mpileaks')
|
spec = spack.spec.Spec('mpileaks')
|
||||||
content = self.get_modulefile_content(spec)
|
content = self.get_modulefile_content(spec)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
@ -317,11 +334,11 @@ def test_conflicts(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len([x for x in content if x == 'conflict intel/14.0.1']), 1)
|
len([x for x in content if x == 'conflict intel/14.0.1']), 1)
|
||||||
|
|
||||||
spack.modules.CONFIGURATION = configuration_wrong_conflicts
|
spack.modules.CONFIGURATION = self.configuration_wrong_conflicts
|
||||||
self.assertRaises(SystemExit, self.get_modulefile_content, spec)
|
self.assertRaises(SystemExit, self.get_modulefile_content, spec)
|
||||||
|
|
||||||
def test_suffixes(self):
|
def test_suffixes(self):
|
||||||
spack.modules.CONFIGURATION = configuration_suffix
|
spack.modules.CONFIGURATION = self.configuration_suffix
|
||||||
spec = spack.spec.Spec('mpileaks+debug arch=x86-linux')
|
spec = spack.spec.Spec('mpileaks+debug arch=x86-linux')
|
||||||
spec.concretize()
|
spec.concretize()
|
||||||
generator = spack.modules.TclModule(spec)
|
generator = spack.modules.TclModule(spec)
|
||||||
|
@ -333,18 +350,123 @@ def test_suffixes(self):
|
||||||
self.assertTrue('bar' in generator.use_name)
|
self.assertTrue('bar' in generator.use_name)
|
||||||
|
|
||||||
|
|
||||||
configuration_dotkit = {
|
class LmodTests(ModuleFileGeneratorTests):
|
||||||
'enable': ['dotkit'],
|
factory = spack.modules.LmodModule
|
||||||
'dotkit': {
|
|
||||||
'all': {
|
configuration_autoload_direct = {
|
||||||
'prerequisites': 'direct'
|
'enable': ['lmod'],
|
||||||
|
'lmod': {
|
||||||
|
'all': {
|
||||||
|
'autoload': 'direct'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
configuration_autoload_all = {
|
||||||
|
'enable': ['lmod'],
|
||||||
|
'lmod': {
|
||||||
|
'all': {
|
||||||
|
'autoload': 'all'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_alter_environment = {
|
||||||
|
'enable': ['lmod'],
|
||||||
|
'lmod': {
|
||||||
|
'all': {
|
||||||
|
'filter': {'environment_blacklist': ['CMAKE_PREFIX_PATH']}
|
||||||
|
},
|
||||||
|
'platform=test target=x86_64': {
|
||||||
|
'environment': {
|
||||||
|
'set': {'FOO': 'foo'},
|
||||||
|
'unset': ['BAR']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'platform=test target=x86_32': {
|
||||||
|
'load': ['foo/bar']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
configuration_blacklist = {
|
||||||
|
'enable': ['lmod'],
|
||||||
|
'lmod': {
|
||||||
|
'blacklist': ['callpath'],
|
||||||
|
'all': {
|
||||||
|
'autoload': 'direct'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_simple_case(self):
|
||||||
|
spack.modules.CONFIGURATION = self.configuration_autoload_direct
|
||||||
|
spec = spack.spec.Spec(mpich_spec_string)
|
||||||
|
content = self.get_modulefile_content(spec)
|
||||||
|
self.assertTrue('-- -*- lua -*-' in content)
|
||||||
|
self.assertTrue('whatis([[Name : mpich]])' in content)
|
||||||
|
self.assertTrue('whatis([[Version : 3.0.4]])' in content)
|
||||||
|
|
||||||
|
def test_autoload(self):
|
||||||
|
spack.modules.CONFIGURATION = self.configuration_autoload_direct
|
||||||
|
spec = spack.spec.Spec(mpileaks_spec_string)
|
||||||
|
content = self.get_modulefile_content(spec)
|
||||||
|
self.assertEqual(
|
||||||
|
len([x for x in content if 'if not isloaded(' in x]), 2)
|
||||||
|
self.assertEqual(len([x for x in content if 'load(' in x]), 2)
|
||||||
|
|
||||||
|
spack.modules.CONFIGURATION = self.configuration_autoload_all
|
||||||
|
spec = spack.spec.Spec(mpileaks_spec_string)
|
||||||
|
content = self.get_modulefile_content(spec)
|
||||||
|
self.assertEqual(
|
||||||
|
len([x for x in content if 'if not isloaded(' in x]), 5)
|
||||||
|
self.assertEqual(len([x for x in content if 'load(' in x]), 5)
|
||||||
|
|
||||||
|
def test_alter_environment(self):
|
||||||
|
spack.modules.CONFIGURATION = self.configuration_alter_environment
|
||||||
|
spec = spack.spec.Spec('mpileaks platform=test target=x86_64')
|
||||||
|
content = self.get_modulefile_content(spec)
|
||||||
|
self.assertEqual(
|
||||||
|
len([x
|
||||||
|
for x in content
|
||||||
|
if x.startswith('prepend_path("CMAKE_PREFIX_PATH"')]), 0)
|
||||||
|
self.assertEqual(
|
||||||
|
len([x for x in content if 'setenv("FOO", "foo")' in x]), 1)
|
||||||
|
self.assertEqual(
|
||||||
|
len([x for x in content if 'unsetenv("BAR")' in x]), 1)
|
||||||
|
|
||||||
|
spec = spack.spec.Spec('libdwarf %clang platform=test target=x86_32')
|
||||||
|
content = self.get_modulefile_content(spec)
|
||||||
|
print('\n'.join(content))
|
||||||
|
self.assertEqual(
|
||||||
|
len([x
|
||||||
|
for x in content
|
||||||
|
if x.startswith('prepend-path("CMAKE_PREFIX_PATH"')]), 0)
|
||||||
|
self.assertEqual(
|
||||||
|
len([x for x in content if 'setenv("FOO", "foo")' in x]), 0)
|
||||||
|
self.assertEqual(
|
||||||
|
len([x for x in content if 'unsetenv("BAR")' in x]), 0)
|
||||||
|
|
||||||
|
def test_blacklist(self):
|
||||||
|
spack.modules.CONFIGURATION = self.configuration_blacklist
|
||||||
|
spec = spack.spec.Spec(mpileaks_spec_string)
|
||||||
|
content = self.get_modulefile_content(spec)
|
||||||
|
self.assertEqual(
|
||||||
|
len([x for x in content if 'if not isloaded(' in x]), 1)
|
||||||
|
self.assertEqual(len([x for x in content if 'load(' in x]), 1)
|
||||||
|
|
||||||
|
|
||||||
class DotkitTests(MockPackagesTest):
|
class DotkitTests(MockPackagesTest):
|
||||||
|
|
||||||
|
configuration_dotkit = {
|
||||||
|
'enable': ['dotkit'],
|
||||||
|
'dotkit': {
|
||||||
|
'all': {
|
||||||
|
'prerequisites': 'direct'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super(DotkitTests, self).setUp()
|
super(DotkitTests, self).setUp()
|
||||||
self.configuration_obj = spack.modules.CONFIGURATION
|
self.configuration_obj = spack.modules.CONFIGURATION
|
||||||
|
@ -365,7 +487,7 @@ def get_modulefile_content(self, spec):
|
||||||
return content
|
return content
|
||||||
|
|
||||||
def test_dotkit(self):
|
def test_dotkit(self):
|
||||||
spack.modules.CONFIGURATION = configuration_dotkit
|
spack.modules.CONFIGURATION = self.configuration_dotkit
|
||||||
spec = spack.spec.Spec('mpileaks arch=x86-linux')
|
spec = spack.spec.Spec('mpileaks arch=x86-linux')
|
||||||
content = self.get_modulefile_content(spec)
|
content = self.get_modulefile_content(spec)
|
||||||
self.assertTrue('#c spack' in content)
|
self.assertTrue('#c spack' in content)
|
||||||
|
|
|
@ -22,9 +22,10 @@
|
||||||
# License along with this program; if not, write to the Free Software
|
# License along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
##############################################################################
|
##############################################################################
|
||||||
from spack import *
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from spack import *
|
||||||
|
|
||||||
|
|
||||||
class Llvm(Package):
|
class Llvm(Package):
|
||||||
"""The LLVM Project is a collection of modular and reusable compiler and
|
"""The LLVM Project is a collection of modular and reusable compiler and
|
||||||
|
@ -37,9 +38,11 @@ class Llvm(Package):
|
||||||
homepage = 'http://llvm.org/'
|
homepage = 'http://llvm.org/'
|
||||||
url = 'http://llvm.org/releases/3.7.1/llvm-3.7.1.src.tar.xz'
|
url = 'http://llvm.org/releases/3.7.1/llvm-3.7.1.src.tar.xz'
|
||||||
|
|
||||||
|
family = 'compiler' # Used by lmod
|
||||||
|
|
||||||
# currently required by mesa package
|
# currently required by mesa package
|
||||||
version('3.0', 'a8e5f5f1c1adebae7b4a654c376a6005',
|
version('3.0', 'a8e5f5f1c1adebae7b4a654c376a6005',
|
||||||
url='http://llvm.org/releases/3.0/llvm-3.0.tar.gz')
|
url='http://llvm.org/releases/3.0/llvm-3.0.tar.gz') # currently required by mesa package
|
||||||
|
|
||||||
variant('debug', default=False,
|
variant('debug', default=False,
|
||||||
description="Build a debug version of LLVM, this increases "
|
description="Build a debug version of LLVM, this increases "
|
||||||
|
|
Loading…
Reference in a new issue