summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/modules.py151
-rw-r--r--var/spack/repos/builtin/packages/mpich/package.py25
-rw-r--r--var/spack/repos/builtin/packages/python/package.py15
3 files changed, 137 insertions, 54 deletions
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
index c27043db8c..1a0a0fd4d6 100644
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -47,18 +47,18 @@ of module file.
__all__ = ['EnvModule', 'Dotkit', 'TclModule']
import os
+import os.path
import re
-import textwrap
import shutil
+import textwrap
from glob import glob
import llnl.util.tty as tty
-from llnl.util.filesystem import join_path, mkdirp
-
import spack
+from spack.environment import *
+from llnl.util.filesystem import join_path, mkdirp
-"""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 = {}
@@ -79,6 +79,32 @@ 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):
+ env, inspector = EnvironmentModifications(), PathInspector()
+ os.path.walk(path, inspector, env)
+ return env
+
+
class EnvModule(object):
name = 'env_module'
@@ -88,21 +114,27 @@ class EnvModule(object):
if cls.name != 'env_module':
module_types[cls.name] = cls
-
def __init__(self, spec=None):
# category in the modules system
# TODO: come up with smarter category names.
self.category = "spack"
- # Descriptions for the module system's UI
- self.short_description = ""
- self.long_description = ""
-
# 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
+
+ # short description default is just the package + version
+ # packages can provide this optional attribute
+ self.short_description = spec.format("$_ $@")
+ if hasattr(self.pkg, 'short_description'):
+ self.short_description = self.pkg.short_description
+ # long description is the docstring with reduced whitespace.
+ self.long_description = None
+ if self.spec.package.__doc__:
+ self.long_description = re.sub(r'\s+', ' ', self.spec.package.__doc__)
@property
def paths(self):
@@ -130,26 +162,19 @@ class EnvModule(object):
add_path(var, directory)
# Add python path unless it's an actual python installation
- # TODO: is there a better way to do this?
+ # 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)
-
- # short description is just the package + version
- # TODO: maybe packages can optionally provide it.
- self.short_description = self.spec.format("$_ $@")
-
- # long description is the docstring with reduced whitespace.
- if self.spec.package.__doc__:
- self.long_description = re.sub(r'\s+', ' ', self.spec.package.__doc__)
+ add_path('GEM_PATH', self.spec.prefix)
return self._paths
-
def write(self):
"""Write out a module file for this object."""
module_dir = os.path.dirname(self.file_name)
@@ -160,9 +185,18 @@ class EnvModule(object):
if not self.paths:
return
- with open(self.file_name, 'w') as f:
- self._write(f)
+ # Construct the changes that needs to be done on the environment for
+ env = inspect_path(self.spec.prefix)
+ # FIXME : move the logic to inspection
+ env.prepend_path('CMAKE_PREFIX_PATH', self.spec.prefix)
+ # FIXME : decide how to distinguish between calls done in the installation and elsewhere
+ env.extend(self.spec.package.environment_modifications(None))
+ # site_specific = ...`
+ if not env:
+ return
+ with open(self.file_name, 'w') as f:
+ self._write(f, env)
def _write(self, stream):
"""To be implemented by subclasses."""
@@ -175,14 +209,12 @@ class EnvModule(object):
where this module lives."""
raise NotImplementedError()
-
@property
def use_name(self):
"""Subclasses should implement this to return the name the
module command uses to refer to the package."""
raise NotImplementedError()
-
def remove(self):
mod_file = self.file_name
if os.path.exists(mod_file):
@@ -205,7 +237,7 @@ class Dotkit(EnvModule):
self.spec.compiler.version,
self.spec.dag_hash())
- def _write(self, dk_file):
+ def _write(self, dk_file, env):
# Category
if self.category:
dk_file.write('#c %s\n' % self.category)
@@ -231,6 +263,10 @@ class Dotkit(EnvModule):
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'
+ }
@property
def file_name(self):
@@ -244,25 +280,56 @@ class TclModule(EnvModule):
self.spec.compiler.version,
self.spec.dag_hash())
-
- def _write(self, m_file):
- # TODO: cateogry?
- m_file.write('#%Module1.0\n')
-
+ 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
+ """
+ # TCL Modulefile header
+ module_file.write('#%Module1.0\n')
+ # TODO : category ?
# Short description
if self.short_description:
- m_file.write('module-whatis \"%s\"\n\n' % self.short_description)
+ module_file.write('module-whatis \"%s\"\n\n' % self.short_description)
# Long description
if self.long_description:
- m_file.write('proc ModulesHelp { } {\n')
+ module_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)
+ 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)
diff --git a/var/spack/repos/builtin/packages/mpich/package.py b/var/spack/repos/builtin/packages/mpich/package.py
index d298981c92..4c34d0308f 100644
--- a/var/spack/repos/builtin/packages/mpich/package.py
+++ b/var/spack/repos/builtin/packages/mpich/package.py
@@ -25,6 +25,7 @@
from spack import *
import os
+
class Mpich(Package):
"""MPICH is a high performance and widely portable implementation of
the Message Passing Interface (MPI) standard."""
@@ -48,11 +49,25 @@ class Mpich(Package):
def environment_modifications(self, dependent_spec):
env = super(Mpich, self).environment_modifications(dependent_spec)
- env.set_env('MPICH_CC', os.environ['CC'])
- env.set_env('MPICH_CXX', os.environ['CXX'])
- env.set_env('MPICH_F77', os.environ['F77'])
- env.set_env('MPICH_F90', os.environ['FC'])
- env.set_env('MPICH_FC', os.environ['FC'])
+
+ if dependent_spec is None:
+ # We are not using compiler wrappers
+ cc = self.compiler.cc
+ cxx = self.compiler.cxx
+ f77 = self.compiler.f77
+ f90 = fc = self.compiler.fc
+ else:
+ # Spack compiler wrappers
+ cc = os.environ['CC']
+ cxx = os.environ['CXX']
+ f77 = os.environ['F77']
+ f90 = fc = os.environ['FC']
+
+ env.set_env('MPICH_CC', cc)
+ env.set_env('MPICH_CXX', cxx)
+ env.set_env('MPICH_F77', f77)
+ env.set_env('MPICH_F90', f90)
+ env.set_env('MPICH_FC', fc)
return env
def module_modifications(self, module, spec, dep_spec):
diff --git a/var/spack/repos/builtin/packages/python/package.py b/var/spack/repos/builtin/packages/python/package.py
index 2f9948d451..acb3651726 100644
--- a/var/spack/repos/builtin/packages/python/package.py
+++ b/var/spack/repos/builtin/packages/python/package.py
@@ -91,13 +91,14 @@ class Python(Package):
def environment_modifications(self, extension_spec):
env = super(Python, self).environment_modifications(extension_spec)
- # Set PYTHONPATH to include site-packages dir for the
- # extension and any other python extensions it depends on.
- python_paths = []
- for d in extension_spec.traverse():
- if d.package.extends(self.spec):
- python_paths.append(os.path.join(d.prefix, self.site_packages_dir))
- env.set_env['PYTHONPATH'] = ':'.join(python_paths)
+ if extension_spec is not None:
+ # Set PYTHONPATH to include site-packages dir for the
+ # extension and any other python extensions it depends on.
+ python_paths = []
+ for d in extension_spec.traverse():
+ if d.package.extends(self.spec):
+ python_paths.append(os.path.join(d.prefix, self.site_packages_dir))
+ env.set_env['PYTHONPATH'] = ':'.join(python_paths)
return env
def module_modifications(self, module, spec, ext_spec):