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

Updates matplotlib, fixes an issue related to shared libc++ #2645

Merged
merged 2 commits into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
18 changes: 2 additions & 16 deletions pythonforandroid/recipe.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ class Recipe(with_metaclass(RecipeMeta)):
"""

need_stl_shared = False
'''Some libraries or python packages may need to be linked with android's
stl. We can automatically do this for any recipe if we set this property to
'''Some libraries or python packages may need the c++_shared in APK.
We can automatically do this for any recipe if we set this property to
`True`'''

stl_lib_name = 'c++_shared'
Expand Down Expand Up @@ -492,20 +492,6 @@ def get_recipe_env(self, arch=None, with_flags_in_cc=True):
if arch is None:
arch = self.filtered_archs[0]
env = arch.get_env(with_flags_in_cc=with_flags_in_cc)

if self.need_stl_shared:
env['CPPFLAGS'] = env.get('CPPFLAGS', '')
env['CPPFLAGS'] += ' -I{}'.format(self.ctx.ndk.libcxx_include_dir)

env['CXXFLAGS'] = env['CFLAGS'] + ' -frtti -fexceptions'

if with_flags_in_cc:
env['CXX'] += ' -frtti -fexceptions'

env['LDFLAGS'] += ' -L{}'.format(arch.ndk_lib_dir)
env['LIBS'] = env.get('LIBS', '') + " -l{}".format(
self.stl_lib_name
)
return env

def prebuild_arch(self, arch):
Expand Down
5 changes: 1 addition & 4 deletions pythonforandroid/recipes/cppy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@

class CppyRecipe(PythonRecipe):
site_packages_name = 'cppy'

# Pin to commit: `Nucleic migration and project documentation`,
# because the official releases are too old, at time of writing
version = '4e0b956'
version = '1.1.0'
url = 'https://github.com/nucleic/cppy/archive/{version}.zip'
call_hostpython_via_targetpython = False
# to be detected by the matplotlib install script
Expand Down
21 changes: 1 addition & 20 deletions pythonforandroid/recipes/kiwisolver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,9 @@

class KiwiSolverRecipe(CppCompiledComponentsPythonRecipe):
site_packages_name = 'kiwisolver'
# Pin to commit `docs: attempt to fix doc building`, the latest one
# at the time of writing, just to be sure that we have te most up to date
# version, but it should be pinned to an official release once the c++
# changes that we want to include are merged to master branch
# Note: the commit we want to include is
# `Cppy use update and c++11 compatibility` (4858730)
version = '0846189'
version = '1.3.2'
url = 'https://github.com/nucleic/kiwi/archive/{version}.zip'
depends = ['cppy']

def get_recipe_env(self, arch=None, with_flags_in_cc=True):
env = super().get_recipe_env(arch, with_flags_in_cc)
if self.need_stl_shared:
# kiwisolver compile flags does not honor the standard flags:
# `CPPFLAGS` and `LDLIBS`, so we put in `CFLAGS` and `LDFLAGS` to
# correctly link with the `c++_shared` library
env['CFLAGS'] += f' -I{self.ctx.ndk.libcxx_include_dir}'
env['CFLAGS'] += ' -frtti -fexceptions'

env['LDFLAGS'] += f' -L{arch.ndk_lib_dir}'
env['LDFLAGS'] += f' -l{self.stl_lib_name}'
return env


recipe = KiwiSolverRecipe()
91 changes: 11 additions & 80 deletions pythonforandroid/recipes/matplotlib/__init__.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,18 @@

from pythonforandroid.logger import info_notify
from pythonforandroid.recipe import CppCompiledComponentsPythonRecipe
from pythonforandroid.util import ensure_dir

from os.path import join
import shutil


class MatplotlibRecipe(CppCompiledComponentsPythonRecipe):

version = '3.1.3'
version = '3.5.2'
url = 'https://github.com/matplotlib/matplotlib/archive/v{version}.zip'

depends = ['numpy', 'png', 'setuptools', 'freetype', 'kiwisolver']

python_depends = ['pyparsing', 'cycler', 'python-dateutil']

# We need to patch to:
# - make mpl install work without importing numpy
# - make mpl use shared libraries for freetype and png
# - make mpl link to png16, to match p4a library name for png
# - prevent mpl trying to build TkAgg, which wouldn't work
# on Android anyway but has build issues
patches = ['mpl_android_fixes.patch']
depends = ['kiwisolver', 'numpy', 'pillow', 'setuptools', 'freetype']

call_hostpython_via_targetpython = False
python_depends = ['cycler', 'fonttools', 'packaging', 'pyparsing', 'python-dateutil']

def generate_libraries_pc_files(self, arch):
"""
Expand All @@ -42,10 +31,9 @@ def generate_libraries_pc_files(self, arch):
# 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',
'png': 'png.pc',
}

for lib_name in {'freetype', 'png'}:
for lib_name in {'freetype'}:
pc_template_file = join(
self.get_recipe_dir(),
f'lib{lib_name}.pc.template'
Expand All @@ -67,83 +55,26 @@ def generate_libraries_pc_files(self, arch):
with open(pc_dest_file, 'w') as pc_file:
pc_file.write(text_buffer)

def download_web_backend_dependencies(self, arch):
"""
During building, host needs to download the jquery-ui package (in order
to make it work the mpl web backend). This operation seems to fail
in our CI tests, so we download this package at the expected location
by the mpl install script which is defined by the environ variable
`XDG_CACHE_HOME` (we modify that one in our `get_recipe_env` so it will
be the same regardless of the host platform).
"""

env = self.get_recipe_env(arch)

info_notify('Downloading jquery-ui for matplatlib web backend')
# We use the same jquery-ui version than mpl's setup.py script,
# inside function `_download_jquery_to`
jquery_sha = (
'f8233674366ab36b2c34c577ec77a3d70cac75d2e387d8587f3836345c0f624d'
)
url = "https://jqueryui.com/resources/download/jquery-ui-1.12.1.zip"
target_file = join(env['XDG_CACHE_HOME'], 'matplotlib', jquery_sha)

info_notify(f'Will download into {env["XDG_CACHE_HOME"]}')
ensure_dir(join(env['XDG_CACHE_HOME'], 'matplotlib'))
self.download_file(url, target_file)

def prebuild_arch(self, arch):
with open(join(self.get_recipe_dir(), 'setup.cfg.template')) as fileh:
setup_cfg = fileh.read()

with open(join(self.get_build_dir(arch), 'setup.cfg'), 'w') as fileh:
fileh.write(setup_cfg.format(
ndk_sysroot_usr=join(self.ctx.ndk.sysroot, 'usr')))

shutil.copyfile(
join(self.get_recipe_dir(), "setup.cfg.template"),
join(self.get_build_dir(arch), "mplsetup.cfg"),
)
self.generate_libraries_pc_files(arch)
self.download_web_backend_dependencies(arch)

def get_recipe_env(self, arch=None, with_flags_in_cc=True):
env = super().get_recipe_env(arch, with_flags_in_cc)
if self.need_stl_shared:
# matplotlib compile flags does not honor the standard flags:
# `CPPFLAGS` and `LDLIBS`, so we put in `CFLAGS` and `LDFLAGS` to
# correctly link with the `c++_shared` library
env['CFLAGS'] += ' -I{}'.format(self.ctx.ndk.libcxx_include_dir)
env['CFLAGS'] += ' -frtti -fexceptions'

env['LDFLAGS'] += ' -L{}'.format(arch.ndk_lib_dir)
env['LDFLAGS'] += ' -l{}'.format(self.stl_lib_name)

# we modify `XDG_CACHE_HOME` to download `jquery-ui` into that folder,
# or mpl install will fail when trying to download/install it, but if
# we have the proper package already downloaded, it will use the cached
# package to successfully finish the installation.
# Note: this may not be necessary for some local systems, but it is
# for our CI provider: `gh-actions`, which will
# fail trying to download the `jquery-ui` package
env['XDG_CACHE_HOME'] = join(self.get_build_dir(arch), 'p4a_files')

# 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), 'p4a_files')
env['PKG_CONFIG_PATH'] = env['XDG_CACHE_HOME']

# We set a new environ variable `NUMPY_INCLUDES` to be able to tell
# the matplotlib script where to find our numpy without importing it
# (which will fail, because numpy isn't installed in our hostpython)
env['NUMPY_INCLUDES'] = join(
self.ctx.get_site_packages_dir(arch),
'numpy', 'core', 'include',
)

# 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 :)
png = self.get_recipe('png', self.ctx)
env['CFLAGS'] += f' -I{png.get_build_dir(arch)}'
env['LDFLAGS'] += f' -L{join(png.get_build_dir(arch.arch), ".libs")}'

freetype = self.get_recipe('freetype', self.ctx)
free_lib_dir = join(freetype.get_build_dir(arch.arch), 'objs', '.libs')
free_inc_dir = join(freetype.get_build_dir(arch.arch), 'include')
Expand Down
10 changes: 0 additions & 10 deletions pythonforandroid/recipes/matplotlib/libpng.pc.template

This file was deleted.

60 changes: 0 additions & 60 deletions pythonforandroid/recipes/matplotlib/mpl_android_fixes.patch

This file was deleted.

Loading