summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/spack/spack/bootstrap.py53
1 files changed, 53 insertions, 0 deletions
diff --git a/lib/spack/spack/bootstrap.py b/lib/spack/spack/bootstrap.py
index b70bb906c9..fe4e0022e6 100644
--- a/lib/spack/spack/bootstrap.py
+++ b/lib/spack/spack/bootstrap.py
@@ -5,8 +5,11 @@
from __future__ import print_function
import contextlib
+import fnmatch
import json
import os
+import os.path
+import re
import sys
try:
@@ -81,6 +84,7 @@ def _try_import_from_store(module, abstract_spec_str):
sys.path.extend(module_paths)
try:
+ _fix_ext_suffix(candidate_spec)
if _python_import(module):
msg = ('[BOOTSTRAP MODULE {0}] The installed spec "{1}/{2}" '
'provides the "{0}" Python module').format(
@@ -101,6 +105,55 @@ def _try_import_from_store(module, abstract_spec_str):
return False
+def _fix_ext_suffix(candidate_spec):
+ """Fix the external suffixes of Python extensions on the fly for
+ platforms that may need it
+
+ Args:
+ candidate_spec (Spec): installed spec with a Python module
+ to be checked.
+ """
+ # Here we map target families to the patterns expected
+ # by pristine CPython. Only architectures with known issues
+ # are included. Known issues:
+ #
+ # [RHEL + ppc64le]: https://github.com/spack/spack/issues/25734
+ #
+ _suffix_to_be_checked = {
+ 'ppc64le': {
+ 'glob': '*.cpython-*-powerpc64le-linux-gnu.so',
+ 're': r'.cpython-[\w]*-powerpc64le-linux-gnu.so'
+ }
+ }
+
+ # If the current architecture is not problematic return
+ generic_target = archspec.cpu.host().family
+ if str(generic_target) not in _suffix_to_be_checked:
+ return
+
+ # If there's no EXT_SUFFIX (Python < 3.5) or the suffix matches
+ # the expectations, return since the package is surely good
+ ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')
+ if ext_suffix is None:
+ return
+
+ expected = _suffix_to_be_checked[str(generic_target)]
+ if fnmatch.fnmatch(ext_suffix, expected['glob']):
+ return
+
+ # If we are here it means the current interpreter expects different names
+ # than pristine CPython. So:
+ # 1. Find what we have
+ # 2. Compute what we want
+ # 3. Create symbolic links if they're not there already
+ extensions_on_disk = fs.find(candidate_spec.prefix, expected['glob'])
+ link_names = [re.sub(expected['re'], ext_suffix, s) for s in extensions_on_disk]
+ for file_name, link_name in zip(extensions_on_disk, link_names):
+ if os.path.exists(link_name):
+ continue
+ os.symlink(file_name, link_name)
+
+
@_bootstrapper(type='buildcache')
class _BuildcacheBootstrapper(object):
"""Install the software needed during bootstrapping from a buildcache."""