modules : more sensible name to blacklist environment variables
modules : added skeleton to permit modifications based on specs
This commit is contained in:
parent
670cb423f9
commit
d636b4fdde
3 changed files with 68 additions and 56 deletions
|
@ -250,7 +250,7 @@
|
||||||
'type': 'string',
|
'type': 'string',
|
||||||
'enum': ['None', 'Direct', 'All']
|
'enum': ['None', 'Direct', 'All']
|
||||||
},
|
},
|
||||||
'module_type_configuration': {
|
'module_file_configuration': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
'default': {},
|
'default': {},
|
||||||
'additionalProperties': False,
|
'additionalProperties': False,
|
||||||
|
@ -260,7 +260,7 @@
|
||||||
'default': {},
|
'default': {},
|
||||||
'additionalProperties': False,
|
'additionalProperties': False,
|
||||||
'properties': {
|
'properties': {
|
||||||
'environment_modifications': {
|
'environment_blacklist': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'default': [],
|
'default': [],
|
||||||
'items': {
|
'items': {
|
||||||
|
@ -270,7 +270,21 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'autoload': {'$ref': '#/definitions/dependency_selection'},
|
'autoload': {'$ref': '#/definitions/dependency_selection'},
|
||||||
'prerequisites': {'$ref': '#/definitions/dependency_selection'}
|
'prerequisites': {'$ref': '#/definitions/dependency_selection'},
|
||||||
|
'environment': {
|
||||||
|
'type': 'object',
|
||||||
|
'default': {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'module_type_configuration': {
|
||||||
|
'type': 'object',
|
||||||
|
'default': {},
|
||||||
|
'properties': {
|
||||||
|
'all': {'$ref': '#/definitions/module_file_configuration'}
|
||||||
|
},
|
||||||
|
'patternProperties': {
|
||||||
|
r'\w[\w-]*': {'$ref': '#/definitions/module_file_configuration'}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -252,7 +252,7 @@ def validate(env, errstream):
|
||||||
set_or_unset_not_first(variable, list_of_changes, errstream)
|
set_or_unset_not_first(variable, list_of_changes, errstream)
|
||||||
|
|
||||||
|
|
||||||
def filter_environment_modifications(env, variables):
|
def filter_environment_blacklist(env, variables):
|
||||||
"""
|
"""
|
||||||
Generator that filters out any change to environment variables present in the input list
|
Generator that filters out any change to environment variables present in the input list
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
import spack
|
import spack
|
||||||
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, set_module_variables_for_package
|
from spack.build_environment import parent_class_modules, set_module_variables_for_package
|
||||||
from spack.environment import *
|
from spack.environment import *
|
||||||
|
@ -137,7 +138,6 @@ def __init__(self, spec=None):
|
||||||
if self.spec.package.__doc__:
|
if self.spec.package.__doc__:
|
||||||
self.long_description = re.sub(r'\s+', ' ', self.spec.package.__doc__)
|
self.long_description = re.sub(r'\s+', ' ', self.spec.package.__doc__)
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def category(self):
|
def category(self):
|
||||||
# Anything defined at the package level takes precedence
|
# Anything defined at the package level takes precedence
|
||||||
|
@ -150,11 +150,33 @@ def category(self):
|
||||||
return 'spack installed package'
|
return 'spack installed package'
|
||||||
|
|
||||||
def write(self):
|
def write(self):
|
||||||
"""Write out a module file for this object."""
|
"""
|
||||||
|
Writes out a module file for this object.
|
||||||
|
|
||||||
|
This method employs a template pattern and expects derived classes to:
|
||||||
|
- override the header property
|
||||||
|
- provide formats for autoload, prerequisites and environment changes
|
||||||
|
"""
|
||||||
module_dir = os.path.dirname(self.file_name)
|
module_dir = os.path.dirname(self.file_name)
|
||||||
if not os.path.exists(module_dir):
|
if not os.path.exists(module_dir):
|
||||||
mkdirp(module_dir)
|
mkdirp(module_dir)
|
||||||
|
|
||||||
|
def dependencies(request='All'):
|
||||||
|
if request == 'None':
|
||||||
|
return []
|
||||||
|
|
||||||
|
l = [xx for xx in sorted(self.spec.traverse(order='post', depth=True, cover='nodes', root=False), reverse=True)]
|
||||||
|
|
||||||
|
if request == 'Direct':
|
||||||
|
return [xx for ii, xx in l if ii == 1]
|
||||||
|
|
||||||
|
# FIXME : during module file creation nodes seem to be visited multiple times even if cover='nodes'
|
||||||
|
# FIXME : is given. This work around permits to get a unique list of spec anyhow.
|
||||||
|
# FIXME : Possibly we miss a merge step among nodes that refer to the same package.
|
||||||
|
seen = set()
|
||||||
|
seen_add = seen.add
|
||||||
|
return [xx for ii, xx in l if not (xx in seen or seen_add(xx))]
|
||||||
|
|
||||||
# Environment modifications guessed by inspecting the
|
# Environment modifications guessed by inspecting the
|
||||||
# installation prefix
|
# installation prefix
|
||||||
env = inspect_path(self.spec.prefix)
|
env = inspect_path(self.spec.prefix)
|
||||||
|
@ -162,23 +184,6 @@ def write(self):
|
||||||
# Let the extendee/dependency modify their extensions/dependencies before asking for
|
# Let the extendee/dependency modify their extensions/dependencies before asking for
|
||||||
# package-specific modifications
|
# package-specific modifications
|
||||||
spack_env = EnvironmentModifications()
|
spack_env = EnvironmentModifications()
|
||||||
|
|
||||||
def dependencies(request='All'):
|
|
||||||
if request == 'None':
|
|
||||||
return []
|
|
||||||
|
|
||||||
l = [x for x in sorted(self.spec.traverse(order='post', depth=True, cover='nodes', root=False), reverse=True)]
|
|
||||||
|
|
||||||
if request == 'Direct':
|
|
||||||
return [x for ii, x in l if ii == 1]
|
|
||||||
|
|
||||||
# FIXME : during module file creation nodes seem to be visited multiple times even if cover='nodes'
|
|
||||||
# FIXME : is given. This work around permits to get a unique list of spec anyhow.
|
|
||||||
# FIXME : Possibly we miss a merge step among nodes that refer to the same package.
|
|
||||||
seen = set()
|
|
||||||
seen_add = seen.add
|
|
||||||
return [x for ii, x in l if not (x in seen or seen_add(x))]
|
|
||||||
|
|
||||||
# TODO : the code down below is quite similar to build_environment.setup_package and needs to be
|
# TODO : the code down below is quite similar to build_environment.setup_package and needs to be
|
||||||
# TODO : factored out to a single place
|
# TODO : factored out to a single place
|
||||||
for item in dependencies('All'):
|
for item in dependencies('All'):
|
||||||
|
@ -207,43 +212,43 @@ def dependencies(request='All'):
|
||||||
|
|
||||||
# Filter modifications to environment variables
|
# Filter modifications to environment variables
|
||||||
try:
|
try:
|
||||||
filter_list = CONFIGURATION[self.name]['filter']['environment_modifications']
|
filter_list = CONFIGURATION[self.name]['filter']['environment_blacklist']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
filter_list = []
|
filter_list = []
|
||||||
|
|
||||||
with open(self.file_name, 'w') as f:
|
# Build up the module file content
|
||||||
# Header
|
module_file_content = self.header
|
||||||
f.write(self.header)
|
|
||||||
# Automatic loads
|
|
||||||
for x in autoload_list:
|
for x in autoload_list:
|
||||||
f.write(self.autoload(x))
|
module_file_content += self.autoload(x)
|
||||||
# Prerequisites
|
|
||||||
for x in prerequisites_list:
|
for x in prerequisites_list:
|
||||||
f.write(self.prerequisite(x))
|
module_file_content += self.prerequisite(x)
|
||||||
# Modifications to the environment
|
for line in self.process_environment_command(filter_environment_blacklist(env, filter_list)):
|
||||||
iterable = self.process_environment_command(filter_environment_modifications(env, filter_list))
|
module_file_content += line
|
||||||
for line in iterable:
|
|
||||||
f.write(line)
|
# Dump to file
|
||||||
|
with open(self.file_name, 'w') as f:
|
||||||
|
f.write(module_file_content)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def header(self):
|
def header(self):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def autoload(self, spec):
|
def autoload(self, spec):
|
||||||
raise NotImplementedError()
|
m = TclModule(spec)
|
||||||
|
return self.autoload_format.format(module_file=m.use_name)
|
||||||
|
|
||||||
def prerequisite(self, spec):
|
def prerequisite(self, spec):
|
||||||
raise NotImplementedError()
|
m = TclModule(spec)
|
||||||
|
return self.prerequisite_format.format(module_file=m.use_name)
|
||||||
|
|
||||||
def process_environment_command(self, env):
|
def process_environment_command(self, env):
|
||||||
for command in env:
|
for command in env:
|
||||||
try:
|
try:
|
||||||
yield self.formats[type(command)].format(**command.args)
|
yield self.environment_modifications_formats[type(command)].format(**command.args)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
tty.warn('Cannot handle command of type {command} : skipping request'.format(command=type(command)))
|
tty.warn('Cannot handle command of type {command} : skipping request'.format(command=type(command)))
|
||||||
tty.warn('{context} at {filename}:{lineno}'.format(**command.args))
|
tty.warn('{context} at {filename}:{lineno}'.format(**command.args))
|
||||||
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def file_name(self):
|
def file_name(self):
|
||||||
"""Subclasses should implement this to return the name of the file
|
"""Subclasses should implement this to return the name of the file
|
||||||
|
@ -266,7 +271,7 @@ class Dotkit(EnvModule):
|
||||||
name = 'dotkit'
|
name = 'dotkit'
|
||||||
path = join_path(spack.share_path, "dotkit")
|
path = join_path(spack.share_path, "dotkit")
|
||||||
|
|
||||||
formats = {
|
environment_modifications_formats = {
|
||||||
PrependPath: 'dk_alter {name} {value}\n',
|
PrependPath: 'dk_alter {name} {value}\n',
|
||||||
SetEnv: 'dk_setenv {name} {value}\n'
|
SetEnv: 'dk_setenv {name} {value}\n'
|
||||||
}
|
}
|
||||||
|
@ -304,7 +309,7 @@ class TclModule(EnvModule):
|
||||||
name = 'tcl'
|
name = 'tcl'
|
||||||
path = join_path(spack.share_path, "modules")
|
path = join_path(spack.share_path, "modules")
|
||||||
|
|
||||||
formats = {
|
environment_modifications_formats = {
|
||||||
PrependPath: 'prepend-path {name} \"{value}\"\n',
|
PrependPath: 'prepend-path {name} \"{value}\"\n',
|
||||||
AppendPath: 'append-path {name} \"{value}\"\n',
|
AppendPath: 'append-path {name} \"{value}\"\n',
|
||||||
RemovePath: 'remove-path {name} \"{value}\"\n',
|
RemovePath: 'remove-path {name} \"{value}\"\n',
|
||||||
|
@ -312,6 +317,13 @@ class TclModule(EnvModule):
|
||||||
UnsetEnv: 'unsetenv {name}\n'
|
UnsetEnv: 'unsetenv {name}\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
autoload_format = ('if ![ is-loaded {module_file} ] {{'
|
||||||
|
' puts stderr "Autoloading {module_file}"'
|
||||||
|
' module load {module_file}'
|
||||||
|
'}}')
|
||||||
|
|
||||||
|
prerequisite_format = 'prereq {module_file}\n'
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def file_name(self):
|
def file_name(self):
|
||||||
return join_path(TclModule.path, self.spec.architecture, self.use_name)
|
return join_path(TclModule.path, self.spec.architecture, self.use_name)
|
||||||
|
@ -339,17 +351,3 @@ def header(self):
|
||||||
header += 'puts stderr "%s"\n' % line
|
header += 'puts stderr "%s"\n' % line
|
||||||
header += '}\n\n'
|
header += '}\n\n'
|
||||||
return header
|
return header
|
||||||
|
|
||||||
def autoload(self, spec):
|
|
||||||
autoload_format = '''
|
|
||||||
if ![ is-loaded {module_file} ] {{
|
|
||||||
puts stderr "Autoloading {module_file}"
|
|
||||||
module load {module_file}
|
|
||||||
}}
|
|
||||||
'''''
|
|
||||||
m = TclModule(spec)
|
|
||||||
return autoload_format.format(module_file=m.use_name)
|
|
||||||
|
|
||||||
def prerequisite(self, spec):
|
|
||||||
m = TclModule(spec)
|
|
||||||
return 'prereq {module_file}\n'.format(module_file=m.use_name)
|
|
||||||
|
|
Loading…
Reference in a new issue