summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/spack/build_systems/python.py16
-rw-r--r--lib/spack/spack/build_systems/sip.py5
-rw-r--r--var/spack/repos/builtin/packages/clingo/package.py3
-rw-r--r--var/spack/repos/builtin/packages/migraphx/package.py3
-rw-r--r--var/spack/repos/builtin/packages/python/package.py176
5 files changed, 90 insertions, 113 deletions
diff --git a/lib/spack/spack/build_systems/python.py b/lib/spack/spack/build_systems/python.py
index 27b1d4a10c..c3bf323d84 100644
--- a/lib/spack/spack/build_systems/python.py
+++ b/lib/spack/spack/build_systems/python.py
@@ -127,7 +127,10 @@ class PythonPackage(PackageBase):
list: list of strings of module names
"""
modules = []
- root = self.spec['python'].package.get_python_lib(prefix=self.prefix)
+ root = os.path.join(
+ self.prefix,
+ self.spec['python'].package.config_vars['python_lib']['false']['false'],
+ )
# Some Python libraries are packages: collections of modules
# distributed in directories containing __init__.py files
@@ -252,12 +255,11 @@ class PythonPackage(PackageBase):
# Get all relative paths since we set the root to `prefix`
# We query the python with which these will be used for the lib and inc
# directories. This ensures we use `lib`/`lib64` as expected by python.
- pure_site_packages_dir = spec['python'].package.get_python_lib(
- plat_specific=False, prefix='')
- plat_site_packages_dir = spec['python'].package.get_python_lib(
- plat_specific=True, prefix='')
- inc_dir = spec['python'].package.get_python_inc(
- plat_specific=True, prefix='')
+ pure_site_packages_dir = spec['python'].package.config_vars[
+ 'python_lib']['false']['false']
+ plat_site_packages_dir = spec['python'].package.config_vars[
+ 'python_lib']['true']['false']
+ inc_dir = spec['python'].package.config_vars['python_inc']['true']
args += ['--root=%s' % prefix,
'--install-purelib=%s' % pure_site_packages_dir,
diff --git a/lib/spack/spack/build_systems/sip.py b/lib/spack/spack/build_systems/sip.py
index 744989e2d6..1b9d01fbf4 100644
--- a/lib/spack/spack/build_systems/sip.py
+++ b/lib/spack/spack/build_systems/sip.py
@@ -64,7 +64,10 @@ class SIPPackage(PackageBase):
list: list of strings of module names
"""
modules = []
- root = self.spec['python'].package.get_python_lib(prefix=self.prefix)
+ root = os.path.join(
+ self.prefix,
+ self.spec['python'].package.config_vars['python_lib']['false']['false'],
+ )
# Some Python libraries are packages: collections of modules
# distributed in directories containing __init__.py files
diff --git a/var/spack/repos/builtin/packages/clingo/package.py b/var/spack/repos/builtin/packages/clingo/package.py
index 6c716fce73..aa9772109b 100644
--- a/var/spack/repos/builtin/packages/clingo/package.py
+++ b/var/spack/repos/builtin/packages/clingo/package.py
@@ -66,7 +66,8 @@ class Clingo(CMakePackage):
current spec is the one found by CMake find_package(Python, ...)
"""
python_spec = self.spec['python']
- include_dir = python_spec.package.get_python_inc()
+ include_dir = join_path(
+ python_spec.prefix, python_spec.package.config_vars['python_inc']['false'])
return [
self.define('Python_EXECUTABLE', str(python_spec.command)),
self.define('Python_INCLUDE_DIR', include_dir)
diff --git a/var/spack/repos/builtin/packages/migraphx/package.py b/var/spack/repos/builtin/packages/migraphx/package.py
index ffccce8057..9e2c316e28 100644
--- a/var/spack/repos/builtin/packages/migraphx/package.py
+++ b/var/spack/repos/builtin/packages/migraphx/package.py
@@ -62,7 +62,8 @@ class Migraphx(CMakePackage):
CMake based on current spec
"""
python_spec = self.spec['python']
- include_dir = python_spec.package.get_python_inc()
+ include_dir = join_path(
+ python_spec.prefix, python_spec.package.config_vars['python_inc']['false'])
return [
self.define('Python_INCLUDE_DIR', include_dir)
]
diff --git a/var/spack/repos/builtin/packages/python/package.py b/var/spack/repos/builtin/packages/python/package.py
index 1f5f2046f0..470b05f6ac 100644
--- a/var/spack/repos/builtin/packages/python/package.py
+++ b/var/spack/repos/builtin/packages/python/package.py
@@ -3,6 +3,7 @@
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
+import json
import os
import platform
import re
@@ -231,8 +232,8 @@ class Python(AutotoolsPackage):
conflicts('%nvhpc')
- # Used to cache home locations, since computing them might be expensive
- _homes = {}
+ # Used to cache various attributes that are expensive to compute
+ _config_vars = {}
# An in-source build with --enable-optimizations fails for python@3.X
build_directory = 'spack-build'
@@ -506,7 +507,7 @@ class Python(AutotoolsPackage):
kwargs = {'ignore_absent': True, 'backup': False, 'string': True}
filenames = [
- self.get_sysconfigdata_name(), self.get_makefile_filename()
+ self.get_sysconfigdata_name(), self.config_vars['makefile_filename']
]
filter_file(spack_cc, self.compiler.cc, *filenames, **kwargs)
@@ -686,87 +687,59 @@ class Python(AutotoolsPackage):
else:
return 'print({0})'.format(string)
- def get_config_var(self, key):
- """Return the value of a single variable. Wrapper around
- ``distutils.sysconfig.get_config_var()``."""
-
- cmd = 'from distutils.sysconfig import get_config_var; '
- cmd += self.print_string("get_config_var('{0}')".format(key))
-
- return self.command('-c', cmd, output=str).strip()
-
- def get_config_h_filename(self):
- """Return the full path name of the configuration header.
- Wrapper around ``distutils.sysconfig.get_config_h_filename()``."""
-
- cmd = 'from distutils.sysconfig import get_config_h_filename; '
- cmd += self.print_string('get_config_h_filename()')
-
- return self.command('-c', cmd, output=str).strip()
-
- def get_makefile_filename(self):
- """Return the full path name of ``Makefile`` used to build Python.
- Wrapper around ``distutils.sysconfig.get_makefile_filename()``."""
-
- cmd = 'from distutils.sysconfig import get_makefile_filename; '
- cmd += self.print_string('get_makefile_filename()')
-
- return self.command('-c', cmd, output=str).strip()
-
- def get_python_inc(self, plat_specific=False, prefix=None):
- """Return the directory for either the general or platform-dependent C
- include files. Wrapper around ``distutils.sysconfig.get_python_inc()``.
-
- Parameters:
- plat_specific (bool): if true, the platform-dependent include directory
- is returned, else the platform-independent directory is returned
- prefix (str): prefix to use instead of ``distutils.sysconfig.PREFIX``
-
- Returns:
- str: include files directory
- """
- # Wrap strings in quotes
- if prefix is not None:
- prefix = '"{0}"'.format(prefix)
-
- args = 'plat_specific={0}, prefix={1}'.format(plat_specific, prefix)
-
- cmd = 'from distutils.sysconfig import get_python_inc; '
- cmd += self.print_string('get_python_inc({0})'.format(args))
-
- return self.command('-c', cmd, output=str).strip()
-
- def get_python_lib(self, plat_specific=False, standard_lib=False, prefix=None):
- """Return the directory for either the general or platform-dependent
- library installation. Wrapper around ``distutils.sysconfig.get_python_lib()``.
+ @property
+ def config_vars(self):
+ """Return a set of variable definitions associated with a Python installation.
- Parameters:
- plat_specific (bool): if true, the platform-dependent library directory
- is returned, else the platform-independent directory is returned
- standard_lib (bool): if true, the directory for the standard library is
- returned rather than the directory for the installation of
- third-party extensions
- prefix (str): prefix to use instead of ``distutils.sysconfig.PREFIX``
+ Wrapper around various ``distutils.sysconfig`` functions.
Returns:
- str: library installation directory
+ dict: variable definitions
"""
- # Wrap strings in quotes
- if prefix is not None:
- prefix = '"{0}"'.format(prefix)
+ # TODO: distutils is deprecated in Python 3.10 and will be removed in
+ # Python 3.12, find a different way to access this information.
+ # Also, calling the python executable disallows us from cross-compiling,
+ # so we want to try to avoid that if possible.
+ cmd = """
+import json
+from distutils.sysconfig import (
+ get_config_vars,
+ get_config_h_filename,
+ get_makefile_filename,
+ get_python_inc,
+ get_python_lib,
+)
+
+config = get_config_vars()
+config['config_h_filename'] = get_config_h_filename()
+config['makefile_filename'] = get_makefile_filename()
+config['python_inc'] = {}
+config['python_lib'] = {}
+
+for plat_specific in [True, False]:
+ config['python_inc'][plat_specific] = get_python_inc(plat_specific, prefix='')
+ config['python_lib'][plat_specific] = {}
+ for standard_lib in [True, False]:
+ config['python_lib'][plat_specific][standard_lib] = get_python_lib(
+ plat_specific, standard_lib, prefix=''
+ )
+
+%s
+""" % self.print_string("json.dumps(config)")
- args = 'plat_specific={0}, standard_lib={1}, prefix={2}'.format(
- plat_specific, standard_lib, prefix)
-
- cmd = 'from distutils.sysconfig import get_python_lib; '
- cmd += self.print_string('get_python_lib({0})'.format(args))
-
- return self.command('-c', cmd, output=str).strip()
+ dag_hash = self.spec.dag_hash()
+ if dag_hash not in self._config_vars:
+ try:
+ config = json.loads(self.command('-c', cmd, output=str))
+ except (ProcessError, RuntimeError):
+ config = {}
+ self._config_vars[dag_hash] = config
+ return self._config_vars[dag_hash]
def get_sysconfigdata_name(self):
"""Return the full path name of the sysconfigdata file."""
- libdest = self.get_config_var('LIBDEST')
+ libdest = self.config_vars['LIBDEST']
filename = '_sysconfigdata.py'
if self.spec.satisfies('@3.6:'):
@@ -790,14 +763,11 @@ class Python(AutotoolsPackage):
determine exactly where it is installed. Fall back on
``spec['python'].prefix`` if that doesn't work."""
- dag_hash = self.spec.dag_hash()
- if dag_hash not in self._homes:
- try:
- prefix = self.get_config_var('prefix')
- except ProcessError:
- prefix = self.prefix
- self._homes[dag_hash] = Prefix(prefix)
- return self._homes[dag_hash]
+ if 'prefix' in self.config_vars:
+ prefix = self.config_vars['prefix']
+ else:
+ prefix = self.prefix
+ return Prefix(prefix)
@property
def libs(self):
@@ -805,19 +775,19 @@ class Python(AutotoolsPackage):
# installs them into lib64. If the user is using an externally
# installed package, it may be in either lib or lib64, so we need
# to ask Python where its LIBDIR is.
- libdir = self.get_config_var('LIBDIR')
+ libdir = self.config_vars['LIBDIR']
# In Ubuntu 16.04.6 and python 2.7.12 from the system, lib could be
# in LBPL
# https://mail.python.org/pipermail/python-dev/2013-April/125733.html
- libpl = self.get_config_var('LIBPL')
+ libpl = self.config_vars['LIBPL']
# The system Python installation on macOS and Homebrew installations
# install libraries into a Frameworks directory
- frameworkprefix = self.get_config_var('PYTHONFRAMEWORKPREFIX')
+ frameworkprefix = self.config_vars['PYTHONFRAMEWORKPREFIX']
if '+shared' in self.spec:
- ldlibrary = self.get_config_var('LDLIBRARY')
+ ldlibrary = self.config_vars['LDLIBRARY']
if os.path.exists(os.path.join(libdir, ldlibrary)):
return LibraryList(os.path.join(libdir, ldlibrary))
@@ -829,7 +799,7 @@ class Python(AutotoolsPackage):
msg = 'Unable to locate {0} libraries in {1}'
raise RuntimeError(msg.format(ldlibrary, libdir))
else:
- library = self.get_config_var('LIBRARY')
+ library = self.config_vars['LIBRARY']
if os.path.exists(os.path.join(libdir, library)):
return LibraryList(os.path.join(libdir, library))
@@ -841,16 +811,16 @@ class Python(AutotoolsPackage):
@property
def headers(self):
- try:
- config_h = self.get_config_h_filename()
+ if 'config_h_filename' in self.config_vars:
+ config_h = self.config_vars['config_h_filename']
if not os.path.exists(config_h):
- includepy = self.get_config_var('INCLUDEPY')
+ includepy = self.config_vars['INCLUDEPY']
msg = 'Unable to locate {0} headers in {1}'
raise RuntimeError(msg.format(self.name, includepy))
headers = HeaderList(config_h)
- except ProcessError:
+ else:
headers = find_headers(
'pyconfig', self.prefix.include, recursive=True)
config_h = headers[0]
@@ -871,9 +841,9 @@ class Python(AutotoolsPackage):
Returns:
str: include files directory
"""
- try:
- return self.get_python_inc(prefix='')
- except (ProcessError, RuntimeError):
+ if 'python_inc' in self.config_vars:
+ return self.config_vars['python_inc']['false']
+ else:
return os.path.join('include', 'python{0}'.format(self.version.up_to(2)))
@property
@@ -895,9 +865,9 @@ class Python(AutotoolsPackage):
Returns:
str: standard library directory
"""
- try:
- return self.get_python_lib(standard_lib=True, prefix='')
- except (ProcessError, RuntimeError):
+ if 'python_lib' in self.config_vars:
+ return self.config_vars['python_lib']['false']['true']
+ else:
return os.path.join('lib', 'python{0}'.format(self.version.up_to(2)))
@property
@@ -919,9 +889,9 @@ class Python(AutotoolsPackage):
Returns:
str: site-packages directory
"""
- try:
- return self.get_python_lib(prefix='')
- except (ProcessError, RuntimeError):
+ if 'python_lib' in self.config_vars:
+ return self.config_vars['python_lib']['false']['false']
+ else:
return self.default_site_packages_dir
@property
@@ -978,8 +948,8 @@ class Python(AutotoolsPackage):
for compile_var, link_var in [('CC', 'LDSHARED'),
('CXX', 'LDCXXSHARED')]:
# First, we get the values from the sysconfigdata:
- config_compile = self.get_config_var(compile_var)
- config_link = self.get_config_var(link_var)
+ config_compile = self.config_vars[compile_var]
+ config_link = self.config_vars[link_var]
# The dependent environment will have the compilation command set to
# the following: