summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/modules.py205
1 files changed, 66 insertions, 139 deletions
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
index 1a0a0fd4d6..b64a8b3226 100644
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -22,14 +22,12 @@
# along with this program; if not, write to the Free Software Foundation,
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
##############################################################################
-"""This module contains code for creating environment modules, which
-can include dotkits, tcl modules, lmod, and others.
+"""
+This module contains code for creating environment modules, which can include dotkits, tcl modules, lmod, and others.
-The various types of modules are installed by post-install hooks and
-removed after an uninstall by post-uninstall hooks. This class
-consolidates the logic for creating an abstract description of the
-information that module systems need. Currently that includes a
-number of directories to be appended to paths in the user's environment:
+The various types of modules are installed by post-install hooks and removed after an uninstall by post-uninstall hooks.
+This class consolidates the logic for creating an abstract description of the information that module systems need.
+Currently that includes a number of directories to be appended to paths in the user's environment:
* /bin directories to be appended to PATH
* /lib* directories for LD_LIBRARY_PATH
@@ -37,26 +35,23 @@ number of directories to be appended to paths in the user's environment:
* /man* and /share/man* directories for MANPATH
* the package prefix for CMAKE_PREFIX_PATH
-This module also includes logic for coming up with unique names for
-the module files so that they can be found by the various
-shell-support files in $SPACK/share/spack/setup-env.*.
+This module also includes logic for coming up with unique names for the module files so that they can be found by the
+various shell-support files in $SPACK/share/spack/setup-env.*.
-Each hook in hooks/ implements the logic for writing its specific type
-of module file.
+Each hook in hooks/ implements the logic for writing its specific type of module file.
"""
-__all__ = ['EnvModule', 'Dotkit', 'TclModule']
-
import os
import os.path
import re
import shutil
import textwrap
-from glob import glob
import llnl.util.tty as tty
import spack
-from spack.environment import *
from llnl.util.filesystem import join_path, mkdirp
+from spack.environment import *
+
+__all__ = ['EnvModule', 'Dotkit', 'TclModule']
# Registry of all types of modules. Entries created by EnvModule's metaclass
module_types = {}
@@ -79,34 +74,35 @@ def print_help():
"")
-class PathInspector(object):
- dirname2varname = {
- 'bin': ('PATH',),
- 'man': ('MANPATH',),
- 'lib': ('LIBRARY_PATH', 'LD_LIBRARY_PATH'),
- 'lib64': ('LIBRARY_PATH', 'LD_LIBRARY_PATH'),
- 'include': ('CPATH',),
- 'pkgconfig': ('PKG_CONFIG_PATH',)
- }
-
- def __call__(self, env, directory, names):
- for name in names:
- variables = PathInspector.dirname2varname.get(name, None)
- if variables is None:
- continue
- absolute_path = join_path(os.path.abspath(directory), name)
- for variable in variables:
- env.prepend_path(variable, absolute_path)
-
-
def inspect_path(path):
+ class PathInspector(object):
+ dirname2varname = {
+ 'bin': ('PATH',),
+ 'man': ('MANPATH',),
+ 'lib': ('LIBRARY_PATH', 'LD_LIBRARY_PATH'),
+ 'lib64': ('LIBRARY_PATH', 'LD_LIBRARY_PATH'),
+ 'include': ('CPATH',),
+ 'pkgconfig': ('PKG_CONFIG_PATH',)
+ }
+
+ def __call__(self, env, directory, names):
+ for name in names:
+ variables = PathInspector.dirname2varname.get(name, None)
+ if variables is None:
+ continue
+ absolute_path = join_path(os.path.abspath(directory), name)
+ for variable in variables:
+ env.prepend_path(variable, absolute_path)
+
env, inspector = EnvironmentModifications(), PathInspector()
os.path.walk(path, inspector, env)
+ env.prepend_path('CMAKE_PREFIX_PATH', path)
return env
class EnvModule(object):
name = 'env_module'
+ formats = {}
class __metaclass__(type):
def __init__(cls, name, bases, dict):
@@ -119,9 +115,6 @@ class EnvModule(object):
# TODO: come up with smarter category names.
self.category = "spack"
- # dict pathname -> list of directories to be prepended to in
- # the module file.
- self._paths = None
self.spec = spec
self.pkg = spec.package # Just stored for convenience
@@ -136,44 +129,21 @@ class EnvModule(object):
if self.spec.package.__doc__:
self.long_description = re.sub(r'\s+', ' ', self.spec.package.__doc__)
- @property
- def paths(self):
- if self._paths is None:
- self._paths = {}
-
- def add_path(path_name, directory):
- path = self._paths.setdefault(path_name, [])
- path.append(directory)
-
- # Add paths if they exist.
- for var, directory in [
- ('PATH', self.spec.prefix.bin),
- ('MANPATH', self.spec.prefix.man),
- ('MANPATH', self.spec.prefix.share_man),
- ('LIBRARY_PATH', self.spec.prefix.lib),
- ('LIBRARY_PATH', self.spec.prefix.lib64),
- ('LD_LIBRARY_PATH', self.spec.prefix.lib),
- ('LD_LIBRARY_PATH', self.spec.prefix.lib64),
- ('CPATH', self.spec.prefix.include),
- ('PKG_CONFIG_PATH', join_path(self.spec.prefix.lib, 'pkgconfig')),
- ('PKG_CONFIG_PATH', join_path(self.spec.prefix.lib64, 'pkgconfig'))]:
-
- if os.path.isdir(directory):
- add_path(var, directory)
-
- # Add python path unless it's an actual python installation
- # TODO : is there a better way to do this?
- # FIXME : add PYTHONPATH to every python package
- if self.spec.name != 'python':
- site_packages = glob(join_path(self.spec.prefix.lib, "python*/site-packages"))
- if site_packages:
- add_path('PYTHONPATH', site_packages[0])
-
- # FIXME : Same for GEM_PATH
- if self.spec.package.extends(spack.spec.Spec('ruby')):
- add_path('GEM_PATH', self.spec.prefix)
-
- return self._paths
+ # @property
+ # def paths(self):
+ # # Add python path unless it's an actual python installation
+ # # TODO : is there a better way to do this?
+ # # FIXME : add PYTHONPATH to every python package
+ # if self.spec.name != 'python':
+ # site_packages = glob(join_path(self.spec.prefix.lib, "python*/site-packages"))
+ # if site_packages:
+ # add_path('PYTHONPATH', site_packages[0])
+ #
+ # # FIXME : Same for GEM_PATH
+ # if self.spec.package.extends(spack.spec.Spec('ruby')):
+ # add_path('GEM_PATH', self.spec.prefix)
+ #
+ # return self._paths
def write(self):
"""Write out a module file for this object."""
@@ -181,14 +151,9 @@ class EnvModule(object):
if not os.path.exists(module_dir):
mkdirp(module_dir)
- # If there are no paths, no need for a dotkit.
- if not self.paths:
- return
-
- # Construct the changes that needs to be done on the environment for
+ # Environment modifications guessed by inspecting the installation prefix
env = inspect_path(self.spec.prefix)
- # FIXME : move the logic to inspection
- env.prepend_path('CMAKE_PREFIX_PATH', self.spec.prefix)
+ # Package-specific environment modifications
# FIXME : decide how to distinguish between calls done in the installation and elsewhere
env.extend(self.spec.package.environment_modifications(None))
# site_specific = ...`
@@ -196,12 +161,17 @@ class EnvModule(object):
return
with open(self.file_name, 'w') as f:
- self._write(f, env)
+ self.write_header(f)
+ for line in self.process_environment_command(env):
+ f.write(line)
- def _write(self, stream):
- """To be implemented by subclasses."""
+ def write_header(self, stream):
raise NotImplementedError()
+ def process_environment_command(self, env):
+ for command in env:
+ # FIXME : how should we handle errors here?
+ yield self.formats[type(command)].format(command)
@property
def file_name(self):
@@ -225,10 +195,14 @@ class Dotkit(EnvModule):
name = 'dotkit'
path = join_path(spack.share_path, "dotkit")
+ formats = {
+ PrependPath: 'dk_alter {0.name} {0.path}\n',
+ SetEnv: 'dk_setenv {0.name} {0.value}\n'
+ }
+
@property
def file_name(self):
- return join_path(Dotkit.path, self.spec.architecture,
- '%s.dk' % self.use_name)
+ return join_path(Dotkit.path, self.spec.architecture, '%s.dk' % self.use_name)
@property
def use_name(self):
@@ -237,7 +211,7 @@ class Dotkit(EnvModule):
self.spec.compiler.version,
self.spec.dag_hash())
- def _write(self, dk_file, env):
+ def write_header(self, dk_file):
# Category
if self.category:
dk_file.write('#c %s\n' % self.category)
@@ -251,18 +225,11 @@ class Dotkit(EnvModule):
for line in textwrap.wrap(self.long_description, 72):
dk_file.write("#h %s\n" % line)
- # Path alterations
- for var, dirs in self.paths.items():
- for directory in dirs:
- dk_file.write("dk_alter %s %s\n" % (var, directory))
-
- # Let CMake find this package.
- dk_file.write("dk_alter CMAKE_PREFIX_PATH %s\n" % self.spec.prefix)
-
class TclModule(EnvModule):
name = 'tcl'
path = join_path(spack.share_path, "modules")
+
formats = {
PrependPath: 'prepend-path {0.name} \"{0.path}\"\n',
SetEnv: 'setenv {0.name} \"{0.value}\"\n'
@@ -272,7 +239,6 @@ class TclModule(EnvModule):
def file_name(self):
return join_path(TclModule.path, self.spec.architecture, self.use_name)
-
@property
def use_name(self):
return "%s-%s-%s-%s-%s" % (self.spec.name, self.spec.version,
@@ -280,19 +246,7 @@ class TclModule(EnvModule):
self.spec.compiler.version,
self.spec.dag_hash())
- def process_environment_command(self, env):
- for command in env:
- # FIXME : how should we handle errors here?
- yield self.formats[type(command)].format(command)
-
- def _write(self, module_file, env):
- """
- Writes a TCL module file for this package
-
- Args:
- module_file: module file stream
- env: list of environment modifications to be written in the module file
- """
+ def write_header(self, module_file):
# TCL Modulefile header
module_file.write('#%Module1.0\n')
# TODO : category ?
@@ -306,30 +260,3 @@ class TclModule(EnvModule):
doc = re.sub(r'"', '\"', self.long_description)
module_file.write("puts stderr \"%s\"\n" % doc)
module_file.write('}\n\n')
-
- # Environment modifications
- for line in self.process_environment_command(env):
- module_file.write(line)
-
- # FIXME : REMOVE
- # def _write(self, m_file):
- # # TODO: cateogry?
- # m_file.write('#%Module1.0\n')
- #
- # # Short description
- # if self.short_description:
- # m_file.write('module-whatis \"%s\"\n\n' % self.short_description)
- #
- # # Long description
- # if self.long_description:
- # m_file.write('proc ModulesHelp { } {\n')
- # doc = re.sub(r'"', '\"', self.long_description)
- # m_file.write("puts stderr \"%s\"\n" % doc)
- # m_file.write('}\n\n')
- #
- # # Path alterations
- # for var, dirs in self.paths.items():
- # for directory in dirs:
- # m_file.write("prepend-path %s \"%s\"\n" % (var, directory))
- #
- # m_file.write("prepend-path CMAKE_PREFIX_PATH \"%s\"\n" % self.spec.prefix)