From 3ba88a750970a995fd295e92dbf231dcb6a13d6c Mon Sep 17 00:00:00 2001
From: Sergey Kosukhin <skosukhin@gmail.com>
Date: Thu, 8 Dec 2016 13:39:10 +0100
Subject: [PATCH] Updated python: pass LDSHARED to dependants' setup scripts.

---
 .../repos/builtin/packages/python/package.py  | 88 +++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/var/spack/repos/builtin/packages/python/package.py b/var/spack/repos/builtin/packages/python/package.py
index 2eab9fa558..b5c11ee527 100644
--- a/var/spack/repos/builtin/packages/python/package.py
+++ b/var/spack/repos/builtin/packages/python/package.py
@@ -22,12 +22,14 @@
 # License along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 ##############################################################################
+import ast
 import os
 import re
 from contextlib import closing
 
 import spack
 import llnl.util.tty as tty
+import yaml
 from llnl.util.lang import match_predicate
 from spack import *
 from spack.util.environment import *
@@ -132,6 +134,8 @@ def install(self, spec, prefix):
         make()
         make('install')
 
+        self.save_distutils_data(prefix)
+
         self.filter_compilers(prefix)
 
         # TODO:
@@ -172,6 +176,84 @@ def install(self, spec, prefix):
     #            >>> import Tkinter
     #            >>> Tkinter._test()
 
+    def save_distutils_data(self, prefix):
+        """
+        Run before changing automatically generated contents of the
+        _sysconfigdata.py, which is used by distutils to figure out what
+        executables to use while compiling and linking extensions. If we build
+        extensions with spack those executables should be spack's wrappers.
+        Spack partially covers this by setting environment variables that
+        are also accounted for by distutils. Currently there is one more known
+        variable that must be set, which is LDSHARED, so the method saves its
+        autogenerated value to pass it to the dependant package's setup script.
+        """
+
+        input_filename = None
+        for filename in [join_path(lib_dir,
+                                   'python{0}'.format(self.version.up_to(2)),
+                                   '_sysconfigdata.py')
+                         for lib_dir in [prefix.lib, prefix.lib64]]:
+            if os.path.isfile(filename):
+                input_filename = filename
+                break
+
+        if not input_filename:
+            return
+
+        input_dict = None
+
+        try:
+            with open(input_filename) as input_file:
+                match = re.search(r'build_time_vars\s*=\s*(?P<dict>{.*})',
+                                  input_file.read(),
+                                  flags=re.DOTALL)
+
+                if match:
+                    input_dict = ast.literal_eval(match.group('dict'))
+        except (IOError, SyntaxError):
+            pass
+
+        if not input_dict:
+            return
+
+        vars_to_save = ['LDSHARED']
+        saved_vars = {}
+
+        for var_name in vars_to_save:
+            if var_name in input_dict:
+                saved_vars[var_name] = input_dict[var_name]
+
+        if len(saved_vars) > 0:
+            try:
+                output_filename = join_path(
+                    spack.store.layout.metadata_path(self.spec),
+                    'sysconfig.yaml')
+                with open(output_filename, 'w') as output_file:
+                    yaml.dump(saved_vars, stream=output_file,
+                              default_flow_style=False)
+            except (yaml.YAMLError, IOError):
+                pass
+
+        setattr(self, '_distutils_data_cache', saved_vars)
+
+    def load_distutils_data(self):
+        if not hasattr(self, '_distutils_data_cache'):
+            input_filename = join_path(
+                spack.store.layout.metadata_path(self.spec),
+                'sysconfig.yaml')
+            if os.path.isfile(input_filename):
+                try:
+                    with open(input_filename) as input_file:
+                        setattr(self, '_distutils_data_cache',
+                                yaml.load(input_file))
+                except (yaml.YAMLError, IOError):
+                    pass
+                
+            if not hasattr(self, '_distutils_data_cache'):
+                setattr(self, '_distutils_data_cache', None)
+
+        return self._distutils_data_cache
+
     def filter_compilers(self, prefix):
         """Run after install to tell the configuration files and Makefiles
         to use the compilers that Spack built the package with.
@@ -268,6 +350,12 @@ def setup_dependent_package(self, module, ext_spec):
         module.python = Executable(python_path)
         module.setup_py = Executable(python_path + ' setup.py --no-user-cfg')
 
+        distutils_data = self.load_distutils_data()
+
+        if distutils_data:
+            for key, value in distutils_data.iteritems():
+                module.setup_py.add_default_env(key, value)
+
         # Add variables for lib/pythonX.Y and lib/pythonX.Y/site-packages dirs.
         module.python_lib_dir = join_path(ext_spec.prefix,
                                           self.python_lib_dir)
-- 
GitLab