Skip to content

Commit

Permalink
Extended set of environment modification commands.
Browse files Browse the repository at this point in the history
  • Loading branch information
skosukhin committed Aug 16, 2018
1 parent 5be5c48 commit fff3f7e
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 25 deletions.
17 changes: 10 additions & 7 deletions lib/spack/docs/basic_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -681,11 +681,12 @@ Compiler environment variables and additional RPATHs

In the exceptional case a compiler requires setting special environment
variables, like an explicit library load path. These can bet set in an
extra section in the compiler configuration. The user can also specify
additional ``RPATHs`` that the compiler will add to all executables
generated by that compiler. This is useful for forcing certain compilers
to RPATH their own runtime libraries, so that executables will run
without the need to set ``LD_LIBRARY_PATH``.
extra section in the compiler configuration (the supported environment
modification commands are: ``set``, ``unset``, ``append-path``, and
``prepend-paths``). The user can also specify additional ``RPATHs`` that the
compiler will add to all executables generated by that compiler. This is
useful for forcing certain compilers to RPATH their own runtime libraries, so
that executables will run without the need to set ``LD_LIBRARY_PATH``.

.. code-block:: yaml
Expand All @@ -698,8 +699,10 @@ without the need to set ``LD_LIBRARY_PATH``.
f77: /opt/gcc/bin/gfortran
fc: /opt/gcc/bin/gfortran
environment:
set:
LD_LIBRARY_PATH : /opt/gcc/lib
- [unset, BAD_VARIABLE]
- [set, GOOD_VARIABLE, 1]
- [prepend-path, PATH, /path/to/binutils]
- [append-path, LD_LIBRARY_PATH, /opt/gcc/lib]
extra_rpaths:
- /path/to/some/compiler/runtime/directory
- /path/to/some/other/compiler/runtime/directory
Expand Down
31 changes: 23 additions & 8 deletions lib/spack/spack/build_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,14 +291,29 @@ def set_build_environment_variables(pkg, env, dirty):
# the given compiler
compiler = pkg.compiler
environment = compiler.environment
if 'set' in environment:
env_to_set = environment['set']
for key, value in iteritems(env_to_set):
env.set('SPACK_ENV_SET_%s' % key, value)
env.set('%s' % key, value)
# Let shell know which variables to set
env_variables = ":".join(env_to_set.keys())
env.set('SPACK_ENV_TO_SET', env_variables)

if issubclass(type(environment), dict):
# For backward compatibility
if 'set' in environment:
env_to_set = environment['set']
for key, value in iteritems(env_to_set):
env.set('SPACK_ENV_SET_%s' % key, value)
env.set('%s' % key, value)
# Let shell know which variables to set
env_variables = ":".join(env_to_set.keys())
env.set('SPACK_ENV_TO_SET', env_variables)
elif issubclass(type(environment), list):
for modification in environment:
env_cmd = modification[0]
env_cmd_args = modification[1:]
if env_cmd == 'set' and len(env_cmd_args) == 2:
env.set(*env_cmd_args)
elif env_cmd == 'unset' and len(env_cmd_args) == 1:
env.unset(*env_cmd_args)
elif env_cmd == 'prepend-path' and len(env_cmd_args) == 2:
env.prepend_path(*env_cmd_args)
elif env_cmd == 'append-path' and len(env_cmd_args) == 2:
env.append_path(*env_cmd_args)

if compiler.extra_rpaths:
extra_rpaths = ':'.join(compiler.extra_rpaths)
Expand Down
2 changes: 1 addition & 1 deletion lib/spack/spack/compilers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ def _to_dict(compiler):
d['operating_system'] = str(compiler.operating_system)
d['target'] = str(compiler.target)
d['modules'] = compiler.modules if compiler.modules else []
d['environment'] = compiler.environment if compiler.environment else {}
d['environment'] = compiler.environment if compiler.environment else []
d['extra_rpaths'] = compiler.extra_rpaths if compiler.extra_rpaths else []

if compiler.alias:
Expand Down
72 changes: 63 additions & 9 deletions lib/spack/spack/schema/compilers.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,19 +81,73 @@
{'type': 'null'},
{'type': 'array'}]},
'environment': {
'type': 'object',
'default': {},
'additionalProperties': False,
'properties': {
'set': {
'oneOf': [
{
'type': 'object',
'patternProperties': {
r'\w[\w-]*': { # variable name
'type': 'string'
'default': {},
'additionalProperties': False,
'properties': {
'set': {
'type': 'object',
'patternProperties': {
r'\w[\w-]*': { # variable name
'type': 'string'
}
}
}
}
},
{
'type': 'array',
'default': [],
'items': {
'anyOf': [
{
# Commands with 2 arguments
'type': 'array',
'additionalItems': False,
'minItems': 3,
'items': [
{
'type': 'string',
'enum': [
'set',
'append-path',
'prepend-path']
},
{
# Variable name
'type': 'string'
},
{
# Variable value
'anyOf': [
{'type': 'string'},
{'type': 'number'}
]
}
]
},
{
# Commands with 1 argument
'type': 'array',
'additionalItems': False,
'minItems': 2,
'items': [
{
'type': 'string',
'enum': ['unset']
},
{
# Variable name
'type': 'string'
}
]
}
]
}
}
}
]
},
'extra_rpaths': {
'type': 'array',
Expand Down
82 changes: 82 additions & 0 deletions lib/spack/spack/test/build_environment.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
from spack.paths import build_env_path
from spack.build_environment import dso_suffix, _static_to_shared_library
from spack.util.executable import Executable
from spack.util.spack_yaml import syaml_dict, syaml_str, syaml_list


@pytest.fixture
Expand Down Expand Up @@ -126,3 +127,84 @@ def _set_wrong_cc(x):

assert os.environ['CC'] != 'NOT_THIS_PLEASE'
assert os.environ['ANOTHER_VAR'] == 'THIS_IS_SET'


@pytest.mark.usefixtures('config', 'mock_packages')
def test_compiler_config_modifications(monkeypatch):

s = spack.spec.Spec('cmake')
s.concretize()
pkg = s.package

os.environ['SOME_VAR'] = 'INIT_VAL'
os.environ['PATH_LIST'] = '/path/second:/path/third'
os.environ['EMPTY_PATH_LIST'] = ''
os.environ.pop('NEWLY_CREATED_PATH_LIST', None)

env_mod = syaml_dict(
{syaml_str('set'): syaml_dict(
{syaml_str('SOME_VAR'): syaml_str('ENV_IS_DICT')})})

monkeypatch.setattr(pkg.compiler, 'environment', env_mod)
spack.build_environment.setup_package(pkg, False)
assert os.environ['SOME_VAR'] == 'ENV_IS_DICT'

env_mod = syaml_list([
syaml_list([syaml_str('set'),
syaml_str('SOME_VAR'), syaml_str('ENV_IS_LIST')])
])

monkeypatch.setattr(pkg.compiler, 'environment', env_mod)
spack.build_environment.setup_package(pkg, False)
assert os.environ['SOME_VAR'] == 'ENV_IS_LIST'

env_mod = syaml_list([
syaml_list([syaml_str('unset'), syaml_str('SOME_VAR')])
])

monkeypatch.setattr(pkg.compiler, 'environment', env_mod)
spack.build_environment.setup_package(pkg, False)
assert 'ENV_IS_LIST' not in os.environ

env_mod = syaml_list([
syaml_list([syaml_str('append-path'),
syaml_str('PATH_LIST'),
syaml_str('/path/last')]),
syaml_list([syaml_str('prepend-path'),
syaml_str('PATH_LIST'),
syaml_str('/path/first')]),
syaml_list([syaml_str('append-path'),
syaml_str('EMPTY_PATH_LIST'),
syaml_str('/path/middle')]),
syaml_list([syaml_str('append-path'),
syaml_str('EMPTY_PATH_LIST'),
syaml_str('/path/last')]),
syaml_list([syaml_str('prepend-path'),
syaml_str('EMPTY_PATH_LIST'),
syaml_str('/path/first')]),
syaml_list([syaml_str('append-path'),
syaml_str('NEWLY_CREATED_PATH_LIST'),
syaml_str('/path/middle')]),
syaml_list([syaml_str('append-path'),
syaml_str('NEWLY_CREATED_PATH_LIST'),
syaml_str('/path/last')]),
syaml_list([syaml_str('prepend-path'),
syaml_str('NEWLY_CREATED_PATH_LIST'),
syaml_str('/path/first')])])

monkeypatch.setattr(pkg.compiler, 'environment', env_mod)
spack.build_environment.setup_package(pkg, False)

expected = '/path/first:/path/second:/path/third:/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/middle:/path/last'
assert os.environ['NEWLY_CREATED_PATH_LIST'] == expected

os.environ.pop('SOME_VAR', None)
os.environ.pop('PATH_LIST', None)
os.environ.pop('EMPTY_PATH_LIST', None)
os.environ.pop('NEWLY_CREATED_PATH_LIST', None)

0 comments on commit fff3f7e

Please sign in to comment.