diff --git a/setup.py b/setup.py index 06cc5fc22fad..7a35e8a85d78 100644 --- a/setup.py +++ b/setup.py @@ -55,20 +55,9 @@ setupext.Matplotlib(), setupext.Python(), setupext.Platform(), - setupext.LibAgg(), setupext.FreeType(), - setupext.FT2Font(), - setupext.Qhull(), - setupext.Image(), - setupext.TTConv(), - setupext.Path(), - setupext.Contour(), - setupext.QhullWrap(), - setupext.Tri(), setupext.SampleData(), setupext.Tests(), - setupext.BackendAgg(), - setupext.BackendTkAgg(), setupext.BackendMacOSX(), ] @@ -93,8 +82,11 @@ def __init__(self, dist): class BuildExtraLibraries(BuildExtCommand): def finalize_options(self): - self.distribution.ext_modules[:] = filter( - None, (package.get_extension() for package in good_packages)) + self.distribution.ext_modules[:] = [ + ext + for package in good_packages + for ext in package.get_extensions() + ] super().finalize_options() def build_extensions(self): diff --git a/setupext.py b/setupext.py index b472a92871f1..c96fbb0b9257 100644 --- a/setupext.py +++ b/setupext.py @@ -283,13 +283,13 @@ def get_package_data(self): """ return {} - def get_extension(self): + def get_extensions(self): """ - Get a list of C extensions (`distutils.core.Extension` + Return or yield a list of C extensions (`distutils.core.Extension` objects) to add to the configuration. These are added to the `extensions` list passed to `distutils.setup`. """ - return None + return [] def do_custom_build(self): """ @@ -374,6 +374,104 @@ def get_package_data(self): ], } + def get_extensions(self): + # agg + ext = Extension( + "matplotlib.backends._backend_agg", [ + "src/mplutils.cpp", + "src/py_converters.cpp", + "src/_backend_agg.cpp", + "src/_backend_agg_wrapper.cpp", + ]) + add_numpy_flags(ext) + add_libagg_flags_and_sources(ext) + FreeType().add_flags(ext) + yield ext + # contour + ext = Extension( + "matplotlib._contour", [ + "src/_contour.cpp", + "src/_contour_wrapper.cpp", + "src/py_converters.cpp", + ]) + add_numpy_flags(ext) + add_libagg_flags(ext) + yield ext + # ft2font + ext = Extension( + "matplotlib.ft2font", [ + "src/ft2font.cpp", + "src/ft2font_wrapper.cpp", + "src/mplutils.cpp", + "src/py_converters.cpp", + ]) + FreeType().add_flags(ext) + add_numpy_flags(ext) + add_libagg_flags(ext) + yield ext + # image + ext = Extension( + "matplotlib._image", [ + "src/_image.cpp", + "src/mplutils.cpp", + "src/_image_wrapper.cpp", + "src/py_converters.cpp", + ]) + add_numpy_flags(ext) + add_libagg_flags_and_sources(ext) + yield ext + # path + ext = Extension( + "matplotlib._path", [ + "src/py_converters.cpp", + "src/_path_wrapper.cpp", + ]) + add_numpy_flags(ext) + add_libagg_flags_and_sources(ext) + yield ext + # qhull + ext = Extension( + "matplotlib._qhull", ["src/qhull_wrap.c"], + define_macros=[("MPL_DEVNULL", os.devnull)]) + add_numpy_flags(ext) + add_qhull_flags(ext) + yield ext + # tkagg + 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. + # user32 library needed for window manipulation functions. + libraries=({"linux": ["dl"], "win32": ["psapi", "user32"]} + .get(sys.platform, [])), + extra_link_args={"win32": ["-mwindows"]}.get(sys.platform, [])) + add_numpy_flags(ext) + add_libagg_flags(ext) + yield ext + # tri + ext = Extension( + "matplotlib._tri", [ + "src/tri/_tri.cpp", + "src/tri/_tri_wrapper.cpp", + "src/mplutils.cpp", + ]) + add_numpy_flags(ext) + yield ext + # ttconv + ext = Extension( + "matplotlib.ttconv", [ + "src/_ttconv.cpp", + "extern/ttconv/pprdrv_tt.cpp", + "extern/ttconv/pprdrv_tt2.cpp", + "extern/ttconv/ttutil.cpp", + ], + include_dirs=["extern"]) + add_numpy_flags(ext) + yield ext + class SampleData(OptionalPackage): """ @@ -422,26 +520,38 @@ def add_numpy_flags(ext): ]) -class LibAgg(SetupPackage): - name = 'libagg' - - def add_flags(self, ext, add_sources=True): - # We need a patched Agg not available elsewhere, so always use the - # vendored version. - ext.include_dirs.insert(0, 'extern/agg24-svn/include') - if add_sources: - agg_sources = [ - 'agg_bezier_arc.cpp', - 'agg_curves.cpp', - 'agg_image_filters.cpp', - 'agg_trans_affine.cpp', - 'agg_vcgen_contour.cpp', - 'agg_vcgen_dash.cpp', - 'agg_vcgen_stroke.cpp', - 'agg_vpgen_segmentator.cpp' - ] - ext.sources.extend(os.path.join('extern', 'agg24-svn', 'src', x) - for x in agg_sources) +def add_libagg_flags(ext): + # We need a patched Agg not available elsewhere, so always use the vendored + # version. + ext.include_dirs.insert(0, "extern/agg24-svn/include") + + +def add_libagg_flags_and_sources(ext): + # We need a patched Agg not available elsewhere, so always use the vendored + # version. + ext.include_dirs.insert(0, "extern/agg24-svn/include") + agg_sources = [ + "agg_bezier_arc.cpp", + "agg_curves.cpp", + "agg_image_filters.cpp", + "agg_trans_affine.cpp", + "agg_vcgen_contour.cpp", + "agg_vcgen_dash.cpp", + "agg_vcgen_stroke.cpp", + "agg_vpgen_segmentator.cpp", + ] + ext.sources.extend( + os.path.join("extern", "agg24-svn", "src", x) for x in agg_sources) + + +def add_qhull_flags(ext): + if options.get("system_qhull"): + ext.libraries.append("qhull") + else: + ext.include_dirs.insert(0, "extern") + ext.sources.extend(sorted(glob.glob("extern/libqhull/*.c"))) + if sysconfig.get_config_var("LIBM") == "-lm": + ext.libraries.extend("m") # First compile checkdep_freetype2.c, which aborts the compilation either @@ -575,170 +685,6 @@ def do_custom_build(self): shutil.copy2(lib_path, src_path / "objs/.libs/libfreetype.lib") -class FT2Font(SetupPackage): - name = 'ft2font' - - def get_extension(self): - sources = [ - 'src/ft2font.cpp', - 'src/ft2font_wrapper.cpp', - 'src/mplutils.cpp', - 'src/py_converters.cpp', - ] - ext = Extension('matplotlib.ft2font', sources) - FreeType().add_flags(ext) - add_numpy_flags(ext) - LibAgg().add_flags(ext, add_sources=False) - return ext - - -class Qhull(SetupPackage): - name = "qhull" - - def add_flags(self, ext): - if options.get('system_qhull'): - ext.libraries.append('qhull') - else: - ext.include_dirs.insert(0, 'extern') - ext.sources.extend(sorted(glob.glob('extern/libqhull/*.c'))) - if sysconfig.get_config_var('LIBM') == '-lm': - ext.libraries.extend('m') - - -class TTConv(SetupPackage): - name = "ttconv" - - def get_extension(self): - sources = [ - 'src/_ttconv.cpp', - 'extern/ttconv/pprdrv_tt.cpp', - 'extern/ttconv/pprdrv_tt2.cpp', - 'extern/ttconv/ttutil.cpp' - ] - ext = Extension('matplotlib.ttconv', sources) - add_numpy_flags(ext) - ext.include_dirs.insert(0, 'extern') - return ext - - -class Path(SetupPackage): - name = "path" - - def get_extension(self): - sources = [ - 'src/py_converters.cpp', - 'src/_path_wrapper.cpp' - ] - ext = Extension('matplotlib._path', sources) - add_numpy_flags(ext) - LibAgg().add_flags(ext) - return ext - - -class Image(SetupPackage): - name = "image" - - def get_extension(self): - sources = [ - 'src/_image.cpp', - 'src/mplutils.cpp', - 'src/_image_wrapper.cpp', - 'src/py_converters.cpp' - ] - ext = Extension('matplotlib._image', sources) - add_numpy_flags(ext) - LibAgg().add_flags(ext) - - return ext - - -class Contour(SetupPackage): - name = "contour" - - def get_extension(self): - sources = [ - "src/_contour.cpp", - "src/_contour_wrapper.cpp", - 'src/py_converters.cpp', - ] - ext = Extension('matplotlib._contour', sources) - add_numpy_flags(ext) - LibAgg().add_flags(ext, add_sources=False) - return ext - - -class QhullWrap(SetupPackage): - name = "qhull_wrap" - - def get_extension(self): - sources = ['src/qhull_wrap.c'] - ext = Extension('matplotlib._qhull', sources, - define_macros=[('MPL_DEVNULL', os.devnull)]) - add_numpy_flags(ext) - Qhull().add_flags(ext) - return ext - - -class Tri(SetupPackage): - name = "tri" - - def get_extension(self): - sources = [ - "src/tri/_tri.cpp", - "src/tri/_tri_wrapper.cpp", - "src/mplutils.cpp" - ] - ext = Extension('matplotlib._tri', sources) - add_numpy_flags(ext) - return ext - - -class BackendAgg(SetupPackage): - name = "agg" - - def get_extension(self): - sources = [ - "src/mplutils.cpp", - "src/py_converters.cpp", - "src/_backend_agg.cpp", - "src/_backend_agg_wrapper.cpp" - ] - ext = Extension('matplotlib.backends._backend_agg', sources) - add_numpy_flags(ext) - LibAgg().add_flags(ext) - FreeType().add_flags(ext) - return ext - - -class BackendTkAgg(SetupPackage): - name = "tkagg" - - def check(self): - return "installing; run-time loading from Python Tcl/Tk" - - def get_extension(self): - sources = [ - 'src/_tkagg.cpp', - 'src/py_converters.cpp', - ] - - ext = Extension('matplotlib.backends._tkagg', sources) - self.add_flags(ext) - add_numpy_flags(ext) - LibAgg().add_flags(ext, add_sources=False) - return ext - - def add_flags(self, ext): - ext.include_dirs.insert(0, 'src') - if sys.platform == 'win32': - # psapi library needed for finding Tcl/Tk at run time. - # user32 library needed for window manipulation functions. - ext.libraries.extend(['psapi', 'user32']) - ext.extra_link_args.extend(["-mwindows"]) - elif sys.platform == 'linux': - ext.libraries.extend(['dl']) - - class BackendMacOSX(OptionalPackage): config_category = 'gui_support' name = 'macosx' @@ -748,7 +694,7 @@ def check(self): raise CheckFailed("Mac OS-X only") return super().check() - def get_extension(self): + def get_extensions(self): sources = [ 'src/_macosx.m' ] @@ -756,4 +702,4 @@ def get_extension(self): ext.extra_link_args.extend(['-framework', 'Cocoa']) if platform.python_implementation().lower() == 'pypy': ext.extra_compile_args.append('-DPYPY=1') - return ext + yield ext