Skip to content

Commit

Permalink
add support for disabling strict RPATH sanity check + implement detec…
Browse files Browse the repository at this point in the history
…tion of mixing of using RPATH with dependencies that were installed without RPATH
  • Loading branch information
boegel committed Mar 6, 2024
1 parent 849ffed commit 1989fa3
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
33 changes: 30 additions & 3 deletions easybuild/framework/easyblock.py
Original file line number Diff line number Diff line change
Expand Up @@ -3118,16 +3118,23 @@ def sanity_check_rpath(self, rpath_dirs=None, check_readelf_rpath=True):
self.log.info("Checking RPATH linkage for binaries/libraries...")

fails = []
mixed_stack = False

# hard reset $LD_LIBRARY_PATH before running RPATH sanity check
orig_env = env.unset_env_vars(['LD_LIBRARY_PATH'])
if build_option('strict_rpath_sanity_check'):
self.log.info("Unsetting $LD_LIBRARY_PATH since strict RPATH sanity check is enabled...")
# hard reset $LD_LIBRARY_PATH before running RPATH sanity check
orig_env = env.unset_env_vars(['LD_LIBRARY_PATH'])
else:
self.log.info("Not unsetting $LD_LIBRARY_PATH since strict RPATH sanity check is disabled...")
orig_env = None

ld_library_path = os.getenv('LD_LIBRARY_PATH', '(empty)')
self.log.debug(f"$LD_LIBRARY_PATH during RPATH sanity check: {ld_library_path}")
modules_list = self.modules_tool.list()
self.log.debug(f"List of loaded modules: {modules_list}")

not_found_regex = re.compile(r'(\S+)\s*\=\>\s*not found')
lib_path_regex = re.compile(r'\S+\s*\=\>\s*(\S+)')
readelf_rpath_regex = re.compile('(RPATH)', re.M)

# List of libraries that should be exempt from the RPATH sanity check;
Expand Down Expand Up @@ -3173,6 +3180,17 @@ def sanity_check_rpath(self, rpath_dirs=None, check_readelf_rpath=True):
fail_msg = f"Library {match} not found for {path}"
self.log.warning(fail_msg)
fails.append(fail_msg)

# inject suggestion to disable strict RPATH sanity check if one or more dependency libraries
# were not installed with RPATH linking enabled (so we're in a "mixed stack" situation)
if fails:
lib_paths = re.findall(lib_path_regex, out)
for lib_path in lib_paths:
self.log.info(f"Checking whether dependency library {lib_path} has RPATH section")
res = run_shell_cmd(f"readelf -d {lib_path}", fail_on_error=False)
if res.exit_code:
self.log.info(f"No RPATH section found in {lib_path}")
mixed_stack = True
else:
self.log.debug(f"Output of 'ldd {path}' checked, looks OK")

Expand All @@ -3195,7 +3213,16 @@ def sanity_check_rpath(self, rpath_dirs=None, check_readelf_rpath=True):
else:
self.log.debug(f"Not sanity checking files in non-existing directory {dirpath}")

env.restore_env_vars(orig_env)
if orig_env:
env.restore_env_vars(orig_env)

if mixed_stack:
msg = "\nNo RPATH section found in one or more dependency libraries, "
msg += "so you should probably change your EasyBuild configuration to disable "
msg += "the strict RPATH sanity check that involves unsetting $LD_LIBRARY_PATH "
msg += "when checking for required libraries; "
msg += "see also https://docs.easybuild.io/easybuild-v5/strict-rpath-sanity-check"
fails.append(msg)

return fails

Expand Down
1 change: 1 addition & 0 deletions easybuild/tools/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ def mk_full_default_path(name, prefix=DEFAULT_PREFIX):
'mpi_tests',
'pre_create_installdir',
'show_progress_bar',
'strict_rpath_sanity_check',
'trace',
],
EMPTY_LIST: [
Expand Down
3 changes: 3 additions & 0 deletions easybuild/tools/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,9 @@ def override_options(self):
'skip-test-cases': ("Skip running test cases", None, 'store_true', False, 't'),
'skip-test-step': ("Skip running the test step (e.g. unit tests)", None, 'store_true', False),
'sticky-bit': ("Set sticky bit on newly created directories", None, 'store_true', False),
'strict-rpath-sanity-check': ("Perform strict RPATH sanity check, which involces unsetting "
"$LD_LIBRARY_PATH before checking whether all required libraries are found",
None, 'store_true', True),
'sysroot': ("Location root directory of system, prefix for standard paths like /usr/lib and /usr/include",
None, 'store', None),
'trace': ("Provide more information in output to stdout on progress", None, 'store_true', True, 'T'),
Expand Down

0 comments on commit 1989fa3

Please sign in to comment.