Skip to content
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

matplotlib recipe #858

Merged
merged 11 commits into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from 3 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
38 changes: 38 additions & 0 deletions kivy_ios/recipes/kiwisolver/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'''
This file is derived from the p4a recipe for kiwisolver.
It is a dependency of matplotlib.

It is a C++ library, and it utilizes the cpplink script to handle
creating the library files needed for inclusion in an iOS project.

It also depends on the headers from the cppy package.
'''

from kivy_ios.toolchain import CythonRecipe
from os.path import join


class KiwiSolverRecipe(CythonRecipe):

site_packages_name = 'kiwisolver'
version = '1.3.2'
url = 'https://github.com/nucleic/kiwi/archive/{version}.zip'
depends = ["python"]
hostpython_prerequisites = ["cppy"]
cythonize = False
library = "libkiwisolver.a"

def get_recipe_env(self, arch=None, with_flags_in_cc=True):
env = super().get_recipe_env(arch)

# cpplink setup
env['CXX_ORIG'] = env['CXX']
env['CXX'] = join(self.ctx.root_dir, "tools", "cpplink")

# setuptools uses CC for compiling and CXX for linking
env['CC'] = env['CXX']
env['CFLAGS'] += ' -isysroot {}'.format(env['IOSSDKROOT'])
return env


recipe = KiwiSolverRecipe()
118 changes: 118 additions & 0 deletions kivy_ios/recipes/matplotlib/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
'''
This file is derived from the p4a recipe for matplotlib.
It is a dependency of matplotlib.

It is a C++ library, and it utilizes the cpplink script to handle
creating the library files needed for inclusion in an iOS project.

In addition to the original patch files for p4a, additional patch files
are necessary to prevent duplicate symbols from appearing in the final
link of a kivy-ios application.
'''

from kivy_ios.toolchain import CythonRecipe, ensure_dir
from os.path import join
from os.path import abspath
import shutil


class MatplotlibRecipe(CythonRecipe):
version = '3.5.2'
url = 'https://github.com/matplotlib/matplotlib/archive/v{version}.zip'
library = 'libmatplotlib.a'
depends = ['kiwisolver', 'numpy', 'pillow', 'freetype']
pre_build_ext = True
python_depends = ['cycler', 'fonttools', 'packaging',
'pyparsing', 'python-dateutil']
cythonize = False

def generate_libraries_pc_files(self, arch):
"""
Create *.pc files for libraries that `matplotib` depends on.

Because, for unix platforms, the mpl install script uses `pkg-config`
to detect libraries installed in non standard locations (our case...
well...we don't even install the libraries...so we must trick a little
the mlp install).
"""
pkg_config_path = self.get_recipe_env(arch)['PKG_CONFIG_PATH']
ensure_dir(pkg_config_path)

lib_to_pc_file = {
# `pkg-config` search for version freetype2.pc, our current
# version for freetype, but we have our recipe named without
# the version...so we add it in here for our pc file
'freetype': 'freetype2.pc',
}

for lib_name in {'freetype'}:
pc_template_file = join(
abspath(self.recipe_dir),
f'lib{lib_name}.pc.template'
)
# read template file into buffer
with open(pc_template_file) as template_file:
text_buffer = template_file.read()
# set the library absolute path and library version
lib_recipe = self.get_recipe(lib_name, self.ctx)
text_buffer = text_buffer.replace(
'path_to_built', lib_recipe.get_build_dir(arch.arch),
)
text_buffer = text_buffer.replace(
'library_version', lib_recipe.version,
)

# write the library pc file into our defined dir `PKG_CONFIG_PATH`
pc_dest_file = join(pkg_config_path, lib_to_pc_file[lib_name])
with open(pc_dest_file, 'w') as pc_file:
pc_file.write(text_buffer)

def prebuild_arch(self, arch):
if self.has_marker("patched"):
return
shutil.copyfile(
join(abspath(self.recipe_dir), "setup.cfg.template"),
join(self.get_build_dir(arch.arch), "mplsetup.cfg"),
)
self.generate_libraries_pc_files(arch)
self.apply_patch('_tri.cpp.patch')
self.apply_patch('_tri.h.patch')
self.apply_patch('_tri_wrapper.cpp.patch')
self.apply_patch('setupext.py.patch')
self.set_marker("patched")

def get_recipe_env(self, arch=None, with_flags_in_cc=True):
env = super().get_recipe_env(arch)

# we make use of the same directory than `XDG_CACHE_HOME`, for our
# custom library pc files, so we have all the install files that we
# generate at the same place
env['XDG_CACHE_HOME'] = join(
self.get_build_dir(arch.arch),
'p4a_files'
)
env['PKG_CONFIG_PATH'] = env['XDG_CACHE_HOME']

# creating proper *.pc files for our libraries does not seem enough to
# success with our build (without depending on system development
# libraries), but if we tell the compiler where to find our libraries
# and includes, then the install success :)
freetype = self.get_recipe('freetype', self.ctx)
free_inc_dir = join(freetype.get_build_dir(arch.arch), 'include')

numpytype = self.get_recipe('numpy', self.ctx)
numpy_inc_dir = join(numpytype.get_build_dir(arch.arch),
'build', 'src.macosx-13.5-arm64-3.10',
'numpy', 'core', 'include', 'numpy')

env['CFLAGS'] += f' -I{free_inc_dir} -I{numpy_inc_dir}'
env['CXX_ORIG'] = env['CXX']
env['CXX'] = join(self.ctx.root_dir, "tools", "cpplink")

# setuptools uses CC for compiling and CXX for linking
env['CFLAGS'] += ' -isysroot {}'.format(env['IOSSDKROOT'])

return env


recipe = MatplotlibRecipe()
15 changes: 15 additions & 0 deletions kivy_ios/recipes/matplotlib/_tri.cpp.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--- matplotlib-3.5.2.orig/src/tri/_tri.cpp 2022-05-02 22:49:57
+++ matplotlib-3.5.2/src/tri/_tri.cpp 2023-09-08 13:17:37
@@ -13,6 +13,7 @@
#include <algorithm>
#include <set>

+namespace tri {

TriEdge::TriEdge()
: tri(-1), edge(-1)
@@ -2069,3 +2070,4 @@
_seed = (_seed*_a + _c) % _m;
return (_seed*max_value) / _m;
}
+}
17 changes: 17 additions & 0 deletions kivy_ios/recipes/matplotlib/_tri.h.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--- matplotlib-3.5.2.orig/src/tri/_tri.h 2022-05-02 22:49:57
+++ matplotlib-3.5.2/src/tri/_tri.h 2023-09-08 13:17:12
@@ -72,6 +72,7 @@
#include <vector>


+namespace tri {

/* An edge of a triangle consisting of an triangle index in the range 0 to
* ntri-1 and an edge index in the range 0 to 2. Edge i goes from the
@@ -814,5 +815,6 @@
const unsigned long _m, _a, _c;
unsigned long _seed;
};
+}

#endif
12 changes: 12 additions & 0 deletions kivy_ios/recipes/matplotlib/_tri_wrapper.cpp.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--- matplotlib-3.5.2.orig/src/tri/_tri_wrapper.cpp 2022-05-02 22:49:57
+++ matplotlib-3.5.2/src/tri/_tri_wrapper.cpp 2023-09-08 13:23:47
@@ -1,7 +1,9 @@
#include "_tri.h"
#include "../mplutils.h"
#include "../py_exceptions.h"
+

+using namespace tri;

/* Triangulation */

10 changes: 10 additions & 0 deletions kivy_ios/recipes/matplotlib/libfreetype.pc.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
prefix=path_to_built
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/objs/.libs

Name: freetype2
Description: The freetype2 library
Version: library_version
Cflags: -I${includedir}
Libs: -L${libdir} -lfreetype
38 changes: 38 additions & 0 deletions kivy_ios/recipes/matplotlib/setup.cfg.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Rename this file to mplsetup.cfg to modify Matplotlib's build options.

[libs]
# By default, Matplotlib builds with LTO, which may be slow if you re-compile
# often, and don't need the space saving/speedup.
enable_lto = False
# By default, Matplotlib downloads and builds its own copies of FreeType and of
# Qhull. You may set the following to True to instead link against a system
# FreeType/Qhull. As an exception, Matplotlib defaults to the system version
# of FreeType on AIX.
system_freetype = True
#system_qhull = False

[packages]
# There are a number of data subpackages from Matplotlib that are
# considered optional. All except 'tests' data (meaning the baseline
# image files) are installed by default, but that can be changed here.
#tests = False

[gui_support]
# Matplotlib supports multiple GUI toolkits, known as backends.
# The MacOSX backend requires the Cocoa headers included with XCode.
# You can select whether to build it by uncommenting the following line.
# It is never built on Linux or Windows, regardless of the config value.
#
macosx = False

[rc_options]
# User-configurable options
#
# Default backend, one of: Agg, Cairo, GTK3Agg, GTK3Cairo, GTK4Agg, GTK4Cairo,
# MacOSX, Pdf, Ps, QtAgg, QtCairo, SVG, TkAgg, WX, WXAgg.
#
# The Agg, Ps, Pdf and SVG backends do not require external dependencies. Do
# not choose MacOSX if you have disabled the relevant extension modules. The
# default is determined by fallback.
#
#backend = Agg
44 changes: 44 additions & 0 deletions kivy_ios/recipes/matplotlib/setupext.py.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
--- matplotlib-3.5.2.orig/setupext.py 2023-09-08 14:01:18
+++ matplotlib-3.5.2/setupext.py 2023-09-08 13:09:10
@@ -404,7 +404,7 @@
"matplotlib._contour", [
"src/_contour.cpp",
"src/_contour_wrapper.cpp",
- "src/py_converters.cpp",
+# "src/py_converters.cpp",
])
add_numpy_flags(ext)
add_libagg_flags(ext)
@@ -414,7 +414,7 @@
"matplotlib.ft2font", [
"src/ft2font.cpp",
"src/ft2font_wrapper.cpp",
- "src/py_converters.cpp",
+# "src/py_converters.cpp",
])
FreeType.add_flags(ext)
add_numpy_flags(ext)
@@ -424,19 +424,19 @@
ext = Extension(
"matplotlib._image", [
"src/_image_wrapper.cpp",
- "src/py_converters.cpp",
+# "src/py_converters.cpp",
])
add_numpy_flags(ext)
- add_libagg_flags_and_sources(ext)
+ add_libagg_flags(ext)
yield ext
# path
ext = Extension(
"matplotlib._path", [
- "src/py_converters.cpp",
+# "src/py_converters.cpp",
"src/_path_wrapper.cpp",
])
add_numpy_flags(ext)
- add_libagg_flags_and_sources(ext)
+ add_libagg_flags(ext)
yield ext
# qhull
ext = Extension(
Loading
Loading