Skip to content

Commit 9395187

Browse files
committed
enhance get_software_libdir to return full paths if requested
This avoids the need to do something like `os.path.join(get_software_root(foo), get_software_libdir(foo))`
1 parent cad3801 commit 9395187

File tree

2 files changed

+35
-18
lines changed

2 files changed

+35
-18
lines changed

easybuild/tools/modules.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1697,7 +1697,7 @@ def get_software_root(name, with_env_var=False):
16971697
return res
16981698

16991699

1700-
def get_software_libdir(name, only_one=True, fs=None):
1700+
def get_software_libdir(name, only_one=True, fs=None, full_path=False):
17011701
"""
17021702
Find library subdirectories for the specified software package.
17031703
@@ -1708,30 +1708,35 @@ def get_software_libdir(name, only_one=True, fs=None):
17081708
:param name: name of the software package
17091709
:param only_one: indicates whether only one lib path is expected to be found
17101710
:param fs: only retain library subdirs that contain one of the files in this list
1711+
:param full_path: Include the software root in the returned path, or just return the subfolder found
17111712
"""
17121713
lib_subdirs = ['lib', 'lib64']
17131714
root = get_software_root(name)
1714-
res = []
1715+
found_subdirs = []
17151716
if root:
17161717
for lib_subdir in lib_subdirs:
17171718
lib_dir_path = os.path.join(root, lib_subdir)
17181719
if os.path.exists(lib_dir_path):
17191720
# take into account that lib64 could be a symlink to lib (or vice versa)
17201721
# see https://github.com/easybuilders/easybuild-framework/issues/3139
1721-
if any(os.path.samefile(lib_dir_path, os.path.join(root, x)) for x in res):
1722+
if any(os.path.samefile(lib_dir_path, os.path.join(root, x)) for x in found_subdirs):
17221723
_log.debug("%s is the same as one of the other paths, so skipping it", lib_dir_path)
17231724

17241725
elif fs is None or any(os.path.exists(os.path.join(lib_dir_path, f)) for f in fs):
17251726
_log.debug("Retaining library subdir '%s' (found at %s)", lib_subdir, lib_dir_path)
1726-
res.append(lib_subdir)
1727+
found_subdirs.append(lib_subdir)
17271728

17281729
elif build_option('extended_dry_run'):
1729-
res.append(lib_subdir)
1730+
found_subdirs.append(lib_subdir)
17301731
break
17311732

17321733
# if no library subdir was found, return None
1733-
if not res:
1734+
if not found_subdirs:
17341735
return None
1736+
if full_path:
1737+
res = [os.path.join(root, subdir) for subdir in found_subdirs]
1738+
else:
1739+
res = found_subdirs
17351740
if only_one:
17361741
if len(res) == 1:
17371742
res = res[0]
@@ -1740,14 +1745,15 @@ def get_software_libdir(name, only_one=True, fs=None):
17401745
# if both lib and lib64 were found, check if only one (exactly) has libraries;
17411746
# this is needed for software with library archives in lib64 but other files/directories in lib
17421747
lib_glob = ['*.%s' % ext for ext in ['a', get_shared_lib_ext()]]
1743-
has_libs = [any(glob.glob(os.path.join(root, subdir, f)) for f in lib_glob) for subdir in res]
1748+
has_libs = [any(glob.glob(os.path.join(root, subdir, f)) for f in lib_glob)
1749+
for subdir in found_subdirs]
17441750
if has_libs[0] and not has_libs[1]:
17451751
return res[0]
1746-
elif has_libs[1] and not has_libs[0]:
1752+
if has_libs[1] and not has_libs[0]:
17471753
return res[1]
17481754

17491755
raise EasyBuildError("Multiple library subdirectories found for %s in %s: %s",
1750-
name, root, ', '.join(res))
1756+
name, root, ', '.join(found_subdirs))
17511757
return res
17521758
else:
17531759
# return None if software package root could not be determined

test/framework/modules.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@ def test_get_software_root_version_libdir(self):
686686
self.assertEqual(get_software_root(name), root)
687687
self.assertEqual(get_software_version(name), version)
688688
self.assertEqual(get_software_libdir(name), 'lib')
689+
self.assertEqual(get_software_libdir(name, full_path=True), os.path.join(root, 'lib'))
689690

690691
os.environ.pop('EBROOT%s' % env_var_name)
691692
os.environ.pop('EBVERSION%s' % env_var_name)
@@ -694,50 +695,60 @@ def test_get_software_root_version_libdir(self):
694695
root = os.path.join(tmpdir, name)
695696
mkdir(os.path.join(root, 'lib64'))
696697
os.environ['EBROOT%s' % env_var_name] = root
698+
699+
def check_get_software_libdir(expected, **additional_args):
700+
self.assertEqual(get_software_libdir(name, **additional_args), expected)
701+
if isinstance(expected, list):
702+
expected = [os.path.join(root, d) for d in expected]
703+
elif expected:
704+
expected = os.path.join(root, expected)
705+
self.assertEqual(get_software_libdir(name, full_path=True, **additional_args), expected)
706+
697707
write_file(os.path.join(root, 'lib', 'libfoo.a'), 'foo')
698-
self.assertEqual(get_software_libdir(name), 'lib')
708+
check_get_software_libdir('lib')
699709

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

702712
# also check vice versa with *shared* library in lib64
703713
shlib_ext = get_shared_lib_ext()
704714
write_file(os.path.join(root, 'lib64', 'libfoo.' + shlib_ext), 'foo')
705-
self.assertEqual(get_software_libdir(name), 'lib64')
715+
check_get_software_libdir('lib64')
706716

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

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

713723
# only directories containing files in specified list should be retained
714724
write_file(os.path.join(root, 'lib64', 'foo'), 'foo')
715-
self.assertEqual(get_software_libdir(name, fs=['foo']), 'lib64')
725+
check_get_software_libdir(fs=['foo'], expected='lib64')
716726

717727
# duplicate paths due to symlink get filtered
718728
remove_dir(os.path.join(root, 'lib64'))
719729
symlink(os.path.join(root, 'lib'), os.path.join(root, 'lib64'))
720-
self.assertEqual(get_software_libdir(name), 'lib')
730+
check_get_software_libdir('lib')
721731

722732
# same goes for lib symlinked to lib64
723733
remove_file(os.path.join(root, 'lib64'))
724734
remove_dir(os.path.join(root, 'lib'))
725735
mkdir(os.path.join(root, 'lib64'))
726736
symlink(os.path.join(root, 'lib64'), os.path.join(root, 'lib'))
727737
# still returns 'lib' because that's the first subdir considered
728-
self.assertEqual(get_software_libdir(name), 'lib')
738+
check_get_software_libdir('lib')
729739

730740
# clean up for previous tests
731741
os.environ.pop('EBROOT%s' % env_var_name)
732742

733743
# if root/version for specified software package can not be found, these functions should return None
734-
self.assertEqual(get_software_root('foo'), None)
735-
self.assertEqual(get_software_version('foo'), None)
736-
self.assertEqual(get_software_libdir('foo'), None)
744+
self.assertEqual(get_software_root(name), None)
745+
self.assertEqual(get_software_version(name), None)
746+
check_get_software_libdir(None)
737747

738748
# if no library subdir is found, get_software_libdir should return None
739749
os.environ['EBROOTFOO'] = tmpdir
740750
self.assertEqual(get_software_libdir('foo'), None)
751+
self.assertEqual(get_software_libdir('foo', full_path=True), None)
741752
os.environ.pop('EBROOTFOO')
742753

743754
shutil.rmtree(tmpdir)

0 commit comments

Comments
 (0)