Skip to content

Commit 9af16a7

Browse files
committed
more wrappers for meson recipe
1 parent 260302e commit 9af16a7

File tree

7 files changed

+69
-27
lines changed

7 files changed

+69
-27
lines changed

pythonforandroid/recipe.py

Lines changed: 52 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from re import match
66

77
import sh
8+
import subprocess
89
import shutil
910
import fnmatch
1011
import zipfile
@@ -1408,6 +1409,7 @@ class MesonRecipe(PyProjectRecipe):
14081409
'''Recipe for projects which uses meson as build system'''
14091410

14101411
meson_version = "1.4.0"
1412+
pybind_version = "3.3.0"
14111413

14121414
skip_python = False
14131415
'''If true, skips all Python build and installation steps.
@@ -1416,6 +1418,18 @@ class MesonRecipe(PyProjectRecipe):
14161418
def sanitize_flags(self, *flag_strings):
14171419
return " ".join(flag_strings).strip().split(" ")
14181420

1421+
def get_wrapper_dir(self, arch):
1422+
return join(self.get_build_dir(arch.arch), "p4a_wrappers")
1423+
1424+
def write_wrapper(self, arch, name, content):
1425+
wrapper_dir = self.get_wrapper_dir(arch)
1426+
ensure_dir(wrapper_dir)
1427+
wrapper_path = join(wrapper_dir, name)
1428+
with open(wrapper_path, "w") as f:
1429+
f.write(content)
1430+
chmod(wrapper_path, 0o755)
1431+
return wrapper_path
1432+
14191433
def get_python_wrapper(self, arch):
14201434
"""
14211435
Meson Python introspection runs on the host interpreter, but the
@@ -1451,19 +1465,50 @@ def get_python_wrapper(self, arch):
14511465
with open(python_file, "r") as f:
14521466
file_data += "\n" + f.read()
14531467

1454-
wrapper_dir = join(self.get_build_dir(arch.arch), "p4a_python_wrapper")
1455-
ensure_dir(wrapper_dir)
1456-
wrapper_path = join(wrapper_dir, "python")
1457-
with open(wrapper_path, "w") as f:
1458-
f.write(file_data)
1459-
chmod(wrapper_path, 0o755)
1468+
return self.write_wrapper(arch, "python", file_data)
14601469

1461-
return wrapper_path
1470+
def get_config_wrappers(self, arch, w_type: str):
1471+
wrapper_name = ""
1472+
version = ""
1473+
include_path = ""
1474+
1475+
if w_type == "pybind11":
1476+
wrapper_name = "pybind11-config"
1477+
include_path = join(self._host_recipe.site_dir, "pybind11/include")
1478+
1479+
version = None
1480+
try:
1481+
command = [self._host_recipe.real_hostpython_location, "-c", "import pybind11; print(pybind11.__version__)"]
1482+
version = subprocess.check_output(command).decode('utf-8').strip()
1483+
except Exception:
1484+
warning("Unable to get pybind11 version")
1485+
if version is None:
1486+
version = self.pybind_version
1487+
1488+
elif w_type == "numpy":
1489+
wrapper_name = "numpy-config"
1490+
recipe = Recipe.get_recipe("numpy", self.ctx)
1491+
include_path = recipe.get_include(arch)
1492+
version = recipe.version
1493+
else:
1494+
raise ValueError(f"Unknown wrapper type: {w_type}")
1495+
1496+
content = (
1497+
f"#!/bin/sh\n"
1498+
f"if [ \"$1\" = \"--version\" ]; then\n"
1499+
f" echo '{version}'\n"
1500+
f"else\n"
1501+
f" echo '-I{include_path}'\n"
1502+
f"fi\n"
1503+
)
1504+
return self.write_wrapper(arch, wrapper_name, content)
14621505

14631506
def get_recipe_meson_options(self, arch):
14641507
env = self.get_recipe_env(arch, with_flags_in_cc=True)
14651508
return {
14661509
"binaries": {
1510+
"pybind11-config": self.get_config_wrappers(arch, "pybind11"),
1511+
"numpy-config": self.get_config_wrappers(arch, "numpy"),
14671512
"python": self.get_python_wrapper(arch),
14681513
"c": arch.get_clang_exe(with_target=True),
14691514
"cpp": arch.get_clang_exe(with_target=True, plus_plus=True),

pythonforandroid/recipes/matplotlib/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class MatplotlibRecipe(MesonRecipe):
1212
"pyparsing",
1313
"python-dateutil",
1414
]
15+
pybind_version = "2.13.4"
1516
hostpython_prerequisites = ["meson-python>=0.13.1,<0.17.0", "pybind11>=2.13.2,!=2.13.3", "setuptools_scm>=7"]
1617
need_stl_shared = True
1718

pythonforandroid/recipes/numpy/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ class NumpyRecipe(MesonRecipe):
1414
need_stl_shared = True
1515
min_ndk_api_support = 24
1616

17+
def get_include(self, arch):
18+
return join(
19+
self.ctx.get_python_install_dir(arch.arch), "numpy/_core/include",
20+
)
21+
1722
def get_recipe_meson_options(self, arch):
1823
options = super().get_recipe_meson_options(arch)
1924
options["properties"]["longdouble_format"] = (

pythonforandroid/recipes/pandas/__init__.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ class PandasRecipe(MesonRecipe):
66
version = 'v2.3.0'
77
url = 'git+https://github.com/pandas-dev/pandas'
88
depends = ['numpy', 'libbz2', 'liblzma']
9-
hostpython_prerequisites = ["Cython<4.0.0a0", "versioneer", "numpy"] # meson does not detects venv's cython
109
patches = ['fix_numpy_includes.patch']
1110
python_depends = ['python-dateutil', 'pytz']
1211
need_stl_shared = True
@@ -29,9 +28,5 @@ def get_recipe_env(self, arch, **kwargs):
2928
env['LDFLAGS'] += f' -landroid -l{self.stl_lib_name}'
3029
return env
3130

32-
def build_arch(self, arch):
33-
super().build_arch(arch)
34-
self.restore_hostpython_prerequisites(["cython"])
35-
3631

3732
recipe = PandasRecipe()

pythonforandroid/recipes/python3/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,11 @@ def apply_patches(self, arch, build_dir=None):
210210
super().apply_patches(arch, build_dir)
211211

212212
def include_root(self, arch_name):
213-
return glob.glob(join(self.get_build_dir(arch_name), 'android-build', 'android-root', 'include/*/'))[0]
213+
_p_version = Version(self.version)
214+
return join(
215+
self.get_build_dir(arch_name), 'android-build', 'android-root',
216+
'include', f'python{_p_version.major}.{_p_version.minor}'
217+
)
214218

215219
def link_root(self, arch_name):
216220
return join(self.get_build_dir(arch_name), 'android-build')

tests/recipes/test_hostpython3.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def test_property__exe_name_no_version(self):
2727
self.recipe._version = hostpython_version
2828

2929
def test_property__exe_name(self):
30-
self.assertEqual(self.recipe._exe_name, 'python3')
30+
self.assertEqual(self.recipe._exe_name, 'python')
3131

3232
@mock.patch("pythonforandroid.recipes.hostpython3.Path.exists")
3333
def test_should_build(self, mock_exists):

tests/recipes/test_python3.py

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,6 @@ def test_property__libpython(self):
2626
f'libpython{self.recipe.link_version}.so'
2727
)
2828

29-
def test_include_root(self):
30-
expected_include_dir = join(
31-
self.recipe.get_build_dir(self.arch.arch), 'Include',
32-
)
33-
self.assertEqual(
34-
expected_include_dir, self.recipe.include_root(self.arch.arch)
35-
)
36-
3729
def test_link_root(self):
3830
expected_link_root = join(
3931
self.recipe.get_build_dir(self.arch.arch), 'android-build',
@@ -116,11 +108,11 @@ def test_build_arch(
116108
mock_sh_command.mock_calls,
117109
)
118110
mock_open_zlib.assert_called()
119-
self.assertEqual(mock_make.call_count, 1)
120-
for make_call, kw in mock_make.call_args_list:
121-
self.assertIn(
122-
f'INSTSONAME={self.recipe._libpython}', make_call
123-
)
111+
self.assertEqual(mock_make.call_count, 2)
112+
make_call, kw = mock_make.call_args_list[0]
113+
self.assertIn(
114+
f'INSTSONAME={self.recipe._libpython}', make_call
115+
)
124116
mock_cp.assert_called_with(
125117
"pyconfig.h", join(recipe_build_dir, 'Include'),
126118
)

0 commit comments

Comments
 (0)