implicit rpaths filtering (#12789)
* implicit_rpaths are now removed from compilers.yaml config and are always instantiated dynamically, this occurs one time in the build_environment module * per-compiler list required libraries (e.g. libstdc++, libgfortran) and whitelist directories from rpaths including those libraries. Remove non-whitelisted implicit rpaths. Some libraries default for all compilers. * reintroduce 'implicit_rpaths' as a config variable that can be used to disable Spack insertion of compiler RPATHs generated at build time.
This commit is contained in:
parent
b11a98abf0
commit
141a1648e6
@ -9,6 +9,7 @@
|
|||||||
import fileinput
|
import fileinput
|
||||||
import glob
|
import glob
|
||||||
import grp
|
import grp
|
||||||
|
import itertools
|
||||||
import numbers
|
import numbers
|
||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
@ -68,6 +69,32 @@ def path_contains_subdirectory(path, root):
|
|||||||
return norm_path.startswith(norm_root)
|
return norm_path.startswith(norm_root)
|
||||||
|
|
||||||
|
|
||||||
|
def possible_library_filenames(library_names):
|
||||||
|
"""Given a collection of library names like 'libfoo', generate the set of
|
||||||
|
library filenames that may be found on the system (e.g. libfoo.so). This
|
||||||
|
generates the library filenames that may appear on any OS.
|
||||||
|
"""
|
||||||
|
lib_extensions = ['a', 'la', 'so', 'tbd', 'dylib']
|
||||||
|
return set(
|
||||||
|
'.'.join((lib, extension)) for lib, extension in
|
||||||
|
itertools.product(library_names, lib_extensions))
|
||||||
|
|
||||||
|
|
||||||
|
def paths_containing_libs(paths, library_names):
|
||||||
|
"""Given a collection of filesystem paths, return the list of paths that
|
||||||
|
which include one or more of the specified libraries.
|
||||||
|
"""
|
||||||
|
required_lib_fnames = possible_library_filenames(library_names)
|
||||||
|
|
||||||
|
rpaths_to_include = []
|
||||||
|
for path in paths:
|
||||||
|
fnames = set(os.listdir(path))
|
||||||
|
if fnames & required_lib_fnames:
|
||||||
|
rpaths_to_include.append(path)
|
||||||
|
|
||||||
|
return rpaths_to_include
|
||||||
|
|
||||||
|
|
||||||
def same_path(path1, path2):
|
def same_path(path1, path2):
|
||||||
norm1 = os.path.abspath(path1).rstrip(os.path.sep)
|
norm1 = os.path.abspath(path1).rstrip(os.path.sep)
|
||||||
norm2 = os.path.abspath(path2).rstrip(os.path.sep)
|
norm2 = os.path.abspath(path2).rstrip(os.path.sep)
|
||||||
|
@ -348,9 +348,9 @@ def set_build_environment_variables(pkg, env, dirty):
|
|||||||
extra_rpaths = ':'.join(compiler.extra_rpaths)
|
extra_rpaths = ':'.join(compiler.extra_rpaths)
|
||||||
env.set('SPACK_COMPILER_EXTRA_RPATHS', extra_rpaths)
|
env.set('SPACK_COMPILER_EXTRA_RPATHS', extra_rpaths)
|
||||||
|
|
||||||
if compiler.implicit_rpaths:
|
implicit_rpaths = compiler.implicit_rpaths()
|
||||||
implicit_rpaths = ':'.join(compiler.implicit_rpaths)
|
if implicit_rpaths:
|
||||||
env.set('SPACK_COMPILER_IMPLICIT_RPATHS', implicit_rpaths)
|
env.set('SPACK_COMPILER_IMPLICIT_RPATHS', ':'.join(implicit_rpaths))
|
||||||
|
|
||||||
# Add bin directories from dependencies to the PATH for the build.
|
# Add bin directories from dependencies to the PATH for the build.
|
||||||
for prefix in build_prefixes:
|
for prefix in build_prefixes:
|
||||||
|
@ -9,7 +9,9 @@
|
|||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
import llnl.util.filesystem
|
import llnl.util.lang
|
||||||
|
from llnl.util.filesystem import (
|
||||||
|
path_contains_subdirectory, paths_containing_libs)
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
import spack.error
|
import spack.error
|
||||||
@ -79,13 +81,7 @@ def tokenize_flags(flags_str):
|
|||||||
_LIBPATH_ARG = re.compile(r'^[-/](LIBPATH|libpath):(?P<dir>.*)')
|
_LIBPATH_ARG = re.compile(r'^[-/](LIBPATH|libpath):(?P<dir>.*)')
|
||||||
|
|
||||||
|
|
||||||
def is_subdirectory(path, prefix):
|
def _parse_link_paths(string):
|
||||||
path = os.path.abspath(path)
|
|
||||||
prefix = os.path.abspath(prefix) + os.path.sep
|
|
||||||
return path.startswith(prefix)
|
|
||||||
|
|
||||||
|
|
||||||
def _parse_implicit_rpaths(string):
|
|
||||||
"""Parse implicit link paths from compiler debug output.
|
"""Parse implicit link paths from compiler debug output.
|
||||||
|
|
||||||
This gives the compiler runtime library paths that we need to add to
|
This gives the compiler runtime library paths that we need to add to
|
||||||
@ -142,18 +138,36 @@ def _parse_implicit_rpaths(string):
|
|||||||
if normalized_path not in visited:
|
if normalized_path not in visited:
|
||||||
implicit_link_dirs.append(normalized_path)
|
implicit_link_dirs.append(normalized_path)
|
||||||
visited.add(normalized_path)
|
visited.add(normalized_path)
|
||||||
implicit_link_dirs = filter_system_paths(implicit_link_dirs)
|
|
||||||
|
|
||||||
# Additional filtering: we also want to exclude paths that are
|
|
||||||
# subdirectories of /usr/lib/ and /lib/
|
|
||||||
implicit_link_dirs = list(
|
|
||||||
path for path in implicit_link_dirs
|
|
||||||
if not any(is_subdirectory(path, d) for d in ['/lib/', '/usr/lib/']))
|
|
||||||
|
|
||||||
tty.debug('found link dirs: %s' % ', '.join(implicit_link_dirs))
|
tty.debug('found link dirs: %s' % ', '.join(implicit_link_dirs))
|
||||||
return implicit_link_dirs
|
return implicit_link_dirs
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_non_system_link_dirs(string):
|
||||||
|
"""Parses link paths out of compiler debug output.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
string (str): compiler debug output as a string
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(list of str): implicit link paths parsed from the compiler output
|
||||||
|
"""
|
||||||
|
link_dirs = _parse_link_paths(string)
|
||||||
|
|
||||||
|
# Return set of directories containing needed compiler libs, minus
|
||||||
|
# system paths. Note that 'filter_system_paths' only checks for an
|
||||||
|
# exact match, while 'in_system_subdirectory' checks if a path contains
|
||||||
|
# a system directory as a subdirectory
|
||||||
|
link_dirs = filter_system_paths(link_dirs)
|
||||||
|
return list(p for p in link_dirs if not in_system_subdirectory(p))
|
||||||
|
|
||||||
|
|
||||||
|
def in_system_subdirectory(path):
|
||||||
|
system_dirs = ['/lib/', '/lib64/', '/usr/lib/', '/usr/lib64/',
|
||||||
|
'/usr/local/lib/', '/usr/local/lib64/']
|
||||||
|
return any(path_contains_subdirectory(path, x) for x in system_dirs)
|
||||||
|
|
||||||
|
|
||||||
class Compiler(object):
|
class Compiler(object):
|
||||||
"""This class encapsulates a Spack "compiler", which includes C,
|
"""This class encapsulates a Spack "compiler", which includes C,
|
||||||
C++, and Fortran compilers. Subclasses should implement
|
C++, and Fortran compilers. Subclasses should implement
|
||||||
@ -187,6 +201,10 @@ class Compiler(object):
|
|||||||
#: Regex used to extract version from compiler's output
|
#: Regex used to extract version from compiler's output
|
||||||
version_regex = '(.*)'
|
version_regex = '(.*)'
|
||||||
|
|
||||||
|
# These libraries are anticipated to be required by all executables built
|
||||||
|
# by any compiler
|
||||||
|
_all_compiler_rpath_libraries = ['libc', 'libc++', 'libstdc++']
|
||||||
|
|
||||||
# Default flags used by a compiler to set an rpath
|
# Default flags used by a compiler to set an rpath
|
||||||
@property
|
@property
|
||||||
def cc_rpath_arg(self):
|
def cc_rpath_arg(self):
|
||||||
@ -210,7 +228,7 @@ def fc_rpath_arg(self):
|
|||||||
|
|
||||||
def __init__(self, cspec, operating_system, target,
|
def __init__(self, cspec, operating_system, target,
|
||||||
paths, modules=[], alias=None, environment=None,
|
paths, modules=[], alias=None, environment=None,
|
||||||
extra_rpaths=None, implicit_rpaths=None,
|
extra_rpaths=None, enable_implicit_rpaths=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
self.spec = cspec
|
self.spec = cspec
|
||||||
self.operating_system = str(operating_system)
|
self.operating_system = str(operating_system)
|
||||||
@ -218,7 +236,7 @@ def __init__(self, cspec, operating_system, target,
|
|||||||
self.modules = modules
|
self.modules = modules
|
||||||
self.alias = alias
|
self.alias = alias
|
||||||
self.extra_rpaths = extra_rpaths
|
self.extra_rpaths = extra_rpaths
|
||||||
self.implicit_rpaths = implicit_rpaths
|
self.enable_implicit_rpaths = enable_implicit_rpaths
|
||||||
|
|
||||||
def check(exe):
|
def check(exe):
|
||||||
if exe is None:
|
if exe is None:
|
||||||
@ -251,31 +269,28 @@ def check(exe):
|
|||||||
def version(self):
|
def version(self):
|
||||||
return self.spec.version
|
return self.spec.version
|
||||||
|
|
||||||
@classmethod
|
def implicit_rpaths(self):
|
||||||
def verbose_flag(cls):
|
if self.enable_implicit_rpaths is False:
|
||||||
"""
|
return []
|
||||||
This property should be overridden in the compiler subclass if a
|
|
||||||
verbose flag is available.
|
|
||||||
|
|
||||||
If it is not overridden, it is assumed to not be supported.
|
exe_paths = [
|
||||||
|
x for x in [self.cc, self.cxx, self.fc, self.f77] if x]
|
||||||
|
link_dirs = self._get_compiler_link_paths(exe_paths)
|
||||||
|
|
||||||
|
all_required_libs = (
|
||||||
|
list(self.required_libs) + Compiler._all_compiler_rpath_libraries)
|
||||||
|
return list(paths_containing_libs(link_dirs, all_required_libs))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def required_libs(self):
|
||||||
|
"""For executables created with this compiler, the compiler libraries
|
||||||
|
that would be generally required to run it.
|
||||||
"""
|
"""
|
||||||
|
# By default every compiler returns the empty list
|
||||||
|
return []
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_implicit_rpaths(cls, string):
|
def _get_compiler_link_paths(cls, paths):
|
||||||
"""Parses link paths out of compiler debug output.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
string (str): compiler debug output as a string
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
(list of str): implicit link paths parsed from the compiler output
|
|
||||||
|
|
||||||
Subclasses can override this to customize.
|
|
||||||
"""
|
|
||||||
return _parse_implicit_rpaths(string)
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def determine_implicit_rpaths(cls, paths):
|
|
||||||
first_compiler = next((c for c in paths if c), None)
|
first_compiler = next((c for c in paths if c), None)
|
||||||
if not first_compiler:
|
if not first_compiler:
|
||||||
return []
|
return []
|
||||||
@ -293,7 +308,7 @@ def determine_implicit_rpaths(cls, paths):
|
|||||||
output = str(compiler_exe(cls.verbose_flag(), fin, '-o', fout,
|
output = str(compiler_exe(cls.verbose_flag(), fin, '-o', fout,
|
||||||
output=str, error=str)) # str for py2
|
output=str, error=str)) # str for py2
|
||||||
|
|
||||||
return cls.parse_implicit_rpaths(output)
|
return _parse_non_system_link_dirs(output)
|
||||||
except spack.util.executable.ProcessError as pe:
|
except spack.util.executable.ProcessError as pe:
|
||||||
tty.debug('ProcessError: Command exited with non-zero status: ' +
|
tty.debug('ProcessError: Command exited with non-zero status: ' +
|
||||||
pe.long_message)
|
pe.long_message)
|
||||||
@ -301,6 +316,15 @@ def determine_implicit_rpaths(cls, paths):
|
|||||||
finally:
|
finally:
|
||||||
shutil.rmtree(tmpdir, ignore_errors=True)
|
shutil.rmtree(tmpdir, ignore_errors=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def verbose_flag(cls):
|
||||||
|
"""
|
||||||
|
This property should be overridden in the compiler subclass if a
|
||||||
|
verbose flag is available.
|
||||||
|
|
||||||
|
If it is not overridden, it is assumed to not be supported.
|
||||||
|
"""
|
||||||
|
|
||||||
# This property should be overridden in the compiler subclass if
|
# This property should be overridden in the compiler subclass if
|
||||||
# OpenMP is supported by that compiler
|
# OpenMP is supported by that compiler
|
||||||
@property
|
@property
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
_path_instance_vars = ['cc', 'cxx', 'f77', 'fc']
|
_path_instance_vars = ['cc', 'cxx', 'f77', 'fc']
|
||||||
_flags_instance_vars = ['cflags', 'cppflags', 'cxxflags', 'fflags']
|
_flags_instance_vars = ['cflags', 'cppflags', 'cxxflags', 'fflags']
|
||||||
_other_instance_vars = ['modules', 'operating_system', 'environment',
|
_other_instance_vars = ['modules', 'operating_system', 'environment',
|
||||||
'extra_rpaths', 'implicit_rpaths']
|
'implicit_rpaths', 'extra_rpaths']
|
||||||
_cache_config_file = []
|
_cache_config_file = []
|
||||||
|
|
||||||
# TODO: Caches at module level make it difficult to mock configurations in
|
# TODO: Caches at module level make it difficult to mock configurations in
|
||||||
@ -73,7 +73,8 @@ def _to_dict(compiler):
|
|||||||
d['modules'] = compiler.modules or []
|
d['modules'] = compiler.modules or []
|
||||||
d['environment'] = compiler.environment or {}
|
d['environment'] = compiler.environment or {}
|
||||||
d['extra_rpaths'] = compiler.extra_rpaths or []
|
d['extra_rpaths'] = compiler.extra_rpaths or []
|
||||||
d['implicit_rpaths'] = compiler.implicit_rpaths or []
|
if compiler.enable_implicit_rpaths is not None:
|
||||||
|
d['implicit_rpaths'] = compiler.enable_implicit_rpaths
|
||||||
|
|
||||||
if compiler.alias:
|
if compiler.alias:
|
||||||
d['alias'] = compiler.alias
|
d['alias'] = compiler.alias
|
||||||
@ -350,10 +351,17 @@ def compiler_from_dict(items):
|
|||||||
compiler_flags = items.get('flags', {})
|
compiler_flags = items.get('flags', {})
|
||||||
environment = items.get('environment', {})
|
environment = items.get('environment', {})
|
||||||
extra_rpaths = items.get('extra_rpaths', [])
|
extra_rpaths = items.get('extra_rpaths', [])
|
||||||
implicit_rpaths = items.get('implicit_rpaths')
|
implicit_rpaths = items.get('implicit_rpaths', None)
|
||||||
|
|
||||||
|
# Starting with c22a145, 'implicit_rpaths' was a list. Now it is a
|
||||||
|
# boolean which can be set by the user to disable all automatic
|
||||||
|
# RPATH insertion of compiler libraries
|
||||||
|
if implicit_rpaths is not None and not isinstance(implicit_rpaths, bool):
|
||||||
|
implicit_rpaths = None
|
||||||
|
|
||||||
return cls(cspec, os, target, compiler_paths, mods, alias,
|
return cls(cspec, os, target, compiler_paths, mods, alias,
|
||||||
environment, extra_rpaths, implicit_rpaths,
|
environment, extra_rpaths,
|
||||||
|
enable_implicit_rpaths=implicit_rpaths,
|
||||||
**compiler_flags)
|
**compiler_flags)
|
||||||
|
|
||||||
|
|
||||||
@ -637,10 +645,8 @@ def _default(cmp_id, paths):
|
|||||||
compiler_cls = spack.compilers.class_for_compiler_name(compiler_name)
|
compiler_cls = spack.compilers.class_for_compiler_name(compiler_name)
|
||||||
spec = spack.spec.CompilerSpec(compiler_cls.name, version)
|
spec = spack.spec.CompilerSpec(compiler_cls.name, version)
|
||||||
paths = [paths.get(l, None) for l in ('cc', 'cxx', 'f77', 'fc')]
|
paths = [paths.get(l, None) for l in ('cc', 'cxx', 'f77', 'fc')]
|
||||||
implicit_rpaths = compiler_cls.determine_implicit_rpaths(paths)
|
|
||||||
compiler = compiler_cls(
|
compiler = compiler_cls(
|
||||||
spec, operating_system, py_platform.machine(), paths,
|
spec, operating_system, py_platform.machine(), paths
|
||||||
implicit_rpaths=implicit_rpaths
|
|
||||||
)
|
)
|
||||||
return [compiler]
|
return [compiler]
|
||||||
|
|
||||||
|
@ -69,6 +69,8 @@ def c11_flag(self):
|
|||||||
def pic_flag(self):
|
def pic_flag(self):
|
||||||
return "-fPIC"
|
return "-fPIC"
|
||||||
|
|
||||||
|
required_libs = ['libclang', 'libflang']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def fc_version(cls, fc):
|
def fc_version(cls, fc):
|
||||||
return cls.default_version(fc)
|
return cls.default_version(fc)
|
||||||
|
@ -177,6 +177,8 @@ def c11_flag(self):
|
|||||||
def pic_flag(self):
|
def pic_flag(self):
|
||||||
return "-fPIC"
|
return "-fPIC"
|
||||||
|
|
||||||
|
required_libs = ['libclang']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@llnl.util.lang.memoized
|
@llnl.util.lang.memoized
|
||||||
def default_version(cls, comp):
|
def default_version(cls, comp):
|
||||||
|
@ -113,6 +113,8 @@ def c11_flag(self):
|
|||||||
def pic_flag(self):
|
def pic_flag(self):
|
||||||
return "-fPIC"
|
return "-fPIC"
|
||||||
|
|
||||||
|
required_libs = ['libgcc', 'libgfortran']
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def default_version(cls, cc):
|
def default_version(cls, cc):
|
||||||
"""Older versions of gcc use the ``-dumpversion`` option.
|
"""Older versions of gcc use the ``-dumpversion`` option.
|
||||||
|
@ -36,6 +36,8 @@ class Intel(Compiler):
|
|||||||
def verbose_flag(cls):
|
def verbose_flag(cls):
|
||||||
return "-v"
|
return "-v"
|
||||||
|
|
||||||
|
required_libs = ['libirc', 'libifcore', 'libifcoremt', 'libirng']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def openmp_flag(self):
|
def openmp_flag(self):
|
||||||
if self.version < ver('16.0'):
|
if self.version < ver('16.0'):
|
||||||
|
@ -48,6 +48,8 @@ def cxx11_flag(self):
|
|||||||
def pic_flag(self):
|
def pic_flag(self):
|
||||||
return "-fpic"
|
return "-fpic"
|
||||||
|
|
||||||
|
required_libs = ['libpgc', 'libpgf90']
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def c99_flag(self):
|
def c99_flag(self):
|
||||||
if self.version >= ver('12.10'):
|
if self.version >= ver('12.10'):
|
||||||
|
@ -62,8 +62,11 @@
|
|||||||
{'type': 'null'},
|
{'type': 'null'},
|
||||||
{'type': 'array'}]},
|
{'type': 'array'}]},
|
||||||
'implicit_rpaths': {
|
'implicit_rpaths': {
|
||||||
'type': 'array',
|
'anyOf': [
|
||||||
'items': {'type': 'string'}
|
{'type': 'array',
|
||||||
|
'items': {'type': 'string'}},
|
||||||
|
{'type': 'boolean'}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
'environment': {
|
'environment': {
|
||||||
'type': 'object',
|
'type': 'object',
|
||||||
|
@ -170,6 +170,24 @@ def name(self):
|
|||||||
def version(self):
|
def version(self):
|
||||||
return "1.0.0"
|
return "1.0.0"
|
||||||
|
|
||||||
|
required_libs = ['libgfortran']
|
||||||
|
|
||||||
|
|
||||||
|
def test_implicit_rpaths(dirs_with_libfiles, monkeypatch):
|
||||||
|
lib_to_dirs, all_dirs = dirs_with_libfiles
|
||||||
|
|
||||||
|
def try_all_dirs(*args):
|
||||||
|
return all_dirs
|
||||||
|
|
||||||
|
monkeypatch.setattr(MockCompiler, '_get_compiler_link_paths', try_all_dirs)
|
||||||
|
|
||||||
|
expected_rpaths = set(lib_to_dirs['libstdc++'] +
|
||||||
|
lib_to_dirs['libgfortran'])
|
||||||
|
|
||||||
|
compiler = MockCompiler()
|
||||||
|
retrieved_rpaths = compiler.implicit_rpaths()
|
||||||
|
assert set(retrieved_rpaths) == expected_rpaths
|
||||||
|
|
||||||
|
|
||||||
# Get the desired flag from the specified compiler spec.
|
# Get the desired flag from the specified compiler spec.
|
||||||
def flag_value(flag, spec):
|
def flag_value(flag, spec):
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
import collections
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import inspect
|
import inspect
|
||||||
|
import itertools
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
import shutil
|
import shutil
|
||||||
@ -488,8 +489,48 @@ def mutable_database(database, _store_dir_and_cache):
|
|||||||
store_path.join('.spack-db').chmod(mode=0o555, rec=1)
|
store_path.join('.spack-db').chmod(mode=0o555, rec=1)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture()
|
||||||
|
def dirs_with_libfiles(tmpdir_factory):
|
||||||
|
lib_to_libfiles = {
|
||||||
|
'libstdc++': ['libstdc++.so', 'libstdc++.tbd'],
|
||||||
|
'libgfortran': ['libgfortran.a', 'libgfortran.dylib'],
|
||||||
|
'libirc': ['libirc.a', 'libirc.so']
|
||||||
|
}
|
||||||
|
|
||||||
|
root = tmpdir_factory.mktemp('root')
|
||||||
|
lib_to_dirs = {}
|
||||||
|
i = 0
|
||||||
|
for lib, libfiles in lib_to_libfiles.items():
|
||||||
|
dirs = []
|
||||||
|
for libfile in libfiles:
|
||||||
|
root.ensure(str(i), dir=True)
|
||||||
|
root.join(str(i)).ensure(libfile)
|
||||||
|
dirs.append(str(root.join(str(i))))
|
||||||
|
i += 1
|
||||||
|
lib_to_dirs[lib] = dirs
|
||||||
|
|
||||||
|
all_dirs = list(itertools.chain.from_iterable(lib_to_dirs.values()))
|
||||||
|
|
||||||
|
yield lib_to_dirs, all_dirs
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.fixture(scope='function', autouse=True)
|
||||||
|
def disable_compiler_execution(monkeypatch):
|
||||||
|
def noop(*args):
|
||||||
|
return []
|
||||||
|
|
||||||
|
# Compiler.determine_implicit_rpaths actually runs the compiler. So this
|
||||||
|
# replaces that function with a noop that simulates finding no implicit
|
||||||
|
# RPATHs
|
||||||
|
monkeypatch.setattr(
|
||||||
|
spack.compiler.Compiler,
|
||||||
|
'_get_compiler_link_paths',
|
||||||
|
noop
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='function')
|
@pytest.fixture(scope='function')
|
||||||
def install_mockery(tmpdir, config, mock_packages):
|
def install_mockery(tmpdir, config, mock_packages, monkeypatch):
|
||||||
"""Hooks a fake install directory, DB, and stage directory into Spack."""
|
"""Hooks a fake install directory, DB, and stage directory into Spack."""
|
||||||
real_store = spack.store.store
|
real_store = spack.store.store
|
||||||
spack.store.store = spack.store.Store(str(tmpdir.join('opt')))
|
spack.store.store = spack.store.Store(str(tmpdir.join('opt')))
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
import spack.paths
|
import spack.paths
|
||||||
from spack.compiler import _parse_implicit_rpaths
|
from spack.compiler import _parse_non_system_link_dirs
|
||||||
|
|
||||||
#: directory with sample compiler data
|
#: directory with sample compiler data
|
||||||
datadir = os.path.join(spack.paths.test_path, 'data',
|
datadir = os.path.join(spack.paths.test_path, 'data',
|
||||||
@ -16,7 +16,7 @@
|
|||||||
def check_link_paths(filename, paths):
|
def check_link_paths(filename, paths):
|
||||||
with open(os.path.join(datadir, filename)) as file:
|
with open(os.path.join(datadir, filename)) as file:
|
||||||
output = file.read()
|
output = file.read()
|
||||||
detected_paths = _parse_implicit_rpaths(output)
|
detected_paths = _parse_non_system_link_dirs(output)
|
||||||
|
|
||||||
actual = detected_paths
|
actual = detected_paths
|
||||||
expected = paths
|
expected = paths
|
||||||
|
@ -197,6 +197,16 @@ def test_symlinks_false(self, stage):
|
|||||||
assert not os.path.islink('dest/2')
|
assert not os.path.islink('dest/2')
|
||||||
|
|
||||||
|
|
||||||
|
def test_paths_containing_libs(dirs_with_libfiles):
|
||||||
|
lib_to_dirs, all_dirs = dirs_with_libfiles
|
||||||
|
|
||||||
|
assert (set(fs.paths_containing_libs(all_dirs, ['libgfortran'])) ==
|
||||||
|
set(lib_to_dirs['libgfortran']))
|
||||||
|
|
||||||
|
assert (set(fs.paths_containing_libs(all_dirs, ['libirc'])) ==
|
||||||
|
set(lib_to_dirs['libirc']))
|
||||||
|
|
||||||
|
|
||||||
def test_move_transaction_commit(tmpdir):
|
def test_move_transaction_commit(tmpdir):
|
||||||
|
|
||||||
fake_library = tmpdir.mkdir('lib').join('libfoo.so')
|
fake_library = tmpdir.mkdir('lib').join('libfoo.so')
|
||||||
|
Loading…
Reference in New Issue
Block a user