summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTodd Gamblin <tgamblin@llnl.gov>2016-03-21 01:48:18 -0700
committerTodd Gamblin <tgamblin@llnl.gov>2016-03-21 16:01:35 -0700
commit439d47b4e45c674ab9aa4ebd0c2bfaf6911ade60 (patch)
treee6f6aef90efa51ec277c5fdb10b0b5026d6db0d4 /lib
parente88df95b42fdcaa49552811853f8ca4ecc52cf9f (diff)
downloadspack-439d47b4e45c674ab9aa4ebd0c2bfaf6911ade60.tar.gz
spack-439d47b4e45c674ab9aa4ebd0c2bfaf6911ade60.tar.bz2
spack-439d47b4e45c674ab9aa4ebd0c2bfaf6911ade60.tar.xz
spack-439d47b4e45c674ab9aa4ebd0c2bfaf6911ade60.zip
Refactor environment setup.
- Gave setup_environment and setup_dependent_environment more similar signatures. They now allows editing the Spack env and the runtime env for *this* package and dependents, respectively. - modify_module renamed to setup_dependent_python_module for symmetry with setup_dependent_environment and to avoid confusion with environment modules. - removed need for patching Package objects at runtime. - adjust packages to reflect these changes.
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/build_environment.py35
-rw-r--r--lib/spack/spack/modules.py3
-rw-r--r--lib/spack/spack/package.py120
3 files changed, 117 insertions, 41 deletions
diff --git a/lib/spack/spack/build_environment.py b/lib/spack/spack/build_environment.py
index 59b234624c..5688d47e2d 100644
--- a/lib/spack/spack/build_environment.py
+++ b/lib/spack/spack/build_environment.py
@@ -84,7 +84,7 @@ class MakeExecutable(Executable):
return super(MakeExecutable, self).__call__(*args, **kwargs)
-def set_compiler_environment_variables(pkg):
+def set_compiler_environment_variables(pkg, env):
assert pkg.spec.concrete
# Set compiler variables used by CMake and autotools
assert all(key in pkg.compiler.link_paths for key in ('cc', 'cxx', 'f77', 'fc'))
@@ -92,7 +92,6 @@ def set_compiler_environment_variables(pkg):
# Populate an object with the list of environment modifications
# and return it
# TODO : add additional kwargs for better diagnostics, like requestor, ttyout, ttyerr, etc.
- env = EnvironmentModifications()
link_dir = spack.build_env_path
env.set_env('CC', join_path(link_dir, pkg.compiler.link_paths['cc']))
env.set_env('CXX', join_path(link_dir, pkg.compiler.link_paths['cxx']))
@@ -113,7 +112,7 @@ def set_compiler_environment_variables(pkg):
return env
-def set_build_environment_variables(pkg):
+def set_build_environment_variables(pkg, env):
"""
This ensures a clean install environment when we build packages
"""
@@ -134,7 +133,6 @@ def set_build_environment_variables(pkg):
if os.path.isdir(ci):
env_paths.append(ci)
- env = EnvironmentModifications()
for item in reversed(env_paths):
env.prepend_path('PATH', item)
env.set_env(SPACK_ENV_PATH, concatenate_paths(env_paths))
@@ -180,7 +178,7 @@ def set_build_environment_variables(pkg):
return env
-def set_module_variables_for_package(pkg, m):
+def set_module_variables_for_package(pkg, module):
"""Populate the module scope of install() with some useful functions.
This makes things easier for package writers.
"""
@@ -190,6 +188,8 @@ def set_module_variables_for_package(pkg, m):
jobs = 1
elif pkg.make_jobs:
jobs = pkg.make_jobs
+
+ m = module
m.make_jobs = jobs
# TODO: make these build deps that can be installed if not found.
@@ -271,9 +271,12 @@ def parent_class_modules(cls):
def setup_package(pkg):
"""Execute all environment setup routines."""
- env = EnvironmentModifications()
- env.extend(set_compiler_environment_variables(pkg))
- env.extend(set_build_environment_variables(pkg))
+ spack_env = EnvironmentModifications()
+ run_env = EnvironmentModifications()
+
+ set_compiler_environment_variables(pkg, spack_env)
+ set_build_environment_variables(pkg, spack_env)
+
# If a user makes their own package repo, e.g.
# spack.repos.mystuff.libelf.Libelf, and they inherit from
# an existing class like spack.repos.original.libelf.Libelf,
@@ -285,12 +288,20 @@ def setup_package(pkg):
# Allow dependencies to modify the module
for dependency_spec in pkg.spec.traverse(root=False):
- dependency_spec.package.modify_module(pkg.module, dependency_spec, pkg.spec)
+ dpkg = dependency_spec.package
+ dpkg.setup_dependent_python_module(pkg.module, pkg.spec)
+
# Allow dependencies to set up environment as well
for dependency_spec in pkg.spec.traverse(root=False):
- dependency_spec.package.setup_dependent_environment(env, pkg.spec)
- validate(env, tty.warn)
- env.apply_modifications()
+ dpkg = dependency_spec.package
+ dpkg.setup_dependent_environment(spack_env, run_env, pkg.spec)
+
+ # Allow the package to apply some settings.
+ pkg.setup_environment(spack_env, run_env)
+
+ # Make sure nothing's strange about the Spack environment.
+ validate(spack_env, tty.warn)
+ spack_env.apply_modifications()
def fork(pkg, function):
diff --git a/lib/spack/spack/modules.py b/lib/spack/spack/modules.py
index 4e98d50001..05c93cd3e6 100644
--- a/lib/spack/spack/modules.py
+++ b/lib/spack/spack/modules.py
@@ -164,7 +164,8 @@ class EnvModule(object):
self.pkg.module, extendee_spec, self.spec)
# Package-specific environment modifications
- self.spec.package.setup_environment(env)
+ spack_env = EnvironmentModifications()
+ self.spec.package.setup_environment(spack_env, env)
# TODO : implement site-specific modifications and filters
if not env:
diff --git a/lib/spack/spack/package.py b/lib/spack/spack/package.py
index acad5a28f6..9d8ac87bd7 100644
--- a/lib/spack/spack/package.py
+++ b/lib/spack/spack/package.py
@@ -1002,56 +1002,120 @@ class Package(object):
return __import__(self.__class__.__module__,
fromlist=[self.__class__.__name__])
- def setup_environment(self, env):
- """
- Appends in `env` the list of environment modifications needed to use this package outside of spack.
+ def setup_environment(self, spack_env, run_env):
+ """Set up the compile and runtime environemnts for a package.
- Default implementation does nothing, but this can be overridden if the package needs a particular environment.
+ `spack_env` and `run_env` are `EnvironmentModifications`
+ objects. Package authors can call methods on them to alter
+ the environment within Spack and at runtime.
- Example :
+ Both `spack_env` and `run_env` are applied within the build
+ process, before this package's `install()` method is called.
+
+ Modifications in `run_env` will *also* be added to the
+ generated environment modules for this package.
+
+ Default implementation does nothing, but this can be
+ overridden if the package needs a particular environment.
- 1. A lot of Qt extensions need `QTDIR` set. This can be used to do that.
+ Examples:
+
+ 1. Qt extensions need `QTDIR` set.
Args:
- env: list of environment modifications to be updated
+ spack_env (EnvironmentModifications): list of
+ modifications to be applied when this package is built
+ within Spack.
+
+ run_env (EnvironmentModifications): list of environment
+ changes to be applied when this package is run outside
+ of Spack.
+
"""
pass
- def setup_dependent_environment(self, env, dependent_spec):
- """
- Called before the install() method of dependents.
- Appends in `env` the list of environment modifications needed by dependents (or extensions) during the
- installation of a package. The default implementation delegates to `setup_environment`, but can be overridden
- if the modifications to the environment happen to be different from the one needed to use the package outside
- of spack.
+ def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
+ """Set up the environment of packages that depend on this one.
+
+ This is similar to `setup_environment`, but it is used to
+ modify the compile and runtime environments of packages that
+ *depend* on this one. This gives packages like Python and
+ others that follow the extension model a way to implement
+ common environment or compile-time settings for dependencies.
- This is useful if there are some common steps to installing all extensions for a certain package.
+ By default, this delegates to self.setup_environment()
Example :
- 1. Installing python modules generally requires `PYTHONPATH` to point to the lib/pythonX.Y/site-packages
- directory in the module's install prefix. This could set that variable.
+ 1. Installing python modules generally requires
+ `PYTHONPATH` to point to the lib/pythonX.Y/site-packages
+ directory in the module's install prefix. This could
+ set that variable.
Args:
- env: list of environment modifications to be updated
- dependent_spec: dependent (or extension) of this spec
- """
- self.setup_environment(env)
- def modify_module(self, module, spec, dependent_spec):
+ spack_env (EnvironmentModifications): list of
+ modifications to be applied when the dependent package
+ is bulit within Spack.
+
+ run_env (EnvironmentModifications): list of environment
+ changes to be applied when the dependent package is
+ run outside of Spack.
+
+ dependent_spec (Spec): The spec of the dependent package
+ about to be built. This allows the extendee (self) to
+ query the dependent's state. Note that *this*
+ package's spec is available as `self.spec`.
+
+ This is useful if there are some common steps to installing
+ all extensions for a certain package.
+
"""
+ self.setup_environment(spack_env, run_env)
+
+
+ def setup_dependent_python_module(self, module, dependent_spec):
+ """Set up Python module-scope variables for dependent packages.
+
Called before the install() method of dependents.
- Default implementation does nothing, but this can be overridden by an extendable package to set up the module of
- its extensions. This is useful if there are some common steps to installing all extensions for a
- certain package.
+ Default implementation does nothing, but this can be
+ overridden by an extendable package to set up the module of
+ its extensions. This is useful if there are some common steps
+ to installing all extensions for a certain package.
Example :
- 1. Extensions often need to invoke the 'python' interpreter from the Python installation being extended.
- This routine can put a 'python' Executable object in the module scope for the extension package to simplify
- extension installs.
+ 1. Extensions often need to invoke the `python`
+ interpreter from the Python installation being
+ extended. This routine can put a 'python' Executable
+ object in the module scope for the extension package to
+ simplify extension installs.
+
+ 2. MPI compilers could set some variables in the
+ dependent's scope that point to `mpicc`, `mpicxx`,
+ etc., allowing them to be called by common names
+ regardless of which MPI is used.
+
+ 3. BLAS/LAPACK implementations can set some variables
+ indicating the path to their libraries, since these
+ paths differ by BLAS/LAPACK implementation.
+
+ Args:
+
+ module (module): The Python `module` object of the
+ dependent package. Packages can use this to set
+ module-scope variables for the dependent to use.
+
+ dependent_spec (Spec): The spec of the dependent package
+ about to be built. This allows the extendee (self) to
+ query the dependent's state. Note that *this*
+ package's spec is available as `self.spec`.
+
+ This is useful if there are some common steps to installing
+ all extensions for a certain package.
+
"""
pass