Skip to content

Commit e6f80db

Browse files
authored
Merge pull request #4051 from boegel/get_linked_libs_raw
add get_linked_libs_raw function, and use it from both check_linked_shared_libs and sanity_check_rpath
2 parents 4f69c62 + 7578e39 commit e6f80db

File tree

2 files changed

+54
-47
lines changed

2 files changed

+54
-47
lines changed

easybuild/framework/easyblock.py

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@
9696
from easybuild.tools.package.utilities import package
9797
from easybuild.tools.py2vs3 import extract_method_name, string_type
9898
from easybuild.tools.repository.repository import init_repository
99-
from easybuild.tools.systemtools import check_linked_shared_libs, det_parallelism, get_shared_lib_ext, use_group
99+
from easybuild.tools.systemtools import check_linked_shared_libs, det_parallelism, get_linked_libs_raw
100+
from easybuild.tools.systemtools import get_shared_lib_ext, use_group
100101
from easybuild.tools.utilities import INDENT_4SPACES, get_class_for, nub, quote_str
101102
from easybuild.tools.utilities import remove_unwanted_chars, time2str, trace_msg
102103
from easybuild.tools.version import this_is_easybuild, VERBOSE_VERSION, VERSION
@@ -2994,24 +2995,15 @@ def sanity_check_rpath(self, rpath_dirs=None):
29942995
for path in [os.path.join(dirpath, x) for x in os.listdir(dirpath)]:
29952996
self.log.debug("Sanity checking RPATH for %s", path)
29962997

2997-
out, ec = run_cmd("file %s" % path, simple=False, trace=False)
2998-
if ec:
2999-
fail_msg = "Failed to run 'file %s': %s" % (path, out)
3000-
self.log.warning(fail_msg)
3001-
fails.append(fail_msg)
3002-
3003-
# only run ldd/readelf on dynamically linked executables/libraries
3004-
# example output:
3005-
# ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), ...
3006-
# ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, not stripped
3007-
if "dynamically linked" in out:
2998+
out = get_linked_libs_raw(path)
2999+
3000+
if out is None:
3001+
msg = "Failed to determine dynamically linked libraries for %s, "
3002+
msg += "so skipping it in RPATH sanity check"
3003+
self.log.debug(msg, path)
3004+
else:
30083005
# check whether all required libraries are found via 'ldd'
3009-
out, ec = run_cmd("ldd %s" % path, simple=False, trace=False)
3010-
if ec:
3011-
fail_msg = "Failed to run 'ldd %s': %s" % (path, out)
3012-
self.log.warning(fail_msg)
3013-
fails.append(fail_msg)
3014-
elif not_found_regex.search(out):
3006+
if not_found_regex.search(out):
30153007
fail_msg = "One or more required libraries not found for %s: %s" % (path, out)
30163008
self.log.warning(fail_msg)
30173009
fails.append(fail_msg)
@@ -3030,9 +3022,6 @@ def sanity_check_rpath(self, rpath_dirs=None):
30303022
fails.append(fail_msg)
30313023
else:
30323024
self.log.debug("Output of 'readelf -d %s' checked, looks OK", path)
3033-
3034-
else:
3035-
self.log.debug("%s is not dynamically linked, so skipping it in RPATH sanity check", path)
30363025
else:
30373026
self.log.debug("Not sanity checking files in non-existing directory %s", dirpath)
30383027

easybuild/tools/systemtools.py

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -935,31 +935,16 @@ def get_glibc_version():
935935
return glibc_ver
936936

937937

938-
def check_linked_shared_libs(path, required_patterns=None, banned_patterns=None):
938+
def get_linked_libs_raw(path):
939939
"""
940-
Check for (lack of) patterns in linked shared libraries for binary/library at specified path.
941-
Uses 'ldd' on Linux and 'otool -L' on macOS to determine linked shared libraries.
942-
943-
Returns True or False for dynamically linked binaries and shared libraries to indicate
944-
whether all patterns match and antipatterns don't match.
945-
946-
Returns None if given path is not a dynamically linked binary or library.
940+
Get raw output from command that reports linked libraries for dynamically linked executables/libraries,
941+
or None for other types of files.
947942
"""
948-
if required_patterns is None:
949-
required_regexs = []
950-
else:
951-
required_regexs = [re.compile(p) if isinstance(p, string_type) else p for p in required_patterns]
952943

953-
if banned_patterns is None:
954-
banned_regexs = []
955-
else:
956-
banned_regexs = [re.compile(p) if isinstance(p, string_type) else p for p in banned_patterns]
957-
958-
# resolve symbolic links (unless they're broken)
959-
if os.path.islink(path) and os.path.exists(path):
960-
path = os.path.realpath(path)
961-
962-
file_cmd_out, _ = run_cmd("file %s" % path, simple=False, trace=False)
944+
file_cmd_out, ec = run_cmd("file %s" % path, simple=False, trace=False)
945+
if ec:
946+
fail_msg = "Failed to run 'file %s': %s" % (path, file_cmd_out)
947+
_log.warning(fail_msg)
963948

964949
os_type = get_os_type()
965950

@@ -970,9 +955,7 @@ def check_linked_shared_libs(path, required_patterns=None, banned_patterns=None)
970955
# example output for shared libraries:
971956
# /lib64/libc-2.17.so: ELF 64-bit LSB shared object, x86-64, ..., dynamically linked (uses shared libs), ...
972957
if "dynamically linked" in file_cmd_out:
973-
# determine linked libraries via 'ldd', but take into account that 'ldd' may fail for strange reasons,
974-
# like printing 'not a dynamic executable' when not enough memory is available
975-
# (see also https://bugzilla.redhat.com/show_bug.cgi?id=1817111)
958+
# determine linked libraries via 'ldd'
976959
linked_libs_cmd = "ldd %s" % path
977960
else:
978961
return None
@@ -990,11 +973,46 @@ def check_linked_shared_libs(path, required_patterns=None, banned_patterns=None)
990973
else:
991974
raise EasyBuildError("Unknown OS type: %s", os_type)
992975

976+
# take into account that 'ldd' may fail for strange reasons,
977+
# like printing 'not a dynamic executable' when not enough memory is available
978+
# (see also https://bugzilla.redhat.com/show_bug.cgi?id=1817111)
993979
out, ec = run_cmd(linked_libs_cmd, simple=False, trace=False, log_ok=False, log_all=False)
994980
if ec == 0:
995981
linked_libs_out = out
996982
else:
997-
print_warning("Determining linked libraries for %s via '%s' failed! Output: '%s'", path, linked_libs_cmd, out)
983+
fail_msg = "Determining linked libraries for %s via '%s' failed! Output: '%s'" % (path, linked_libs_cmd, out)
984+
print_warning(fail_msg)
985+
linked_libs_out = None
986+
987+
return linked_libs_out
988+
989+
990+
def check_linked_shared_libs(path, required_patterns=None, banned_patterns=None):
991+
"""
992+
Check for (lack of) patterns in linked shared libraries for binary/library at specified path.
993+
Uses 'ldd' on Linux and 'otool -L' on macOS to determine linked shared libraries.
994+
995+
Returns True or False for dynamically linked binaries and shared libraries to indicate
996+
whether all patterns match and antipatterns don't match.
997+
998+
Returns None if given path is not a dynamically linked binary or library.
999+
"""
1000+
if required_patterns is None:
1001+
required_regexs = []
1002+
else:
1003+
required_regexs = [re.compile(p) if isinstance(p, string_type) else p for p in required_patterns]
1004+
1005+
if banned_patterns is None:
1006+
banned_regexs = []
1007+
else:
1008+
banned_regexs = [re.compile(p) if isinstance(p, string_type) else p for p in banned_patterns]
1009+
1010+
# resolve symbolic links (unless they're broken)
1011+
if os.path.islink(path) and os.path.exists(path):
1012+
path = os.path.realpath(path)
1013+
1014+
linked_libs_out = get_linked_libs_raw(path)
1015+
if linked_libs_out is None:
9981016
return None
9991017

10001018
found_banned_patterns = []

0 commit comments

Comments
 (0)