Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance get_software_libdir to return lib or lib64 if only one of them contains library files #4513

Merged
merged 2 commits into from
Jun 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions easybuild/tools/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
* Jens Timmerman (Ghent University)
* David Brown (Pacific Northwest National Laboratory)
"""
import glob
import os
import re
import shlex
Expand All @@ -52,6 +53,7 @@
from easybuild.tools.module_naming_scheme.mns import DEVEL_MODULE_SUFFIX
from easybuild.tools.py2vs3 import subprocess_popen_text
from easybuild.tools.run import run_cmd
from easybuild.tools.systemtools import get_shared_lib_ext
from easybuild.tools.utilities import get_subclasses, nub

# software root/version environment variable name prefixes
Expand Down Expand Up @@ -1671,6 +1673,7 @@ def get_software_libdir(name, only_one=True, fs=None):

Returns the library subdirectory, relative to software root.
It fails if multiple library subdirs are found, unless only_one is False which yields a list of all library subdirs.
If only_one is True and fs is None, select the one subdirectory with shared or static libraries, if possible.

:param name: name of the software package
:param only_one: indicates whether only one lib path is expected to be found
Expand Down Expand Up @@ -1703,6 +1706,16 @@ def get_software_libdir(name, only_one=True, fs=None):
if len(res) == 1:
res = res[0]
else:
if fs is None and len(res) == 2:
# if both lib and lib64 were found, check if only one (exactly) has libraries;
# this is needed for software with library archives in lib64 but other files/directories in lib
lib_glob = ['*.%s' % ext for ext in ['a', get_shared_lib_ext()]]
has_libs = [any(glob.glob(os.path.join(root, subdir, f)) for f in lib_glob) for subdir in res]
if has_libs[0] and not has_libs[1]:
return res[0]
elif has_libs[1] and not has_libs[0]:
return res[1]

raise EasyBuildError("Multiple library subdirectories found for %s in %s: %s",
name, root, ', '.join(res))
return res
Expand Down
16 changes: 15 additions & 1 deletion test/framework/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
from easybuild.tools.modules import curr_module_paths, get_software_libdir, get_software_root, get_software_version
from easybuild.tools.modules import invalidate_module_caches_for, modules_tool, reset_module_caches
from easybuild.tools.run import run_cmd
from easybuild.tools.systemtools import get_shared_lib_ext


# number of modules included for testing purposes
Expand Down Expand Up @@ -674,10 +675,23 @@ def test_get_software_root_version_libdir(self):
os.environ.pop('EBROOT%s' % env_var_name)
os.environ.pop('EBVERSION%s' % env_var_name)

# check expected result of get_software_libdir with multiple lib subdirs
# if only 'lib' has a library archive, use it
root = os.path.join(tmpdir, name)
mkdir(os.path.join(root, 'lib64'))
os.environ['EBROOT%s' % env_var_name] = root
write_file(os.path.join(root, 'lib', 'libfoo.a'), 'foo')
self.assertEqual(get_software_libdir(name), 'lib')

remove_file(os.path.join(root, 'lib', 'libfoo.a'))

# also check vice versa with *shared* library in lib64
shlib_ext = get_shared_lib_ext()
write_file(os.path.join(root, 'lib64', 'libfoo.' + shlib_ext), 'foo')
self.assertEqual(get_software_libdir(name), 'lib64')

remove_file(os.path.join(root, 'lib64', 'libfoo.' + shlib_ext))

# check expected result of get_software_libdir with multiple lib subdirs
self.assertErrorRegex(EasyBuildError, "Multiple library subdirectories found.*", get_software_libdir, name)
self.assertEqual(get_software_libdir(name, only_one=False), ['lib', 'lib64'])

Expand Down