8000 Kill the PkgConfig singleton in setupext. · matplotlib/matplotlib@9869c20 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9869c20

Browse files
committed
Kill the PkgConfig singleton in setupext.
PkgConfig.setup_extension works just fine as a free-standing function.
1 parent 4e5d83e commit 9869c20

File tree

1 file changed

+62
-71
lines changed

1 file changed

+62
-71
lines changed

setupext.py

Lines changed: 62 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import configparser
22
from distutils import sysconfig
33
from distutils.core import Extension
4-
from io import BytesIO
4+
import functools
55
import glob
66
import hashlib
7+
from io import BytesIO
78
import logging
89
import os
910
import pathlib
@@ -203,83 +204,73 @@ def get_buffer_hash(fd):
203204
return hasher.hexdigest()
204205

205206

206-
class PkgConfig(object):
207-
"""This is a class for communicating with pkg-config."""
208-
209-
def __init__(self):
210-
"""Determines whether pkg-config exists on this machine."""
211-
self.pkg_config = None
212-
if sys.platform != 'win32':
213-
pkg_config = os.environ.get('PKG_CONFIG', 'pkg-config')
214-
if shutil.which(pkg_config) is not None:
215-
self.pkg_config = pkg_config
216-
self.set_pkgconfig_path()
217-
else:
218-
print("IMPORTANT WARNING:\n"
219-
" pkg-config is not installed.\n"
220-
" matplotlib may not be able to find some of its dependencies")
221-
222-
def set_pkgconfig_path(self):
223-
pkgconfig_path = sysconfig.get_config_var('LIBDIR')
224-
if pkgconfig_path is None:
225-
return
226-
227-
pkgconfig_path = os.path.join(pkgconfig_path, 'pkgconfig')
228-
if not os.path.isdir(pkgconfig_path):
229-
return
230-
207+
@functools.lru_cache(1) # We only need to compute this once.
208+
def get_pkg_config():
209+
"""
210+
Get path to pkg-config and set up the PKG_CONFIG environment variable.
211+
"""
212+
if sys.platform == 'win32':
213+
return None
214+
pkg_config = os.environ.get('PKG_CONFIG', 'pkg-config')
215+
if shutil.which(pkg_config) is None:
216+
print("IMPORTANT WARNING:\n"
217+
" pkg-config is not installed.\n"
218+
" matplotlib may not be able to find some of its dependencies.")
219+
return None
220+
pkg_config_path = sysconfig.get_config_var('LIBDIR')
221+
if pkg_config_path is not None:
222+
pkg_config_path = os.path.join(pkg_config_path, 'pkgconfig')
231223
try:
232-
os.environ['PKG_CONFIG_PATH'] += ':' + pkgconfig_path
224+
os.environ['PKG_CONFIG_PATH'] += ':' + pkg_config_path
233225
except KeyError:
234-
os.environ['PKG_CONFIG_PATH'] = pkgconfig_path
226+
os.environ['PKG_CONFIG_PATH'] = pkg_config_path
227+
return pkg_config
235228

236-
def setup_extension(
237-
self, ext, package,
238-
atleast_version=None, alt_exec=None, default_libraries=()):
239-
"""Add parameters to the given *ext* for the given *package*."""
240229

241-
# First, try to get the flags from pkg-config.
242-
243-
cmd = ([self.pkg_config, package] if self.pkg_config else alt_exec)
244-
if cmd is not None:
245-
try:
246-
if self.pkg_config and atleast_version:
247-
subprocess.check_call(
248-
[*cmd, f"--atleast-version={atleast_version}"])
249-
# Use sys.getfilesystemencoding() to allow round-tripping
250-
# when passed back to later subprocess calls; do not use
251-
# locale.getpreferredencoding() which universal_newlines=True
252-
# would do.
253-
cflags = shlex.split(
254-
os.fsdecode(subprocess.check_output([*cmd, "--cflags"])))
255-
libs = shlex.split(
256-
os.fsdecode(subprocess.check_output([*cmd, "--libs"])))
257-
except (OSError, subprocess.CalledProcessError):
258-
pass
259-
else:
260-
ext.extra_compile_args.extend(cflags)
261-
ext.extra_link_args.extend(libs)
262-
return
230+
def pkg_config_setup_extension(
231+
ext, package,
232+
atleast_version=None, alt_exec=None, default_libraries=()):
233+
"""Add parameters to the given *ext* for the given *package*."""
263234

264-
# If that fails, fall back on the defaults.
235+
# First, try to get the flags from pkg-config.
265236

266-
# conda Windows header and library paths.
267-
# https://github.com/conda/conda/issues/2312 re: getting the env dir.
268-
if sys.platform == 'win32':
269-
conda_env_path = (os.getenv('CONDA_PREFIX') # conda >= 4.1
270-
or os.getenv('CONDA_DEFAULT_ENV')) # conda < 4.1
271-
if conda_env_path and os.path.isdir(conda_env_path):
272-
ext.include_dirs.append(os.fspath(
273-
pathlib.Path(conda_env_path, "Library/include")))
274-
ext.library_dirs.append(os.fspath(
275-
pathlib.Path(conda_env_path, "Library/lib")))
237+
pkg_config = get_pkg_config()
238+
cmd = [pkg_config, package] if pkg_config else alt_exec
239+
if cmd is not None:
240+
try:
241+
if pkg_config and atleast_version:
242+
subprocess.check_call(
243+
[*cmd, f"--atleast-version={atleast_version}"])
244+
# Use sys.getfilesystemencoding() to allow round-tripping
245+
# when passed back to later subprocess calls; do not use
246+
# locale.getpreferredencoding() which universal_newlines=True
247+
# would do.
248+
cflags = shlex.split(
249+
os.fsdecode(subprocess.check_output([*cmd, "--cflags"])))
250+
libs = shlex.split(
251+
os.fsdecode(subprocess.check_output([*cmd, "--libs"])))
252+
except (OSError, subprocess.CalledProcessError):
253+
pass
254+
else:
255+
ext.extra_compile_args.extend(cflags)
256+
ext.extra_link_args.extend(libs)
257+
return
276258

277-
# Default linked libs.
278-
ext.libraries.extend(default_libraries)
259+
# If that fails, fall back on the defaults.
279260

261+
# conda Windows header and library paths.
262+
# https://github.com/conda/conda/issues/2312 re: getting the env dir.
263+
if sys.platform == 'win32':
264+
conda_env_path = (os.getenv('CONDA_PREFIX') # conda >= 4.1
265+
or os.getenv('CONDA_DEFAULT_ENV')) # conda < 4.1
266+
if conda_env_path and os.path.isdir(conda_env_path):
267+
ext.include_dirs.append(os.fspath(
268+
pathlib.Path(conda_env_path, "Library/include")))
269+
ext.library_dirs.append(os.fspath(
270+
pathlib.Path(conda_env_path, "Library/lib")))
280271

281-
# The PkgConfig class should be used through this singleton
282-
pkg_config = PkgConfig()
272+
# Default linked libs.
273+
ext.libraries.extend(default_libraries)
283274

284275

285276
class CheckFailed(Exception):
@@ -577,7 +568,7 @@ def add_flags(self, ext):
577568
0, os.path.join(src_path, 'objs', '.libs', libfreetype))
578569
ext.define_macros.append(('FREETYPE_BUILD_TYPE', 'local'))
579570
else:
580-
pkg_config.setup_extension(
571+
pkg_config_setup_extension(
581572
# FreeType 2.3 has libtool version 9.11.3 as can be checked
582573
# from the tarball. For FreeType>=2.4, there is a conversion
583574
# table in docs/VERSIONS.txt in the FreeType source tree.
@@ -724,7 +715,7 @@ def get_extension(self):
724715
'src/mplutils.cpp',
725716
]
726717
ext = Extension('matplotlib._png', sources)
727-
pkg_config.setup_extension(
718+
pkg_config_setup_extension(
728719
ext, 'libpng',
729720
atleast_version='1.2',
730721
alt_exec=['libpng-config', '--ldflags'],

0 commit comments

Comments
 (0)
0