8000 Don't explicitly add default include paths to Extensions by anntzer · Pull Request #13064 · matplotlib/matplotlib · GitHub
[go: up one dir, main page]

Skip to content

Don't explicitly add default include paths to Extensions #13064

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 13, 2019
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
161 changes: 34 additions & 127 deletions setupext.py
8000
Original file line number Diff line numberDiff line change
Expand Up @@ -11,6 +11,7 @@
import pathlib
import platform
import setuptools
import shlex
import shutil
import subprocess
import sys
Expand Down Expand Up @@ -205,28 +206,6 @@ def write_cache(local_fn, data):
options['local_freetype'] = lft or options.get('local_freetype', False)


def has_include_file(include_dirs, filename):
"""
Returns `True` if *filename* can be found in one of the
directories in *include_dirs*.
"""
if sys.platform == 'win32':
include_dirs = [*include_dirs, # Don't modify it in-place.
*os.environ.get('INCLUDE', '.').split(os.pathsep)]
return any(pathlib.Path(dir, filename).exists() for dir in include_dirs)


def check_include_file(include_dirs, filename, package):
"""
Raises an exception if the given include file can not be found.
"""
if not has_include_file(include_dirs, filename):
raise CheckFailed(
"The C/C++ header for %s (%s) could not be found. You "
"may need to install the development package." %
(package, filename))


def get_base_dirs():
"""
Returns a list of standard base directories on this platform.
Expand Down Expand Up @@ -343,20 +322,17 @@ def get_buffer_hash(fd):


class PkgConfig(object):
"""
This is a class for communicating with pkg-config.
"""
"""This is a class for communicating with pkg-config."""

def __init__(self):
"""
Determines whether pkg-config exists on this machine.
"""
if sys.platform == 'win32':
self.has_pkgconfig = False
else:
self.pkg_config = os.environ.get('PKG_CONFIG', 'pkg-config')
self.set_pkgconfig_path()
self.has_pkgconfig = shutil.which(self.pkg_config) is not None
if not self.has_pkgconfig:
"""Determines whether pkg-config exists on this machine."""
self.pkg_config = None
if sys.platform != 'win32':
pkg_config = os.environ.get('PKG_CONFIG', 'pkg-config')
if shutil.which(pkg_config) is not None:
self.pkg_config = pkg_config
self.set_pkgconfig_path()
else:
print("IMPORTANT WARNING:\n"
" pkg-config is not installed.\n"
" matplotlib may not be able to find some of its dependencies")
Expand All @@ -375,52 +351,28 @@ def set_pkgconfig_path(self):
except KeyError:
os.environ['PKG_CONFIG_PATH'] = pkgconfig_path

def setup_extension(self, ext, package, default_include_dirs=[],
default_library_dirs=[], default_libraries=[],
alt_exec=None):
"""
Add parameters to the given `ext` for the given `package`.
"""
flag_map = {
'-I': 'include_dirs', '-L': 'library_dirs', '-l': 'libraries'}

executable = alt_exec
if self.has_pkgconfig:
executable = (self.pkg_config + ' {0}').format(package)

use_defaults = True

if executable is not None:
command = "{0} --libs --cflags ".format(executable)

def setup_extension(self, ext, package,
alt_exec=None, default_libraries=()):
"""Add parameters to the given *ext* for the given *package*."""
cmd = ([self.pkg_config, package] if self.pkg_config
else alt_exec)
if cmd is not None:
try:
output = subprocess.check_output(
command, shell=True, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
flags = shlex.split(subprocess.check_output(
[*cmd, "--cflags", "--libs"], universal_newlines=True))
except (OSError, subprocess.CalledProcessError):
pass
else:
output = output.decode(sys.getfilesystemencoding())
use_defaults = False
for token in output.split():
attr = flag_map.get(token[:2])
if attr is not None:
getattr(ext, attr).insert(0, token[2:])

if use_defaults:
basedirs = get_base_dirs()
for base in basedirs:
for include in default_include_dirs:
dir = os.path.join(base, include)
if os.path.exists(dir):
ext.include_dirs.append(dir)
for lib in default_library_dirs:
dir = os.path.join(base, lib)
if os.path.exists(dir):
ext.library_dirs.append(dir)
ext.libraries.extend(default_libraries)
return True

return False
# In theory, one could call pkg-config separately with --cflags
# and --libs and use them to fill extra_compile_args and
# extra_link_args respectively, but keeping all the flags
# together works as well and makes it simpler to handle
# libpng-config, which has --ldflags instead of --libs.
ext.extra_compile_args.extend(flags)
ext.extra_link_args.extend(flags)
return
# Else, fall back on the defaults.
ext.libraries.extend(default_libraries)

def get_version(self, package):
"""
Expand Down Expand Up @@ -523,47 +475,6 @@ def get_setup_requires(self):
"""
return []

def _check_for_pkg_config(self, package, include_file, min_version=None,
version=None):
"""
A convenience function for writing checks for a
pkg_config-defined dependency.

`package` is the pkg_config package name.

`include_file` is a top-level include file we expect to find.

`min_version` is the minimum version required.

`version` will override the found version if this package
requires an alternate method for that. Set version='unknown'
if the version is not known but you still want to disabled
pkg_config version check.
"""
if version is None:
version = pkg_config.get_version(package)

if version is None:
raise CheckFailed(
"pkg-config information for '%s' could not be found." %
package)

if min_version and version != 'unknown':
if not is_min_version(version, min_version):
raise CheckFailed(
"Requires %s %s or later. Found %s." %
(package, min_version, version))

ext = self.get_extension()
if ext is None:
ext = make_extension('test', [])
pkg_config.setup_extension(ext, package)

check_include_file(
ext.include_dirs + get_include_dirs(), include_file, package)

return 'version %s' % version

def do_custom_build(self):
"""
If a package needs to do extra custom things, such as building a
Expand Down Expand Up @@ -869,12 +780,7 @@ def add_flags(self, ext):
else:
pkg_config.setup_extension(
ext, 'freetype2',
default_include_dirs=[
'include/freetype2', 'freetype2',
'lib/freetype2/include',
'lib/freetype2/include/freetype2'],
default_library_dirs=[
'freetype2/lib'],
alt_exec=['freetype-config', '--cflags', '--libs'],
default_libraries=['freetype', 'z'])
ext.define_macros.append(('FREETYPE_BUILD_TYPE', 'system'))

Expand Down Expand Up @@ -1017,8 +923,9 @@ def get_extension(self):
]
ext = make_extension('matplotlib._png', sources)
pkg_config.setup_extension(
ext, 'libpng', default_libraries=['png', 'z'],
alt_exec='libpng-config --ldflags')
ext, 'libpng',
alt_exec=['libpng-config', '--cflags', '--ldflags'],
default_libraries=['png', 'z'])
Numpy().add_flags(ext)
return ext

Expand Down
0