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.
This commit is contained in:
@@ -84,7 +84,7 @@ def __call__(self, *args, **kwargs):
|
||||
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):
|
||||
|
@@ -164,7 +164,8 @@ def write(self):
|
||||
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:
|
||||
|
@@ -1002,56 +1002,120 @@ def module(self):
|
||||
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.
|
||||
|
||||
1. A lot of Qt extensions need `QTDIR` set. This can be used to do that.
|
||||
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.
|
||||
|
||||
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 useful if there are some common steps to installing all extensions for a certain package.
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
|
Reference in New Issue
Block a user