diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/spack/spack/bootstrap.py | 53 |
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.""" |