Unified environment modifications in config files (#14372)
* Unified environment modifications in config files fixes #13357 This commit factors all the code that is involved in the validation (schema) and parsing of environment modifications from configuration files in a single place. The factored out code is then used for module files and compiler configuration. Attributes were separated by dashes in `compilers.yaml` files and by underscores in `modules.yaml` files. This PR unifies the syntax on attributes separated by underscores. Unit testing of environment modifications in compilers has been refactored and simplified.
This commit is contained in:
parent
0f3ae864a5
commit
b9629c36f2
@ -929,11 +929,13 @@ in GNU Autotools. If all flags are set, the order is
|
|||||||
Compiler environment variables and additional RPATHs
|
Compiler environment variables and additional RPATHs
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
In the exceptional case a compiler requires setting special environment
|
Sometimes compilers require setting special environment variables to
|
||||||
variables, like an explicit library load path. These can bet set in an
|
operate correctly. Spack handles these cases by allowing custom environment
|
||||||
extra section in the compiler configuration (the supported environment
|
modifications in the ``environment`` attribute of the compiler configuration
|
||||||
modification commands are: ``set``, ``unset``, ``append-path``, and
|
section. See also the :ref:`configuration_environment_variables` section
|
||||||
``prepend-path``). The user can also specify additional ``RPATHs`` that the
|
of the configuration files docs for more information.
|
||||||
|
|
||||||
|
It is also possible to specify additional ``RPATHs`` that the
|
||||||
compiler will add to all executables generated by that compiler. This is
|
compiler will add to all executables generated by that compiler. This is
|
||||||
useful for forcing certain compilers to RPATH their own runtime libraries, so
|
useful for forcing certain compilers to RPATH their own runtime libraries, so
|
||||||
that executables will run without the need to set ``LD_LIBRARY_PATH``.
|
that executables will run without the need to set ``LD_LIBRARY_PATH``.
|
||||||
@ -950,28 +952,19 @@ that executables will run without the need to set ``LD_LIBRARY_PATH``.
|
|||||||
fc: /opt/gcc/bin/gfortran
|
fc: /opt/gcc/bin/gfortran
|
||||||
environment:
|
environment:
|
||||||
unset:
|
unset:
|
||||||
BAD_VARIABLE: # The colon is required but the value must be empty
|
- BAD_VARIABLE
|
||||||
set:
|
set:
|
||||||
GOOD_VARIABLE_NUM: 1
|
GOOD_VARIABLE_NUM: 1
|
||||||
GOOD_VARIABLE_STR: good
|
GOOD_VARIABLE_STR: good
|
||||||
prepend-path:
|
prepend_path:
|
||||||
PATH: /path/to/binutils
|
PATH: /path/to/binutils
|
||||||
append-path:
|
append_path:
|
||||||
LD_LIBRARY_PATH: /opt/gcc/lib
|
LD_LIBRARY_PATH: /opt/gcc/lib
|
||||||
extra_rpaths:
|
extra_rpaths:
|
||||||
- /path/to/some/compiler/runtime/directory
|
- /path/to/some/compiler/runtime/directory
|
||||||
- /path/to/some/other/compiler/runtime/directory
|
- /path/to/some/other/compiler/runtime/directory
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
The section `environment` is interpreted as an ordered dictionary, which
|
|
||||||
means two things. First, environment modification are applied in the order
|
|
||||||
they are specified in the configuration file. Second, you cannot express
|
|
||||||
environment modifications that require mixing different commands, i.e. you
|
|
||||||
cannot `set` one variable, than `prepend-path` to another one, and than
|
|
||||||
again `set` a third one.
|
|
||||||
|
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
Architecture specifiers
|
Architecture specifiers
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
@ -427,6 +427,33 @@ home directory, and ``~user`` will expand to a specified user's home
|
|||||||
directory. The ``~`` must appear at the beginning of the path, or Spack
|
directory. The ``~`` must appear at the beginning of the path, or Spack
|
||||||
will not expand it.
|
will not expand it.
|
||||||
|
|
||||||
|
.. _configuration_environment_variables:
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
Environment Modifications
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
Spack allows to prescribe custom environment modifications in a few places
|
||||||
|
within its configuration files. Every time these modifications are allowed
|
||||||
|
they are specified as a dictionary, like in the following example:
|
||||||
|
|
||||||
|
.. code-block:: yaml
|
||||||
|
|
||||||
|
environment:
|
||||||
|
set:
|
||||||
|
LICENSE_FILE: '/path/to/license'
|
||||||
|
unset:
|
||||||
|
- CPATH
|
||||||
|
- LIBRARY_PATH
|
||||||
|
append_path:
|
||||||
|
PATH: '/new/bin/dir'
|
||||||
|
|
||||||
|
The possible actions that are permitted are ``set``, ``unset``, ``append_path``,
|
||||||
|
``prepend_path`` and finally ``remove_path``. They all require a dictionary
|
||||||
|
of variable names mapped to the values used for the modification.
|
||||||
|
The only exception is ``unset`` that requires just a list of variable names.
|
||||||
|
No particular order is ensured on the execution of each of these modifications.
|
||||||
|
|
||||||
----------------------------
|
----------------------------
|
||||||
Seeing Spack's Configuration
|
Seeing Spack's Configuration
|
||||||
----------------------------
|
----------------------------
|
||||||
|
@ -39,7 +39,6 @@
|
|||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import types
|
import types
|
||||||
from six import iteritems
|
|
||||||
from six import StringIO
|
from six import StringIO
|
||||||
|
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
@ -52,6 +51,7 @@
|
|||||||
import spack.config
|
import spack.config
|
||||||
import spack.main
|
import spack.main
|
||||||
import spack.paths
|
import spack.paths
|
||||||
|
import spack.schema.environment
|
||||||
import spack.store
|
import spack.store
|
||||||
from spack.util.string import plural
|
from spack.util.string import plural
|
||||||
from spack.util.environment import (
|
from spack.util.environment import (
|
||||||
@ -342,21 +342,7 @@ def set_build_environment_variables(pkg, env, dirty):
|
|||||||
# Set environment variables if specified for
|
# Set environment variables if specified for
|
||||||
# the given compiler
|
# the given compiler
|
||||||
compiler = pkg.compiler
|
compiler = pkg.compiler
|
||||||
environment = compiler.environment
|
env.extend(spack.schema.environment.parse(compiler.environment))
|
||||||
|
|
||||||
for command, variable in iteritems(environment):
|
|
||||||
if command == 'set':
|
|
||||||
for name, value in iteritems(variable):
|
|
||||||
env.set(name, value)
|
|
||||||
elif command == 'unset':
|
|
||||||
for name, _ in iteritems(variable):
|
|
||||||
env.unset(name)
|
|
||||||
elif command == 'prepend-path':
|
|
||||||
for name, value in iteritems(variable):
|
|
||||||
env.prepend_path(name, value)
|
|
||||||
elif command == 'append-path':
|
|
||||||
for name, value in iteritems(variable):
|
|
||||||
env.append_path(name, value)
|
|
||||||
|
|
||||||
if compiler.extra_rpaths:
|
if compiler.extra_rpaths:
|
||||||
extra_rpaths = ':'.join(compiler.extra_rpaths)
|
extra_rpaths = ':'.join(compiler.extra_rpaths)
|
||||||
|
@ -28,26 +28,24 @@
|
|||||||
Each of the four classes needs to be sub-classed when implementing a new
|
Each of the four classes needs to be sub-classed when implementing a new
|
||||||
module type.
|
module type.
|
||||||
"""
|
"""
|
||||||
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import inspect
|
import inspect
|
||||||
import os.path
|
import os.path
|
||||||
import re
|
import re
|
||||||
import collections
|
|
||||||
|
|
||||||
import six
|
|
||||||
import llnl.util.filesystem
|
import llnl.util.filesystem
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
import spack.paths
|
|
||||||
import spack.build_environment as build_environment
|
import spack.build_environment as build_environment
|
||||||
import spack.util.environment
|
|
||||||
import spack.tengine as tengine
|
|
||||||
import spack.util.path
|
|
||||||
import spack.util.environment
|
|
||||||
import spack.error
|
import spack.error
|
||||||
import spack.util.spack_yaml as syaml
|
import spack.paths
|
||||||
|
import spack.schema.environment
|
||||||
|
import spack.tengine as tengine
|
||||||
|
import spack.util.environment
|
||||||
import spack.util.file_permissions as fp
|
import spack.util.file_permissions as fp
|
||||||
|
import spack.util.path
|
||||||
|
import spack.util.spack_yaml as syaml
|
||||||
|
|
||||||
|
|
||||||
#: config section for this file
|
#: config section for this file
|
||||||
@ -415,22 +413,7 @@ def env(self):
|
|||||||
"""List of environment modifications that should be done in the
|
"""List of environment modifications that should be done in the
|
||||||
module.
|
module.
|
||||||
"""
|
"""
|
||||||
env_mods = spack.util.environment.EnvironmentModifications()
|
return spack.schema.environment.parse(self.conf.get('environment', {}))
|
||||||
actions = self.conf.get('environment', {})
|
|
||||||
|
|
||||||
def process_arglist(arglist):
|
|
||||||
if method == 'unset':
|
|
||||||
for x in arglist:
|
|
||||||
yield (x,)
|
|
||||||
else:
|
|
||||||
for x in six.iteritems(arglist):
|
|
||||||
yield x
|
|
||||||
|
|
||||||
for method, arglist in actions.items():
|
|
||||||
for args in process_arglist(arglist):
|
|
||||||
getattr(env_mods, method)(*args)
|
|
||||||
|
|
||||||
return env_mods
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def suffixes(self):
|
def suffixes(self):
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
.. literalinclude:: _spack_root/lib/spack/spack/schema/compilers.py
|
.. literalinclude:: _spack_root/lib/spack/spack/schema/compilers.py
|
||||||
:lines: 13-
|
:lines: 13-
|
||||||
"""
|
"""
|
||||||
|
import spack.schema.environment
|
||||||
|
|
||||||
#: Properties for inclusion in other schemas
|
#: Properties for inclusion in other schemas
|
||||||
properties = {
|
properties = {
|
||||||
@ -68,50 +68,7 @@
|
|||||||
{'type': 'boolean'}
|
{'type': 'boolean'}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
'environment': {
|
'environment': spack.schema.environment.definition,
|
||||||
'type': 'object',
|
|
||||||
'default': {},
|
|
||||||
'additionalProperties': False,
|
|
||||||
'properties': {
|
|
||||||
'set': {
|
|
||||||
'type': 'object',
|
|
||||||
'patternProperties': {
|
|
||||||
# Variable name
|
|
||||||
r'\w[\w-]*': {
|
|
||||||
'anyOf': [{'type': 'string'},
|
|
||||||
{'type': 'number'}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'unset': {
|
|
||||||
'type': 'object',
|
|
||||||
'patternProperties': {
|
|
||||||
# Variable name
|
|
||||||
r'\w[\w-]*': {'type': 'null'}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'prepend-path': {
|
|
||||||
'type': 'object',
|
|
||||||
'patternProperties': {
|
|
||||||
# Variable name
|
|
||||||
r'\w[\w-]*': {
|
|
||||||
'anyOf': [{'type': 'string'},
|
|
||||||
{'type': 'number'}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'append-path': {
|
|
||||||
'type': 'object',
|
|
||||||
'patternProperties': {
|
|
||||||
# Variable name
|
|
||||||
r'\w[\w-]*': {
|
|
||||||
'anyOf': [{'type': 'string'},
|
|
||||||
{'type': 'number'}]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
'extra_rpaths': {
|
'extra_rpaths': {
|
||||||
'type': 'array',
|
'type': 'array',
|
||||||
'default': [],
|
'default': [],
|
||||||
|
58
lib/spack/spack/schema/environment.py
Normal file
58
lib/spack/spack/schema/environment.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
|
||||||
|
# Spack Project Developers. See the top-level COPYRIGHT file for details.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
|
||||||
|
"""Schema for environment modifications. Meant for inclusion in other
|
||||||
|
schemas.
|
||||||
|
"""
|
||||||
|
|
||||||
|
array_of_strings_or_num = {
|
||||||
|
'type': 'array', 'default': [], 'items':
|
||||||
|
{'anyOf': [{'type': 'string'}, {'type': 'number'}]}
|
||||||
|
}
|
||||||
|
|
||||||
|
dictionary_of_strings_or_num = {
|
||||||
|
'type': 'object', 'patternProperties':
|
||||||
|
{r'\w[\w-]*': {'anyOf': [{'type': 'string'}, {'type': 'number'}]}}
|
||||||
|
}
|
||||||
|
|
||||||
|
definition = {
|
||||||
|
'type': 'object',
|
||||||
|
'default': {},
|
||||||
|
'additionalProperties': False,
|
||||||
|
'properties': {
|
||||||
|
'set': dictionary_of_strings_or_num,
|
||||||
|
'unset': array_of_strings_or_num,
|
||||||
|
'prepend_path': dictionary_of_strings_or_num,
|
||||||
|
'append_path': dictionary_of_strings_or_num,
|
||||||
|
'remove_path': dictionary_of_strings_or_num
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def parse(config_obj):
|
||||||
|
"""Returns an EnvironmentModifications object containing the modifications
|
||||||
|
parsed from input.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config_obj: a configuration dictionary conforming to the
|
||||||
|
schema definition for environment modifications
|
||||||
|
"""
|
||||||
|
import spack.util.environment as ev
|
||||||
|
try:
|
||||||
|
from collections import Sequence # novm
|
||||||
|
except ImportError:
|
||||||
|
from collections.abc import Sequence # novm
|
||||||
|
|
||||||
|
env = ev.EnvironmentModifications()
|
||||||
|
for command, variable in config_obj.items():
|
||||||
|
# Distinguish between commands that take only a name as argument
|
||||||
|
# (e.g. unset) and commands that take a name and a value.
|
||||||
|
if isinstance(variable, Sequence):
|
||||||
|
for name in variable:
|
||||||
|
getattr(env, command)(name)
|
||||||
|
else:
|
||||||
|
for name, value in variable.items():
|
||||||
|
getattr(env, command)(name, value)
|
||||||
|
|
||||||
|
return env
|
@ -8,6 +8,8 @@
|
|||||||
.. literalinclude:: _spack_root/lib/spack/spack/schema/modules.py
|
.. literalinclude:: _spack_root/lib/spack/spack/schema/modules.py
|
||||||
:lines: 13-
|
:lines: 13-
|
||||||
"""
|
"""
|
||||||
|
import spack.schema.environment
|
||||||
|
|
||||||
|
|
||||||
#: Matches a spec or a multi-valued variant but not another
|
#: Matches a spec or a multi-valued variant but not another
|
||||||
#: valid keyword.
|
#: valid keyword.
|
||||||
@ -66,17 +68,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
'environment': {
|
'environment': spack.schema.environment.definition
|
||||||
'type': 'object',
|
|
||||||
'default': {},
|
|
||||||
'additionalProperties': False,
|
|
||||||
'properties': {
|
|
||||||
'set': dictionary_of_strings,
|
|
||||||
'unset': array_of_strings,
|
|
||||||
'prepend_path': dictionary_of_strings,
|
|
||||||
'append_path': dictionary_of_strings
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,7 +14,6 @@
|
|||||||
from spack.paths import build_env_path
|
from spack.paths import build_env_path
|
||||||
from spack.build_environment import dso_suffix, _static_to_shared_library
|
from spack.build_environment import dso_suffix, _static_to_shared_library
|
||||||
from spack.util.executable import Executable
|
from spack.util.executable import Executable
|
||||||
from spack.util.spack_yaml import syaml_dict, syaml_str
|
|
||||||
from spack.util.environment import EnvironmentModifications
|
from spack.util.environment import EnvironmentModifications
|
||||||
|
|
||||||
from llnl.util.filesystem import LibraryList, HeaderList
|
from llnl.util.filesystem import LibraryList, HeaderList
|
||||||
@ -65,6 +64,18 @@ def build_environment(working_env):
|
|||||||
del os.environ[name]
|
del os.environ[name]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture
|
||||||
|
def ensure_env_variables(config, mock_packages, monkeypatch, working_env):
|
||||||
|
"""Returns a function that takes a dictionary and updates os.environ
|
||||||
|
for the test lifetime accordingly. Plugs-in mock config and repo.
|
||||||
|
"""
|
||||||
|
def _ensure(env_mods):
|
||||||
|
for name, value in env_mods.items():
|
||||||
|
monkeypatch.setenv(name, value)
|
||||||
|
|
||||||
|
return _ensure
|
||||||
|
|
||||||
|
|
||||||
def test_static_to_shared_library(build_environment):
|
def test_static_to_shared_library(build_environment):
|
||||||
os.environ['SPACK_TEST_COMMAND'] = 'dump-args'
|
os.environ['SPACK_TEST_COMMAND'] = 'dump-args'
|
||||||
|
|
||||||
@ -119,79 +130,58 @@ def _set_wrong_cc(x):
|
|||||||
assert os.environ['ANOTHER_VAR'] == 'THIS_IS_SET'
|
assert os.environ['ANOTHER_VAR'] == 'THIS_IS_SET'
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures('config', 'mock_packages')
|
@pytest.mark.parametrize('initial,modifications,expected', [
|
||||||
def test_compiler_config_modifications(monkeypatch, working_env):
|
# Set and unset variables
|
||||||
s = spack.spec.Spec('cmake')
|
({'SOME_VAR_STR': '', 'SOME_VAR_NUM': '0'},
|
||||||
s.concretize()
|
{'set': {'SOME_VAR_STR': 'SOME_STR', 'SOME_VAR_NUM': 1}},
|
||||||
pkg = s.package
|
{'SOME_VAR_STR': 'SOME_STR', 'SOME_VAR_NUM': '1'}),
|
||||||
|
({'SOME_VAR_STR': ''},
|
||||||
|
{'unset': ['SOME_VAR_STR']},
|
||||||
|
{'SOME_VAR_STR': None}),
|
||||||
|
({}, # Set a variable that was not defined already
|
||||||
|
{'set': {'SOME_VAR_STR': 'SOME_STR'}},
|
||||||
|
{'SOME_VAR_STR': 'SOME_STR'}),
|
||||||
|
# Append and prepend to the same variable
|
||||||
|
({'EMPTY_PATH_LIST': '/path/middle'},
|
||||||
|
{'prepend_path': {'EMPTY_PATH_LIST': '/path/first'},
|
||||||
|
'append_path': {'EMPTY_PATH_LIST': '/path/last'}},
|
||||||
|
{'EMPTY_PATH_LIST': '/path/first:/path/middle:/path/last'}),
|
||||||
|
# Append and prepend from empty variables
|
||||||
|
({'EMPTY_PATH_LIST': '', 'SOME_VAR_STR': ''},
|
||||||
|
{'prepend_path': {'EMPTY_PATH_LIST': '/path/first'},
|
||||||
|
'append_path': {'SOME_VAR_STR': '/path/last'}},
|
||||||
|
{'EMPTY_PATH_LIST': '/path/first', 'SOME_VAR_STR': '/path/last'}),
|
||||||
|
({}, # Same as before but on variables that were not defined
|
||||||
|
{'prepend_path': {'EMPTY_PATH_LIST': '/path/first'},
|
||||||
|
'append_path': {'SOME_VAR_STR': '/path/last'}},
|
||||||
|
{'EMPTY_PATH_LIST': '/path/first', 'SOME_VAR_STR': '/path/last'}),
|
||||||
|
# Remove a path from a list
|
||||||
|
({'EMPTY_PATH_LIST': '/path/first:/path/middle:/path/last'},
|
||||||
|
{'remove_path': {'EMPTY_PATH_LIST': '/path/middle'}},
|
||||||
|
{'EMPTY_PATH_LIST': '/path/first:/path/last'}),
|
||||||
|
({'EMPTY_PATH_LIST': '/only/path'},
|
||||||
|
{'remove_path': {'EMPTY_PATH_LIST': '/only/path'}},
|
||||||
|
{'EMPTY_PATH_LIST': ''}),
|
||||||
|
])
|
||||||
|
def test_compiler_config_modifications(
|
||||||
|
initial, modifications, expected, ensure_env_variables, monkeypatch
|
||||||
|
):
|
||||||
|
# Set the environment as per prerequisites
|
||||||
|
ensure_env_variables(initial)
|
||||||
|
|
||||||
os.environ['SOME_VAR_STR'] = ''
|
# Monkeypatch a pkg.compiler.environment with the required modifications
|
||||||
os.environ['SOME_VAR_NUM'] = '0'
|
pkg = spack.spec.Spec('cmake').concretized().package
|
||||||
os.environ['PATH_LIST'] = '/path/third:/path/forth'
|
monkeypatch.setattr(pkg.compiler, 'environment', modifications)
|
||||||
os.environ['EMPTY_PATH_LIST'] = ''
|
|
||||||
os.environ.pop('NEW_PATH_LIST', None)
|
|
||||||
|
|
||||||
env_mod = syaml_dict()
|
# Trigger the modifications
|
||||||
set_cmd = syaml_dict()
|
|
||||||
env_mod[syaml_str('set')] = set_cmd
|
|
||||||
|
|
||||||
set_cmd[syaml_str('SOME_VAR_STR')] = syaml_str('SOME_STR')
|
|
||||||
set_cmd[syaml_str('SOME_VAR_NUM')] = 1
|
|
||||||
|
|
||||||
monkeypatch.setattr(pkg.compiler, 'environment', env_mod)
|
|
||||||
spack.build_environment.setup_package(pkg, False)
|
spack.build_environment.setup_package(pkg, False)
|
||||||
assert os.environ['SOME_VAR_STR'] == 'SOME_STR'
|
|
||||||
assert os.environ['SOME_VAR_NUM'] == str(1)
|
|
||||||
|
|
||||||
env_mod = syaml_dict()
|
# Check they were applied
|
||||||
unset_cmd = syaml_dict()
|
for name, value in expected.items():
|
||||||
env_mod[syaml_str('unset')] = unset_cmd
|
if value is not None:
|
||||||
|
assert os.environ[name] == value
|
||||||
unset_cmd[syaml_str('SOME_VAR_STR')] = None
|
continue
|
||||||
|
assert name not in os.environ
|
||||||
monkeypatch.setattr(pkg.compiler, 'environment', env_mod)
|
|
||||||
assert 'SOME_VAR_STR' in os.environ
|
|
||||||
spack.build_environment.setup_package(pkg, False)
|
|
||||||
assert 'SOME_VAR_STR' not in os.environ
|
|
||||||
|
|
||||||
env_mod = syaml_dict()
|
|
||||||
set_cmd = syaml_dict()
|
|
||||||
env_mod[syaml_str('set')] = set_cmd
|
|
||||||
append_cmd = syaml_dict()
|
|
||||||
env_mod[syaml_str('append-path')] = append_cmd
|
|
||||||
unset_cmd = syaml_dict()
|
|
||||||
env_mod[syaml_str('unset')] = unset_cmd
|
|
||||||
prepend_cmd = syaml_dict()
|
|
||||||
env_mod[syaml_str('prepend-path')] = prepend_cmd
|
|
||||||
|
|
||||||
set_cmd[syaml_str('EMPTY_PATH_LIST')] = syaml_str('/path/middle')
|
|
||||||
|
|
||||||
append_cmd[syaml_str('PATH_LIST')] = syaml_str('/path/last')
|
|
||||||
append_cmd[syaml_str('EMPTY_PATH_LIST')] = syaml_str('/path/last')
|
|
||||||
append_cmd[syaml_str('NEW_PATH_LIST')] = syaml_str('/path/last')
|
|
||||||
|
|
||||||
unset_cmd[syaml_str('SOME_VAR_NUM')] = None
|
|
||||||
|
|
||||||
prepend_cmd[syaml_str('PATH_LIST')] = syaml_str('/path/first:/path/second')
|
|
||||||
prepend_cmd[syaml_str('EMPTY_PATH_LIST')] = syaml_str('/path/first')
|
|
||||||
prepend_cmd[syaml_str('NEW_PATH_LIST')] = syaml_str('/path/first')
|
|
||||||
prepend_cmd[syaml_str('SOME_VAR_NUM')] = syaml_str('/8')
|
|
||||||
|
|
||||||
assert 'SOME_VAR_NUM' in os.environ
|
|
||||||
monkeypatch.setattr(pkg.compiler, 'environment', env_mod)
|
|
||||||
spack.build_environment.setup_package(pkg, False)
|
|
||||||
# Check that the order of modifications is respected and the
|
|
||||||
# variable was unset before it was prepended.
|
|
||||||
assert os.environ['SOME_VAR_NUM'] == '/8'
|
|
||||||
|
|
||||||
expected = '/path/first:/path/second:/path/third:/path/forth:/path/last'
|
|
||||||
assert os.environ['PATH_LIST'] == expected
|
|
||||||
|
|
||||||
expected = '/path/first:/path/middle:/path/last'
|
|
||||||
assert os.environ['EMPTY_PATH_LIST'] == expected
|
|
||||||
|
|
||||||
expected = '/path/first:/path/last'
|
|
||||||
assert os.environ['NEW_PATH_LIST'] == expected
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.regression('9107')
|
@pytest.mark.regression('9107')
|
||||||
|
Loading…
Reference in New Issue
Block a user