Skip to content

Commit 15fdc3b

Browse files
authored
Merge pull request #5 from boegel/use_patch_when_filter_ld_library_path
relax condition in Python easyblock to run sanity check on ctypes correctly working + minor changes to comments & log messages
2 parents 51cb613 + dd442a3 commit 15fdc3b

File tree

1 file changed

+39
-31
lines changed

1 file changed

+39
-31
lines changed

easybuild/easyblocks/p/python.py

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -354,18 +354,20 @@ def _get_pip_ext_version(self):
354354

355355
def fetch_step(self, *args, **kwargs):
356356
"""
357-
Custom fetch step for Python: add patches from patches_custom_ctypes to 'patches' if
358-
EasyBuild is configured to filter LD_LIBRARY_PATH (and is configured not to filter LIBRARY_PATH).
357+
Custom fetch step for Python.
358+
359+
Add patch specified in patch_ctypes_ld_library_path to list of patches if
360+
EasyBuild is configured to filter $LD_LIBRARY_PATH (and is configured not to filter $LIBRARY_PATH).
359361
This needs to be done in (or before) the fetch step to ensure that those patches are also fetched.
360362
"""
361-
# If we filter out LD_LIBRARY_PATH (not unusual when using rpath), ctypes is not able to dynamically load
363+
# If we filter out $LD_LIBRARY_PATH (not unusual when using rpath), ctypes is not able to dynamically load
362364
# libraries installed with EasyBuild (see https://github.com/EESSI/software-layer/issues/192).
363-
# If EasyBuild is configured to filter LD_LIBRARY_PATH any patches listed in `patches_custom_ctypes`
365+
# If EasyBuild is configured to filter $LD_LIBRARY_PATH the patch specified in 'patch_ctypes_ld_library_path'
364366
# are added to the list of patches. Also, we add the checksums_filter_ld_library_path to the checksums list in
365367
# that case.
366-
# This mechanism e.g. makes sure we can patch ctypes, which normally strongly relies on LD_LIBRARY_PATH to find
368+
# This mechanism e.g. makes sure we can patch ctypes, which normally strongly relies on $LD_LIBRARY_PATH to find
367369
# libraries. But, we want to do the patching conditionally on EasyBuild configuration (i.e. which env vars
368-
# are filtered), hence this setup based on the custom config option 'patches_custom_ctypes'
370+
# are filtered), hence this setup based on the custom easyconfig parameter 'patch_ctypes_ld_library_path'
369371
filtered_env_vars = build_option('filter_env_vars') or []
370372
patch_ctypes_ld_library_path = self.cfg.get('patch_ctypes_ld_library_path')
371373
if (
@@ -380,29 +382,29 @@ def fetch_step(self, *args, **kwargs):
380382
patches = self.cfg.get('patches')
381383
len_patches = len(patches) if patches else 0
382384
if len_patches + len(sources) + 1 == len(checksums):
383-
msg = "EasyBuild was configured to filter LD_LIBRARY_PATH (and not to filter LIBRARY_PATH). "
384-
msg += "The ctypes module relies heavily on LD_LIBRARY_PATH for locating its libraries. "
385-
msg += "The following patches will be applied to make sure ctypes.CDLL, ctypes.cdll.LoadLibrary "
385+
msg = "EasyBuild was configured to filter $LD_LIBRARY_PATH (and not to filter $LIBRARY_PATH). "
386+
msg += "The ctypes module relies heavily on $LD_LIBRARY_PATH for locating its libraries. "
387+
msg += "The following patch will be applied to make sure ctypes.CDLL, ctypes.cdll.LoadLibrary "
386388
msg += f"and ctypes.util.find_library will still work correctly: {patch_ctypes_ld_library_path}."
387389
self.log.info(msg)
388390
self.log.info(f"Original list of patches: {self.cfg['patches']}")
389391
self.log.info(f"Patch to be added: {patch_ctypes_ld_library_path}")
390392
self.cfg.update('patches', [patch_ctypes_ld_library_path])
391393
self.log.info(f"Updated list of patches: {self.cfg['patches']}")
392394
else:
393-
msg = "The length of 'checksums' (%s) was not equal to the total amount of sources (%s) + patches (%s)"
394-
msg += ". Did you forget to add a checksum for patch_ctypes_ld_library_path?."
395+
msg = "The length of 'checksums' (%s) is not equal to the total amount of sources (%s) + patches (%s). "
396+
msg += "Did you forget to add a checksum for patch_ctypes_ld_library_path?"
395397
raise EasyBuildError(msg, len(checksums), len(sources), len(len_patches + 1))
396398
# If LD_LIBRARY_PATH is filtered, but no patch is specified, warn the user that his may not work
397399
elif (
398400
'LD_LIBRARY_PATH' in filtered_env_vars and
399401
'LIBRARY_PATH' not in filtered_env_vars and
400402
not patch_ctypes_ld_library_path
401403
):
402-
msg = "EasyBuild was configured to filter LD_LIBRARY_PATH (and not to filter LIBRARY_PATH). "
404+
msg = "EasyBuild was configured to filter $LD_LIBRARY_PATH (and not to filter $LIBRARY_PATH). "
403405
msg += "However, no patch for ctypes was specified through 'patch_ctypes_ld_library_path' in the "
404-
msg += "EasyConfig. Note that ctypes.util.find_library, ctypes.CDLL and ctypes.cdll.LoadLibrary heavily "
405-
msg += "rely on LD_LIBRARY_PATH. Without the patch, a setup without LD_LIBRARY_PATH will likely not work "
406+
msg += "easyconfig. Note that ctypes.util.find_library, ctypes.CDLL and ctypes.cdll.LoadLibrary heavily "
407+
msg += "rely on $LD_LIBRARY_PATH. Without the patch, a setup without $LD_LIBRARY_PATH will likely not work "
406408
msg += "correctly."
407409
self.log.warning(msg)
408410

@@ -722,7 +724,11 @@ def install_step(self):
722724
change_dir(cwd)
723725

724726
def _sanity_check_ctypes_ld_library_path_patch(self):
725-
"""Check that the patch for ctypes that should be applied when filtering LD_LIBRARY_PATH works"""
727+
"""
728+
Check that ctypes.util.find_library and ctypes.CDLL work as expected.
729+
When $LD_LIBRARY_PATH is filtered, a patch is required for this to work correctly
730+
(see patch_ctypes_ld_library_path).
731+
"""
726732
# Try find_library first, since ctypes.CDLL relies on that to work correctly
727733
cmd = "python -c 'from ctypes import util; print(util.find_library(\"libpython3.so\"))'"
728734
res = run_shell_cmd(cmd)
@@ -732,13 +738,15 @@ def _sanity_check_ctypes_ld_library_path_patch(self):
732738
match = re.match(pattern, out)
733739
self.log.debug(f"Matching regular expression pattern {pattern} to string {out}")
734740
if match:
735-
msg = "Call to ctypes.util.find_library('libpython3.so') succesfully found libpython3.so under the prefix "
736-
msg += "of the current python installation. indicating that the patch that fixes ctypes when EasyBuild is "
737-
msg += "configured to filter LD_LIBRARY_PATH was applied succesfully."
741+
msg = "Call to ctypes.util.find_library('libpython3.so') successfully found libpython3.so under "
742+
msg += f"the installation prefix of the current Python installation ({self.installdir}). "
743+
if self.cfg.get('patch_ctypes_ld_library_path'):
744+
msg += "This indicates that the patch that fixes ctypes when EasyBuild is "
745+
msg += "configured to filter $LD_LIBRARY_PATH was applied succesfully."
738746
self.log.info(msg)
739747
else:
740748
msg = "Finding the library libpython3.so using ctypes.util.find_library('libpython3.so') failed. "
741-
msg += "Ctypes requires a patch when EasyBuild is configured to filter LD_LIBRARY_PATH. "
749+
msg += "The ctypes Python module requires a patch when EasyBuild is configured to filter $LD_LIBRARY_PATH. "
742750
msg += "Please check if you specified a patch through patch_ctypes_ld_library_path and check "
743751
msg += "the logs to see if it applied correctly."
744752
raise EasyBuildError(msg)
@@ -750,12 +758,18 @@ def _sanity_check_ctypes_ld_library_path_patch(self):
750758
match = re.match(pattern, out)
751759
self.log.debug(f"Matching regular expression pattern {pattern} to string {out}")
752760
if match:
753-
msg = "Call to ctypes.CDLL('libpython3.so') succesfully opened libpython3.so, indicating that the patch "
754-
msg += "that fixes ctypes when EasyBuild is configured to filter LD_LIBRARY_PATH was applied succesfully."
761+
msg = "Call to ctypes.CDLL('libpython3.so') succesfully opened libpython3.so. "
762+
if self.cfg.get('patch_ctypes_ld_library_path'):
763+
msg += "This indicates that the patch that fixes ctypes when $LD_LIBRARY_PATH is not set "
764+
msg += "was applied successfully."
755765
self.log.info(msg)
766+
msg = "Call to ctypes.CDLL('libpython3.so') succesfully opened libpython3.so. "
767+
if self.cfg.get('patch_ctypes_ld_library_path'):
768+
msg += "This indicates that the patch that fixes ctypes when $LD_LIBRARY_PATH is not set "
769+
msg += "was applied successfully."
756770
else:
757771
msg = "Opening of libpython3.so using ctypes.CDLL('libpython3.so') failed. "
758-
msg += "Ctypes requires a patch when EasyBuild is configured to filter LD_LIBRARY_PATH. "
772+
msg += "The ctypes Python module requires a patch when EasyBuild is configured to filter $LD_LIBRARY_PATH. "
759773
msg += "Please check if you specified a patch through patch_ctypes_ld_library_path and check "
760774
msg += "the logs to see if it applied correctly."
761775
raise EasyBuildError(msg)
@@ -824,16 +838,10 @@ def sanity_check_step(self):
824838
if self.cfg.get('ebpythonprefixes'):
825839
self._sanity_check_ebpythonprefixes()
826840

827-
# If the conditions for applying the patch specified through patch_ctypes_ld_library_path are met, check that
828-
# the patch applied correctly (and fixed the issue). Note that the condition should be identical to the one
829-
# used to determine if the patch_ctypes_ld_library_path patch should be applied
841+
# If the conditions for applying the patch specified through patch_ctypes_ld_library_path are met,
842+
# check that a patch was applied and indeed fixed the issue
830843
filtered_env_vars = build_option('filter_env_vars') or []
831-
patch_ctypes_ld_library_path = self.cfg.get('patch_ctypes_ld_library_path')
832-
if (
833-
'LD_LIBRARY_PATH' in filtered_env_vars and
834-
'LIBRARY_PATH' not in filtered_env_vars and
835-
patch_ctypes_ld_library_path
836-
):
844+
if 'LD_LIBRARY_PATH' in filtered_env_vars and 'LIBRARY_PATH' not in filtered_env_vars:
837845
self._sanity_check_ctypes_ld_library_path_patch()
838846

839847
pyver = 'python' + self.pyshortver

0 commit comments

Comments
 (0)