Separate setting build environment and run environment in packages (#11115)

* Methods setting the environment now do it separately for build and run

Before this commit the `*_environment` methods were setting
modifications to both the build-time and run-time environment
simultaneously. This might cause issues as the two environments
inherently rely on different preconditions:

1. The build-time environment is set before building a package, thus
the package prefix doesn't exist and can't be inspected

2. The run-time environment instead is set assuming the target package
has been already installed

Here we split each of these functions into two: one setting the
build-time environment, one the run-time.

We also adopt a fallback strategy that inspects for old methods and
executes them as before, but prints a deprecation warning to tty. This
permits to port packages to use the new methods in a distributed way,
rather than having to modify all the packages at once.

* Added a test that fails if any package uses the old API

Marked the test xfail for now as we have a lot of packages in that
state.

* Added a test to check that a package modified by a PR is up to date

This test can be used any time we deprecate a method call to ensure
that during the first modification of the package we update also
the deprecated calls.

* Updated documentation
This commit is contained in:
Massimiliano Culpo 2019-10-17 19:17:21 +02:00 committed by Greg Becker
parent cf9de058aa
commit 9ddc98e46a
14 changed files with 337 additions and 219 deletions

View File

@ -303,8 +303,7 @@ content of the module files generated by Spack. The first one:
.. code-block:: python
def setup_environment(self, spack_env, run_env):
"""Set up the compile and runtime environments for a package."""
def setup_run_environment(self, env):
pass
can alter the content of the module file associated with the same package where it is overridden.
@ -312,16 +311,15 @@ The second method:
.. code-block:: python
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
"""Set up the environment of packages that depend on this one"""
def setup_dependent_run_environment(self, env, dependent_spec):
pass
can instead inject run-time environment modifications in the module files of packages
that depend on it. In both cases you need to fill ``run_env`` with the desired
list of environment modifications.
.. note::
The ``r`` package and callback APIs
.. admonition:: The ``r`` package and callback APIs
An example in which it is crucial to override both methods
is given by the ``r`` package. This package installs libraries and headers
in non-standard locations and it is possible to prepend the appropriate directory
@ -336,14 +334,14 @@ list of environment modifications.
with the following snippet:
.. literalinclude:: _spack_root/var/spack/repos/builtin/packages/r/package.py
:pyobject: R.setup_environment
:pyobject: R.setup_run_environment
The ``r`` package also knows which environment variable should be modified
to make language extensions provided by other packages available, and modifies
it appropriately in the override of the second method:
.. literalinclude:: _spack_root/var/spack/repos/builtin/packages/r/package.py
:pyobject: R.setup_dependent_environment
:pyobject: R.setup_dependent_run_environment
.. _modules-yaml:

View File

@ -2032,55 +2032,58 @@ appear in the package file (or in this case, in the list).
.. _setup-dependent-environment:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
``setup_dependent_environment()``
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Influence how dependents are built or run
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Spack provides a mechanism for dependencies to provide variables that
can be used in their dependents' build. Any package can declare a
``setup_dependent_environment()`` function, and this function will be
called before the ``install()`` method of any dependent packages.
This allows dependencies to set up environment variables and other
properties to be used by dependents.
The function declaration should look like this:
Spack provides a mechanism for dependencies to influence the
environment of their dependents by overriding the
:meth:`setup_dependent_run_environment <spack.package.PackageBase.setup_dependent_run_environment>`
or the
:meth:`setup_dependent_build_environment <spack.package.PackageBase.setup_dependent_build_environment>`
methods.
The Qt package, for instance, uses this call:
.. literalinclude:: _spack_root/var/spack/repos/builtin/packages/qt/package.py
:pyobject: Qt.setup_dependent_environment
:pyobject: Qt.setup_dependent_build_environment
:linenos:
Here, the Qt package sets the ``QTDIR`` environment variable so that
packages that depend on a particular Qt installation will find it.
The arguments to this function are:
* **spack_env**: List of environment modifications to be applied when
the dependent package is built within Spack.
* **run_env**: List of environment modifications to be applied when
the dependent package is run outside of Spack. These are added to the
resulting module file.
* **dependent_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``.
A good example of using these is in the Python package:
to set the ``QTDIR`` environment variable so that packages
that depend on a particular Qt installation will find it.
Another good example of how a dependency can influence
the build environment of dependents is the Python package:
.. literalinclude:: _spack_root/var/spack/repos/builtin/packages/python/package.py
:pyobject: Python.setup_dependent_environment
:pyobject: Python.setup_dependent_build_environment
:linenos:
The first thing that happens here is that the ``python`` command is
inserted into module scope of the dependent. This allows most python
packages to have a very simple install method, like this:
In the method above it is ensured that any package that depends on Python
will have the ``PYTHONPATH``, ``PYTHONHOME`` and ``PATH`` environment
variables set appropriately before starting the installation. To make things
even simpler the ``python setup.py`` command is also inserted into the module
scope of dependents by overriding a third method called
:meth:`setup_dependent_package <spack.package.PackageBase.setup_dependent_package>`
:
.. literalinclude:: _spack_root/var/spack/repos/builtin/packages/python/package.py
:pyobject: Python.setup_dependent_package
:linenos:
This allows most python packages to have a very simple install procedure,
like the following:
.. code-block:: python
def install(self, spec, prefix):
python('setup.py', 'install', '--prefix={0}'.format(prefix))
setup_py('install', '--prefix={0}'.format(prefix))
Finally the Python package takes also care of the modifications to ``PYTHONPATH``
to allow dependencies to run correctly:
.. literalinclude:: _spack_root/var/spack/repos/builtin/packages/python/package.py
:pyobject: Python.setup_dependent_run_environment
:linenos:
Python's ``setup_dependent_environment`` method also sets up some
other variables, creates a directory, and sets up the ``PYTHONPATH``
so that dependent packages can find their dependencies at build time.
.. _packaging_conflicts:

View File

@ -90,21 +90,23 @@ like py-numpy, Spack's ``python`` package will add it to ``PYTHONPATH``
so it is available at build time; this is required because the default setup
that spack does is not sufficient for python to import modules.
To provide environment setup for a dependent, a package can implement the
:py:func:`setup_dependent_environment <spack.package.PackageBase.setup_dependent_environment>`
function. This function takes as a parameter a :py:class:`EnvironmentModifications <spack.util.environment.EnvironmentModifications>`
Any package can override the
:py:func:`setup_dependent_build_environment <spack.package.PackageBase.setup_dependent_build_environment>`
method to setup the build environment for a dependent.
This method takes as an argument a :py:class:`EnvironmentModifications <spack.util.environment.EnvironmentModifications>`
object which includes convenience methods to update the environment. For
example, an MPI implementation can set ``MPICC`` for packages that depend on it:
.. code-block:: python
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
spack_env.set('MPICC', join_path(self.prefix.bin, 'mpicc'))
def setup_dependent_build_environment(self, env, dependent_spec):
env.set('MPICC', join_path(self.prefix.bin, 'mpicc'))
In this case packages that depend on ``mpi`` will have ``MPICC`` defined in
their environment when they build. This section is focused on modifying the
build-time environment represented by ``spack_env``, but it's worth noting that
modifications to ``run_env`` are included in Spack's automatically-generated
their environment when they build. This section is focused on setting up the
build-time environment but it's worth noting that a similar method called
:py:func:`setup_dependent_run_environment <spack.package.PackageBase.setup_dependent_run_environment>`
can be used to code modifications that will be included in Spack's automatically-generated
module files.
We can practice by editing the ``mpich`` package to set the ``MPICC``
@ -118,17 +120,17 @@ Once you're finished, the method should look like this:
.. code-block:: python
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
spack_env.set('MPICC', join_path(self.prefix.bin, 'mpicc'))
spack_env.set('MPICXX', join_path(self.prefix.bin, 'mpic++'))
spack_env.set('MPIF77', join_path(self.prefix.bin, 'mpif77'))
spack_env.set('MPIF90', join_path(self.prefix.bin, 'mpif90'))
def setup_dependent_build_environment(self, env, dependent_spec):
env.set('MPICC', join_path(self.prefix.bin, 'mpicc'))
env.set('MPICXX', join_path(self.prefix.bin, 'mpic++'))
env.set('MPIF77', join_path(self.prefix.bin, 'mpif77'))
env.set('MPIF90', join_path(self.prefix.bin, 'mpif90'))
spack_env.set('MPICH_CC', spack_cc)
spack_env.set('MPICH_CXX', spack_cxx)
spack_env.set('MPICH_F77', spack_f77)
spack_env.set('MPICH_F90', spack_fc)
spack_env.set('MPICH_FC', spack_fc)
env.set('MPICH_CC', spack_cc)
env.set('MPICH_CXX', spack_cxx)
env.set('MPICH_F77', spack_f77)
env.set('MPICH_F90', spack_fc)
env.set('MPICH_FC', spack_fc)
At this point we can, for instance, install ``netlib-scalapack`` with
``mpich``:
@ -155,25 +157,32 @@ set to the correct value.
Set environment variables in your own package
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Packages can modify their own build-time environment by implementing the
:py:func:`setup_environment <spack.package.PackageBase.setup_environment>` function.
For ``qt`` this looks like:
Packages can override the
:py:func:`setup_build_environment <spack.package.PackageBase.setup_build_environment>`
or the
:py:func:`setup_run_environment <spack.package.PackageBase.setup_run_environment>`
methods to modify their own build-time or run-time environment respectively.
An example of a package that overrides both methods is ``qt``:
.. code-block:: python
def setup_environment(self, spack_env, run_env):
spack_env.set('MAKEFLAGS', '-j{0}'.format(make_jobs))
run_env.set('QTDIR', self.prefix)
def setup_build_environment(self, env):
env.set('MAKEFLAGS', '-j{0}'.format(make_jobs))
When ``qt`` builds, ``MAKEFLAGS`` will be defined in the environment.
def setup_run_environment(self, env):
env.set('QTDIR', self.prefix)
To contrast with ``qt``'s :py:func:`setup_dependent_environment <spack.package.PackageBase.setup_dependent_environment>`
When ``qt`` builds, ``MAKEFLAGS`` will be defined in the environment. Likewise, when a
module file is created for ``qt`` it will contain commands to define ``QTDIR`` appropriately.
To contrast with ``qt``'s
:py:func:`setup_dependent_build_environment <spack.package.PackageBase.setup_dependent_build_environment>`
function:
.. code-block:: python
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
spack_env.set('QTDIR', self.prefix)
def setup_dependent_build_environment(self, env, dependent_spec):
env.set('QTDIR', self.prefix)
Let's see how it works by completing the ``elpa`` package:
@ -185,16 +194,16 @@ In the end your method should look like:
.. code-block:: python
def setup_environment(self, spack_env, run_env):
def setup_build_environment(self, env):
spec = self.spec
spack_env.set('CC', spec['mpi'].mpicc)
spack_env.set('FC', spec['mpi'].mpifc)
spack_env.set('CXX', spec['mpi'].mpicxx)
spack_env.set('SCALAPACK_LDFLAGS', spec['scalapack'].libs.joined())
env.set('CC', spec['mpi'].mpicc)
env.set('FC', spec['mpi'].mpifc)
env.set('CXX', spec['mpi'].mpicxx)
env.set('SCALAPACK_LDFLAGS', spec['scalapack'].libs.joined())
spack_env.append_flags('LDFLAGS', spec['lapack'].libs.search_flags)
spack_env.append_flags('LIBS', spec['lapack'].libs.link_flags)
env.append_flags('LDFLAGS', spec['lapack'].libs.search_flags)
env.append_flags('LIBS', spec['lapack'].libs.link_flags)
At this point it's possible to proceed with the installation of ``elpa ^mpich``

View File

@ -673,35 +673,26 @@ def load_external_modules(pkg):
def setup_package(pkg, dirty):
"""Execute all environment setup routines."""
spack_env = EnvironmentModifications()
run_env = EnvironmentModifications()
build_env = EnvironmentModifications()
if not dirty:
clean_environment()
set_compiler_environment_variables(pkg, spack_env)
set_build_environment_variables(pkg, spack_env, dirty)
pkg.architecture.platform.setup_platform_environment(pkg, spack_env)
set_compiler_environment_variables(pkg, build_env)
set_build_environment_variables(pkg, build_env, dirty)
pkg.architecture.platform.setup_platform_environment(pkg, build_env)
# traverse in postorder so package can use vars from its dependencies
spec = pkg.spec
for dspec in pkg.spec.traverse(order='post', root=False,
deptype=('build', 'test')):
spkg = dspec.package
set_module_variables_for_package(spkg)
build_env.extend(
modifications_from_dependencies(pkg.spec, context='build')
)
# Allow dependencies to modify the module
dpkg = dspec.package
dpkg.setup_dependent_package(pkg.module, spec)
dpkg.setup_dependent_environment(spack_env, run_env, spec)
if (not dirty) and (not spack_env.is_unset('CPATH')):
if (not dirty) and (not build_env.is_unset('CPATH')):
tty.debug("A dependency has updated CPATH, this may lead pkg-config"
" to assume that the package is part of the system"
" includes and omit it when invoked with '--cflags'.")
set_module_variables_for_package(pkg)
pkg.setup_environment(spack_env, run_env)
pkg.setup_build_environment(build_env)
# Loading modules, in particular if they are meant to be used outside
# of Spack, can change environment variables that are relevant to the
@ -711,7 +702,7 @@ def setup_package(pkg, dirty):
# unnecessary. Modules affecting these variables will be overwritten anyway
with preserve_environment('CC', 'CXX', 'FC', 'F77'):
# All module loads that otherwise would belong in previous
# functions have to occur after the spack_env object has its
# functions have to occur after the build_env object has its
# modifications applied. Otherwise the environment modifications
# could undo module changes, such as unsetting LD_LIBRARY_PATH
# after a module changes it.
@ -727,8 +718,39 @@ def setup_package(pkg, dirty):
load_external_modules(pkg)
# Make sure nothing's strange about the Spack environment.
validate(spack_env, tty.warn)
spack_env.apply_modifications()
validate(build_env, tty.warn)
build_env.apply_modifications()
def modifications_from_dependencies(spec, context):
"""Returns the environment modifications that are required by
the dependencies of a spec and also applies modifications
to this spec's package at module scope, if need be.
Args:
spec (Spec): spec for which we want the modifications
context (str): either 'build' for build-time modifications or 'run'
for run-time modifications
"""
env = EnvironmentModifications()
pkg = spec.package
# Maps the context to deptype and method to be called
deptype_and_method = {
'build': (('build', 'link', 'test'),
'setup_dependent_build_environment'),
'run': (('link', 'run'), 'setup_dependent_run_environment')
}
deptype, method = deptype_and_method[context]
for dspec in spec.traverse(order='post', root=False, deptype=deptype):
dpkg = dspec.package
set_module_variables_for_package(dpkg)
# Allow dependencies to modify the module
dpkg.setup_dependent_package(pkg.module, spec)
getattr(dpkg, method)(env, spec)
return env
def fork(pkg, function, dirty, fake):

View File

@ -93,12 +93,11 @@ def is_package(f):
for file_pattern, error_dict in pattern_exemptions.items())
def changed_files(args):
def changed_files(base=None, untracked=True, all_files=False):
"""Get list of changed files in the Spack repository."""
git = which('git', required=True)
base = args.base
if base is None:
base = os.environ.get('TRAVIS_BRANCH', 'develop')
@ -114,11 +113,11 @@ def changed_files(args):
]
# Add new files that are untracked
if args.untracked:
if untracked:
git_args.append(['ls-files', '--exclude-standard', '--other'])
# add everything if the user asked for it
if args.all:
if all_files:
git_args.append(['ls-files', '--exclude-standard'])
excludes = [os.path.realpath(f) for f in exclude_directories]
@ -246,7 +245,7 @@ def prefix_relative(path):
with working_dir(spack.paths.prefix):
if not file_list:
file_list = changed_files(args)
file_list = changed_files(args.base, args.untracked, args.all)
print('=======================================================')
print('flake8: running flake8 code checks on spack.')

View File

@ -634,23 +634,16 @@ def environment_modifications(self):
exclude=spack.util.environment.is_system_path
)
# Modifications that are coded at package level
_ = spack.util.environment.EnvironmentModifications()
# TODO : the code down below is quite similar to
# TODO : build_environment.setup_package and needs to be factored out
# TODO : to a single place
# Let the extendee/dependency modify their extensions/dependencies
# before asking for package-specific modifications
for item in dependencies(self.spec, 'all'):
package = self.spec[item.name].package
build_environment.set_module_variables_for_package(package)
package.setup_dependent_package(
self.spec.package.module, self.spec
env.extend(
build_environment.modifications_from_dependencies(
self.spec, context='run'
)
package.setup_dependent_environment(_, env, self.spec)
)
# Package specific modifications
build_environment.set_module_variables_for_package(self.spec.package)
self.spec.package.setup_environment(_, env)
self.spec.package.setup_run_environment(env)
# Modifications required from modules.yaml
env.extend(self.conf.env)

View File

@ -45,6 +45,7 @@
import spack.multimethod
import spack.repo
import spack.url
import spack.util.environment
import spack.util.web
import spack.multimethod
import spack.binary_distribution as binary_distribution
@ -1951,68 +1952,108 @@ def build_system_flags(cls, name, flags):
"""
return (None, None, flags)
def setup_environment(self, spack_env, run_env):
"""Set up the compile and runtime environments for a package.
def _get_legacy_environment_method(self, method_name):
legacy_fn = getattr(self, method_name, None)
name_prefix = method_name.split('_environment')[0]
if legacy_fn:
msg = '[DEPRECATED METHOD]\n"{0}" ' \
'still defines the deprecated method "{1}" ' \
'[should be split into "{2}_build_environment" and ' \
'"{2}_run_environment"]'
tty.debug(msg.format(self.name, method_name, name_prefix))
return legacy_fn
``spack_env`` and ``run_env`` are ``EnvironmentModifications``
objects. Package authors can call methods on them to alter
the environment within Spack and at runtime.
def setup_build_environment(self, env):
"""Sets up the build environment for a package.
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.
Example:
1. Qt extensions need ``QTDIR`` set.
This method will be called before the current package prefix exists in
Spack's store.
Args:
spack_env (EnvironmentModifications): List of environment
modifications to be applied when this package is built
within Spack.
run_env (EnvironmentModifications): List of environment
modifications to be applied when this package is run outside
of Spack. These are added to the resulting module file.
env (EnvironmentModifications): environment modifications to be
applied when the package is built. Package authors can call
methods on it to alter the build environment.
"""
pass
legacy_fn = self._get_legacy_environment_method('setup_environment')
if legacy_fn:
_ = spack.util.environment.EnvironmentModifications()
legacy_fn(env, _)
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.
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 method could be used to set that variable.
def setup_run_environment(self, env):
"""Sets up the run environment for a package.
Args:
spack_env (EnvironmentModifications): List of environment
modifications to be applied when the dependent package is
built within Spack.
run_env (EnvironmentModifications): List of environment
modifications to be applied when the dependent package is
run outside of Spack. These are added to the resulting
module file.
dependent_spec (Spec): The spec of the dependent package
env (EnvironmentModifications): environment modifications to be
applied when the package is run. Package authors can call
methods on it to alter the run environment.
"""
legacy_fn = self._get_legacy_environment_method('setup_environment')
if legacy_fn:
_ = spack.util.environment.EnvironmentModifications()
legacy_fn(_, env)
def setup_dependent_build_environment(self, env, dependent_spec):
"""Sets up the build environment of packages that depend on this one.
This is similar to ``setup_build_environment``, but it is used to
modify the build 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 method will be called before the dependent package prefix exists
in Spack's store.
Examples:
1. Installing python modules generally requires ``PYTHONPATH``
to point to the ``lib/pythonX.Y/site-packages`` directory in the
module's install prefix. This method could be used to set that
variable.
Args:
env (EnvironmentModifications): environment modifications to be
applied when the dependent package is built. Package authors
can call methods on it to alter the build environment.
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``.
available as ``self.spec``
"""
pass
legacy_fn = self._get_legacy_environment_method(
'setup_dependent_environment'
)
if legacy_fn:
_ = spack.util.environment.EnvironmentModifications()
legacy_fn(env, _, dependent_spec)
def setup_dependent_run_environment(self, env, dependent_spec):
"""Sets up the run environment of packages that depend on this one.
This is similar to ``setup_run_environment``, but it is used to
modify the run 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 run-time settings
for dependencies.
Args:
env (EnvironmentModifications): environment modifications to be
applied when the dependent package is run. Package authors
can call methods on it to alter the build environment.
dependent_spec (Spec): The spec of the dependent package
about to be run. This allows the extendee (self) to query
the dependent's state. Note that *this* package's spec is
available as ``self.spec``
"""
legacy_fn = self._get_legacy_environment_method(
'setup_dependent_environment'
)
if legacy_fn:
_ = spack.util.environment.EnvironmentModifications()
legacy_fn(_, env, dependent_spec)
def setup_dependent_package(self, module, dependent_spec):
"""Set up Python module-scope variables for dependent packages.

View File

@ -4,6 +4,7 @@
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
"""This test does sanity checks on Spack's builtin package database."""
import os.path
import re
import pytest
@ -11,6 +12,10 @@
import spack.fetch_strategy
import spack.paths
import spack.repo
import spack.util.executable as executable
# A few functions from this module are used to
# do sanity checks only on packagess modified by a PR
import spack.cmd.flake8 as flake8
import spack.util.crypto as crypto
@ -134,3 +139,48 @@ def invalid_sha256_digest(fetcher):
)
assert [] == errors
@pytest.mark.xfail
def test_api_for_build_and_run_environment():
"""Ensure that every package uses the correct API to set build and
run environment, and not the old one.
"""
failing = []
for pkg in spack.repo.path.all_packages():
add_to_list = (hasattr(pkg, 'setup_environment') or
hasattr(pkg, 'setup_dependent_environment'))
if add_to_list:
failing.append(pkg)
msg = ('there are {0} packages using the old API to set build '
'and run environment [{1}]')
assert not failing, msg.format(
len(failing), ','.join(x.name for x in failing)
)
@pytest.mark.skipif(
not executable.which('git'), reason='requires git to be installed'
)
def test_prs_update_old_api():
"""Ensures that every package modified in a PR doesn't contain
deprecated calls to any method.
"""
changed_package_files = [
x for x in flake8.changed_files() if flake8.is_package(x)
]
failing = []
for file in changed_package_files:
name = os.path.basename(os.path.dirname(file))
pkg = spack.repo.get(name)
# Check for old APIs
failed = (hasattr(pkg, 'setup_environment') or
hasattr(pkg, 'setup_dependent_environment'))
if failed:
failing.append(pkg)
msg = 'there are {0} packages still using old APIs in this PR [{1}]'
assert not failing, msg.format(
len(failing), ','.join(x.name for x in failing)
)

View File

@ -20,6 +20,6 @@ class DocbookXml(Package):
def install(self, spec, prefix):
install_tree('.', prefix)
def setup_environment(self, spack_env, run_env):
def setup_run_environment(self, env):
catalog = os.path.join(self.prefix, 'catalog.xml')
run_env.set('XML_CATALOG_FILES', catalog, separator=' ')
env.set('XML_CATALOG_FILES', catalog, separator=' ')

View File

@ -61,16 +61,16 @@ def headers(self):
build_directory = 'spack-build'
def setup_environment(self, spack_env, run_env):
def setup_build_environment(self, env):
spec = self.spec
spack_env.set('CC', spec['mpi'].mpicc)
spack_env.set('FC', spec['mpi'].mpifc)
spack_env.set('CXX', spec['mpi'].mpicxx)
env.set('CC', spec['mpi'].mpicc)
env.set('FC', spec['mpi'].mpifc)
env.set('CXX', spec['mpi'].mpicxx)
spack_env.append_flags('LDFLAGS', spec['lapack'].libs.search_flags)
spack_env.append_flags('LIBS', spec['lapack'].libs.link_flags)
spack_env.set('SCALAPACK_LDFLAGS', spec['scalapack'].libs.joined())
env.append_flags('LDFLAGS', spec['lapack'].libs.search_flags)
env.append_flags('LIBS', spec['lapack'].libs.link_flags)
env.set('SCALAPACK_LDFLAGS', spec['scalapack'].libs.joined())
def configure_args(self):
# TODO: set optimum flags for platform+compiler combo, see

View File

@ -110,29 +110,28 @@ class Mpich(AutotoolsPackage):
conflicts('pmi=pmi2', when='device=ch3 netmod=ofi')
conflicts('pmi=pmix', when='device=ch3')
def setup_environment(self, spack_env, run_env):
# mpich configure fails when F90 and F90FLAGS are set
spack_env.unset('F90')
spack_env.unset('F90FLAGS')
def setup_build_environment(self, env):
env.unset('F90')
env.unset('F90FLAGS')
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
def setup_dependent_build_environment(self, env, dependent_spec):
# On Cray, the regular compiler wrappers *are* the MPI wrappers.
if 'platform=cray' in self.spec:
spack_env.set('MPICC', spack_cc)
spack_env.set('MPICXX', spack_cxx)
spack_env.set('MPIF77', spack_fc)
spack_env.set('MPIF90', spack_fc)
env.set('MPICC', spack_cc)
env.set('MPICXX', spack_cxx)
env.set('MPIF77', spack_fc)
env.set('MPIF90', spack_fc)
else:
spack_env.set('MPICC', join_path(self.prefix.bin, 'mpicc'))
spack_env.set('MPICXX', join_path(self.prefix.bin, 'mpic++'))
spack_env.set('MPIF77', join_path(self.prefix.bin, 'mpif77'))
spack_env.set('MPIF90', join_path(self.prefix.bin, 'mpif90'))
env.set('MPICC', join_path(self.prefix.bin, 'mpicc'))
env.set('MPICXX', join_path(self.prefix.bin, 'mpic++'))
env.set('MPIF77', join_path(self.prefix.bin, 'mpif77'))
env.set('MPIF90', join_path(self.prefix.bin, 'mpif90'))
spack_env.set('MPICH_CC', spack_cc)
spack_env.set('MPICH_CXX', spack_cxx)
spack_env.set('MPICH_F77', spack_f77)
spack_env.set('MPICH_F90', spack_fc)
spack_env.set('MPICH_FC', spack_fc)
env.set('MPICH_CC', spack_cc)
env.set('MPICH_CXX', spack_cxx)
env.set('MPICH_F77', spack_f77)
env.set('MPICH_F90', spack_fc)
env.set('MPICH_FC', spack_fc)
def setup_dependent_package(self, module, dependent_spec):
if 'platform=cray' in self.spec:

View File

@ -183,7 +183,7 @@ def patch(self):
r'\1setup.py\2 --no-user-cfg \3\6'
)
def setup_environment(self, spack_env, run_env):
def setup_build_environment(self, env):
spec = self.spec
# TODO: The '--no-user-cfg' option for Python installation is only in
@ -195,7 +195,7 @@ def setup_environment(self, spack_env, run_env):
'user configurations are present.').format(self.version))
# Need this to allow python build to find the Python installation.
spack_env.set('MACOSX_DEPLOYMENT_TARGET', platform.mac_ver()[0])
env.set('MACOSX_DEPLOYMENT_TARGET', platform.mac_ver()[0])
def configure_args(self):
spec = self.spec
@ -672,7 +672,7 @@ def site_packages_dir(self):
def easy_install_file(self):
return join_path(self.site_packages_dir, "easy-install.pth")
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
def setup_dependent_build_environment(self, env, dependent_spec):
"""Set PYTHONPATH to include the site-packages directory for the
extension and any other python extensions it depends on."""
@ -680,11 +680,11 @@ def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
# python is found in the build environment. This to prevent cases
# where a system provided python is run against the standard libraries
# of a Spack built python. See issue #7128
spack_env.set('PYTHONHOME', self.home)
env.set('PYTHONHOME', self.home)
path = os.path.dirname(self.command.path)
if not is_system_path(path):
spack_env.prepend_path('PATH', path)
env.prepend_path('PATH', path)
python_paths = []
for d in dependent_spec.traverse(
@ -694,12 +694,13 @@ def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
self.site_packages_dir))
pythonpath = ':'.join(python_paths)
spack_env.set('PYTHONPATH', pythonpath)
env.set('PYTHONPATH', pythonpath)
def setup_dependent_run_environment(self, env, dependent_spec):
# For run time environment set only the path for
# dependent_spec and prepend it to PYTHONPATH
if dependent_spec.package.extends(self.spec):
run_env.prepend_path('PYTHONPATH', join_path(
env.prepend_path('PYTHONPATH', join_path(
dependent_spec.prefix, self.site_packages_dir))
def setup_dependent_package(self, module, dependent_spec):

View File

@ -206,12 +206,14 @@ def url_for_version(self, version):
return url
def setup_environment(self, spack_env, run_env):
spack_env.set('MAKEFLAGS', '-j{0}'.format(make_jobs))
run_env.set('QTDIR', self.prefix)
def setup_build_environment(self, env):
env.set('MAKEFLAGS', '-j{0}'.format(make_jobs))
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
spack_env.set('QTDIR', self.prefix)
def setup_run_environment(self, env):
env.set('QTDIR', self.prefix)
def setup_dependent_build_environment(self, env, dependent_spec):
env.set('QTDIR', self.prefix)
def setup_dependent_package(self, module, dependent_spec):
module.qmake = Executable(join_path(self.spec.prefix.bin, 'qmake'))

View File

@ -168,7 +168,7 @@ def copy_makeconf(self):
def r_lib_dir(self):
return join_path('rlib', 'R', 'library')
def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
def setup_dependent_build_environment(self, env, dependent_spec):
# Set R_LIBS to include the library dir for the
# extension and any other R extensions it depends on.
r_libs_path = []
@ -178,27 +178,28 @@ def setup_dependent_environment(self, spack_env, run_env, dependent_spec):
r_libs_path.append(join_path(d.prefix, self.r_lib_dir))
r_libs_path = ':'.join(r_libs_path)
spack_env.set('R_LIBS', r_libs_path)
spack_env.set('R_MAKEVARS_SITE',
join_path(self.etcdir, 'Makeconf.spack'))
env.set('R_LIBS', r_libs_path)
env.set('R_MAKEVARS_SITE',
join_path(self.etcdir, 'Makeconf.spack'))
# Use the number of make_jobs set in spack. The make program will
# determine how many jobs can actually be started.
spack_env.set('MAKEFLAGS', '-j{0}'.format(make_jobs))
env.set('MAKEFLAGS', '-j{0}'.format(make_jobs))
def setup_dependent_run_environment(self, env, dependent_spec):
# For run time environment set only the path for dependent_spec and
# prepend it to R_LIBS
if dependent_spec.package.extends(self.spec):
run_env.prepend_path('R_LIBS', join_path(
env.prepend_path('R_LIBS', join_path(
dependent_spec.prefix, self.r_lib_dir))
def setup_environment(self, spack_env, run_env):
run_env.prepend_path('LIBRARY_PATH',
join_path(self.prefix, 'rlib', 'R', 'lib'))
run_env.prepend_path('LD_LIBRARY_PATH',
join_path(self.prefix, 'rlib', 'R', 'lib'))
run_env.prepend_path('CPATH',
join_path(self.prefix, 'rlib', 'R', 'include'))
def setup_run_environment(self, env):
env.prepend_path('LIBRARY_PATH',
join_path(self.prefix, 'rlib', 'R', 'lib'))
env.prepend_path('LD_LIBRARY_PATH',
join_path(self.prefix, 'rlib', 'R', 'lib'))
env.prepend_path('CPATH',
join_path(self.prefix, 'rlib', 'R', 'include'))
def setup_dependent_package(self, module, dependent_spec):
"""Called before R modules' install() methods. In most cases,