5
5
from __future__ import print_function
6
6
7
7
import contextlib
8
+ import fnmatch
8
9
import json
9
10
import os
11
+ import os .path
12
+ import re
10
13
import sys
11
14
12
15
try :
@@ -80,6 +83,7 @@ def _try_import_from_store(module, abstract_spec_str):
80
83
sys .path .extend (module_paths )
81
84
82
85
try :
86
+ _fix_ext_suffix (candidate_spec )
83
87
if _python_import (module ):
84
88
msg = ('[BOOTSTRAP MODULE {0}] The installed spec "{1}/{2}" '
85
89
'provides the "{0}" Python module' ).format (
@@ -100,6 +104,55 @@ def _try_import_from_store(module, abstract_spec_str):
100
104
return False
101
105
102
106
107
+ def _fix_ext_suffix (candidate_spec ):
108
+ """Fix the external suffixes of Python extensions on the fly for
109
+ platforms that may need it
110
+
111
+ Args:
112
+ candidate_spec (Spec): installed spec with a Python module
113
+ to be checked.
114
+ """
115
+ # Here we map target families to the patterns expected
116
+ # by pristine CPython. Only architectures with known issues
117
+ # are included. Known issues:
118
+ #
119
+ # [RHEL + ppc64le]: https://github.com/spack/spack/issues/25734
120
+ #
121
+ _suffix_to_be_checked = {
122
+ 'ppc64le' : {
123
+ 'glob' : '*.cpython-*-powerpc64le-linux-gnu.so' ,
124
+ 're' : r'.cpython-[\w]*-powerpc64le-linux-gnu.so'
125
+ }
126
+ }
127
+
128
+ # If the current architecture is not problematic return
129
+ generic_target = archspec .cpu .host ().family
130
+ if str (generic_target ) not in _suffix_to_be_checked :
131
+ return
132
+
133
+ # If there's no EXT_SUFFIX (Python < 3.5) or the suffix matches
134
+ # the expectations, return since the package is surely good
135
+ ext_suffix = sysconfig .get_config_var ('EXT_SUFFIX' )
136
+ if ext_suffix is None :
137
+ return
138
+
139
+ expected = _suffix_to_be_checked [str (generic_target )]
140
+ if fnmatch .fnmatch (ext_suffix , expected ['glob' ]):
141
+ return
142
+
143
+ # If we are here it means the current interpreter expects different names
144
+ # than pristine CPython. So:
145
+ # 1. Find what we have
146
+ # 2. Compute what we want
147
+ # 3. Create symbolic links if they're not there already
148
+ extensions_on_disk = fs .find (candidate_spec .prefix , expected ['glob' ])
149
+ link_names = [re .sub (expected ['re' ], ext_suffix , s ) for s in extensions_on_disk ]
150
+ for file_name , link_name in zip (extensions_on_disk , link_names ):
151
+ if os .path .exists (link_name ):
152
+ continue
153
+ os .symlink (file_name , link_name )
154
+
155
+
103
156
@_bootstrapper (type = 'buildcache' )
104
157
class _BuildcacheBootstrapper (object ):
105
158
"""Install the software needed during bootstrapping from a buildcache."""
0 commit comments