Skip to content

Commit

Permalink
get_software_libdir: return dir if it's only 1 with libs
Browse files Browse the repository at this point in the history
There are situations e.g. with recent Gentoo where all 64-bit libraries
are under `lib64`, but `lib` is seperate and used for other files and
directories (e.g. `lib/python`), and for 32-bit libraries.

`get_software_libdir` would fail for such. To avoid this:

if `only_one` is `True` (default), *and* no specific file (`fs`) is
specified (also default), *and* `lib` and `lib64` both exist and are
separate, and only one of them has libraries (shared or static),
it returns that one directory.
  • Loading branch information
bartoldeman committed Apr 22, 2024
1 parent 7eee9b1 commit 1636724
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 1 deletion.
10 changes: 10 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,13 @@ def get_software_libdir(name, only_one=True, fs=None):
if len(res) == 1:
res = res[0]
else:
if fs is None:
# 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()]]
haslibs = [any(glob.glob(os.path.join(root, subdir, f)) for f in lib_glob) for subdir in res]
if haslibs[0] != haslibs[1]:
return res[int(not haslibs[0])]
raise EasyBuildError("Multiple library subdirectories found for %s in %s: %s",
name, root, ', '.join(res))
return res
Expand Down
7 changes: 6 additions & 1 deletion test/framework/modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,10 +674,15 @@ 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', 'foo.a'), 'foo')
self.assertEqual(get_software_libdir(name), 'lib')

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

Expand Down

0 comments on commit 1636724

Please sign in to comment.