From 81305b4d1e9accbf3deafd8e127fefc467cfc99d Mon Sep 17 00:00:00 2001 From: Elliott Sales de Andrade Date: Wed, 27 Jan 2021 21:01:42 -0500 Subject: [PATCH] Backport PR #19238: Fix build with LTO disabled in environment --- .github/workflows/tests.yml | 1 + setup.py | 38 +++++++++++++++++++++++++------------ setupext.py | 1 - src/_tkagg.cpp | 8 +++++++- src/py_converters.cpp | 7 ------- src/py_converters.h | 1 - 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 132bd70949d5..253f0e8f9fb0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,6 +31,7 @@ jobs: python-version: 3.7 extra-requirements: '-r requirements/testing/travis_extra.txt' XVFB_RUN: xvfb-run -a + CFLAGS: "-fno-lto" # Ensure that disabling LTO works. - os: ubuntu-16.04 python-version: 3.8 extra-requirements: '-r requirements/testing/travis_extra.txt' diff --git a/setup.py b/setup.py index 6e1d19d4b85c..56bf9de2c71e 100644 --- a/setup.py +++ b/setup.py @@ -103,20 +103,34 @@ def add_optimization_flags(self): """ env = os.environ.copy() - if not setupext.config.getboolean('libs', 'enable_lto', fallback=True): - return env if sys.platform == 'win32': return env - - cppflags = [] - if 'CPPFLAGS' in os.environ: - cppflags.append(os.environ['CPPFLAGS']) - cxxflags = [] - if 'CXXFLAGS' in os.environ: - cxxflags.append(os.environ['CXXFLAGS']) - ldflags = [] - if 'LDFLAGS' in os.environ: - ldflags.append(os.environ['LDFLAGS']) + enable_lto = setupext.config.getboolean('libs', 'enable_lto', + fallback=None) + + def prepare_flags(name, enable_lto): + """ + Prepare *FLAGS from the environment. + + If set, return them, and also check whether LTO is disabled in each + one, raising an error if Matplotlib config explicitly enabled LTO. + """ + if name in os.environ: + if '-fno-lto' in os.environ[name]: + if enable_lto is True: + raise ValueError('Configuration enable_lto=True, but ' + '{0} contains -fno-lto'.format(name)) + enable_lto = False + return [os.environ[name]], enable_lto + return [], enable_lto + + _, enable_lto = prepare_flags('CFLAGS', enable_lto) # Only check lto. + cppflags, enable_lto = prepare_flags('CPPFLAGS', enable_lto) + cxxflags, enable_lto = prepare_flags('CXXFLAGS', enable_lto) + ldflags, enable_lto = prepare_flags('LDFLAGS', enable_lto) + + if enable_lto is False: + return env if has_flag(self.compiler, '-fvisibility=hidden'): for ext in self.extensions: diff --git a/setupext.py b/setupext.py index fda44ed7db3b..dfa004d7f09e 100644 --- a/setupext.py +++ b/setupext.py @@ -399,7 +399,6 @@ def get_extensions(self): ext = Extension( "matplotlib.backends._tkagg", [ "src/_tkagg.cpp", - "src/py_converters.cpp", ], include_dirs=["src"], # psapi library needed for finding Tcl/Tk at run time. diff --git a/src/_tkagg.cpp b/src/_tkagg.cpp index b87d118a7167..68907d0d6d16 100644 --- a/src/_tkagg.cpp +++ b/src/_tkagg.cpp @@ -37,7 +37,13 @@ // Include our own excerpts from the Tcl / Tk headers #include "_tkmini.h" -#include "py_converters.h" + +static int convert_voidptr(PyObject *obj, void *p) +{ + void **val = (void **)p; + *val = PyLong_AsVoidPtr(obj); + return *val != NULL ? 1 : !PyErr_Occurred(); +} // Global vars for Tk functions. We load these symbols from the tkinter // extension module or loaded Tk libraries at run-time. diff --git a/src/py_converters.cpp b/src/py_converters.cpp index ace8332dda76..a4c0b1909940 100644 --- a/src/py_converters.cpp +++ b/src/py_converters.cpp @@ -94,13 +94,6 @@ int convert_from_attr(PyObject *obj, const char *name, converter func, void *p) return 1; } -int convert_voidptr(PyObject *obj, void *p) -{ - void **val = (void **)p; - *val = PyLong_AsVoidPtr(obj); - return *val != NULL ? 1 : !PyErr_Occurred(); -} - int convert_double(PyObject *obj, void *p) { double *val = (double *)p; diff --git a/src/py_converters.h b/src/py_converters.h index 33af43a474e8..2c19acdaaf80 100644 --- a/src/py_converters.h +++ b/src/py_converters.h @@ -22,7 +22,6 @@ typedef int (*converter)(PyObject *, void *); int convert_from_attr(PyObject *obj, const char *name, converter func, void *p); int convert_from_method(PyObject *obj, const char *name, converter func, void *p); -int convert_voidptr(PyObject *obj, void *p); int convert_double(PyObject *obj, void *p); int convert_bool(PyObject *obj, void *p); int convert_cap(PyObject *capobj, void *capp);