Skip to content

Commit e1bd249

Browse files
clayoteT-Dynamos
andauthored
Update to Python 3.14, remove distutils (#3242)
* Use `pip install` instead of `setup.py install` in `recipe.py` On Python 3.14, many recipes, notably `msgpack`, no longer byte- compile with `setup.py install`, because the way that command byte-compiles relies on `distutils`, which is gone. * Import from setuptools and not distutils in the `android` recipe * Remove freetype's distutils "fallback" It was actually using distutils every time, apparently? * Bump `freetype` version to match that of `freetype-py` * On second thought, use the latest freetype version * Use the latest *released* freetype-py version * Tell setuptools what freetype-py version we have * Turn `FreetypePyRecipe` into a `PyProjectRecipe` I don't think this will require the version hack * Put the `setuptools-scm` version hack back in * Fix `FreetypePyRecipe.get_recipe_env` * Switch to pythonhosted FreetypePy `setuptools-scm` can't deal with the github hosted one, it seems. * Update apsw recipe, use pythonhosted package * Fix `LibffiRecipe.get_include_dirs` for `arch=None` * Use recent libffi and cffi * Require setuptools for every recipe * `python`: update to `3.14.0` * Use `pip install` instead of `setup.py install` in `recipe.py` On Python 3.14, many recipes, notably `msgpack`, no longer byte- compile with `setup.py install`, because the way that command byte-compiles relies on `distutils`, which is gone. * Import from setuptools and not distutils in the `android` recipe * Remove freetype's distutils "fallback" It was actually using distutils every time, apparently? * Bump `freetype` version to match that of `freetype-py` * On second thought, use the latest freetype version * Use the latest *released* freetype-py version * Tell setuptools what freetype-py version we have * Turn `FreetypePyRecipe` into a `PyProjectRecipe` I don't think this will require the version hack * Put the `setuptools-scm` version hack back in * Fix `FreetypePyRecipe.get_recipe_env` * Switch to pythonhosted FreetypePy `setuptools-scm` can't deal with the github hosted one, it seems. * Update apsw recipe, use pythonhosted package * Require setuptools for every recipe * `python`: update to `3.14.0` * Remove 'six' from `build_order` in `TestToolchainCL.test_create` * Add 'six' to `python_modules` in `TestToolchainCL.test_create` * Remove 'setuptools' from 'build_order' in `TestToolchainCL.test_create` I guess because the hostpython already has it, there's no need to build it again? * Revert the change to `modules_build_dir` in `Python3Recipe.create_python_bundle` * Remove old versions from `modules_build_dir` expected value in `TestPython3Recipe.test_create_python_bundle` * Roll back to an earlier apsw version * only load libpython once * fix pip install path * fix build * shift foundPython check * fix newline * remove unnecessary test --------- Co-authored-by: Ansh Dadwal <[email protected]>
1 parent 3762c88 commit e1bd249

File tree

15 files changed

+71
-191
lines changed

15 files changed

+71
-191
lines changed

pythonforandroid/bootstraps/common/build/src/main/java/org/kivy/android/PythonUtil.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ protected static ArrayList<String> getLibraries(File libsDir) {
5151
addLibraryIfExists(libsList, name, libsDir);
5252
}
5353

54-
for (int v = 5; v <= 14; v++) {
54+
for (int v = 14; v >= 5; v--) {
5555
libsList.add("python3." + v + (v <= 7 ? "m" : ""));
5656
}
5757

@@ -63,6 +63,7 @@ public static void loadLibraries(File filesDir, File libsDir) {
6363
boolean foundPython = false;
6464

6565
for (String lib : getLibraries(libsDir)) {
66+
if (lib.startsWith("python") && foundPython) {continue;}
6667
Log.v(TAG, "Loading library: " + lib);
6768
try {
6869
System.loadLibrary(lib);

pythonforandroid/recipe.py

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -883,7 +883,7 @@ class PythonRecipe(Recipe):
883883
on python2 or python3 which can break the dependency graph
884884
'''
885885

886-
hostpython_prerequisites = []
886+
hostpython_prerequisites = ['setuptools']
887887
'''List of hostpython packages required to build a recipe'''
888888

889889
_host_recipe = None
@@ -1025,18 +1025,11 @@ def install_python_package(self, arch, name=None, env=None, is_dir=True):
10251025
hostpython = sh.Command(self.hostpython_location)
10261026
hpenv = env.copy()
10271027
with current_directory(self.get_build_dir(arch.arch)):
1028-
1029-
if isfile("setup.py"):
1030-
shprint(hostpython, 'setup.py', 'install', '-O2',
1031-
'--root={}'.format(self.ctx.get_python_install_dir(arch.arch)),
1032-
'--install-lib=.',
1033-
_env=hpenv, *self.setup_extra_args)
1034-
1035-
# If asked, also install in the hostpython build dir
1036-
if self.install_in_hostpython:
1037-
self.install_hostpython_package(arch)
1038-
else:
1039-
warning("`PythonRecipe.install_python_package` called without `setup.py` file!")
1028+
shprint(hostpython, '-m', 'pip', 'install', '.',
1029+
'--compile', '--target',
1030+
self.ctx.get_python_install_dir(arch.arch),
1031+
_env=hpenv, *self.setup_extra_args
1032+
)
10401033

10411034
def get_hostrecipe_env(self, arch=None):
10421035
env = environ.copy()
@@ -1053,8 +1046,8 @@ def hostpython_site_dir(self):
10531046
def install_hostpython_package(self, arch):
10541047
env = self.get_hostrecipe_env(arch)
10551048
real_hostpython = sh.Command(self.real_hostpython_location)
1056-
shprint(real_hostpython, 'setup.py', 'install', '-O2',
1057-
'--install-lib=Lib/site-packages',
1049+
shprint(real_hostpython, '-m', 'pip', 'install', '.',
1050+
'--compile',
10581051
'--root={}'.format(self._host_recipe.site_root),
10591052
_env=env, *self.setup_extra_args)
10601053

@@ -1100,7 +1093,7 @@ class CompiledComponentsPythonRecipe(PythonRecipe):
11001093

11011094
def build_arch(self, arch):
11021095
'''Build any cython components, then install the Python module by
1103-
calling setup.py install with the target Python dir.
1096+
calling pip install with the target Python dir.
11041097
'''
11051098
Recipe.build_arch(self, arch)
11061099
self.install_hostpython_prerequisites()
@@ -1149,7 +1142,7 @@ class CythonRecipe(PythonRecipe):
11491142

11501143
def build_arch(self, arch):
11511144
'''Build any cython components, then install the Python module by
1152-
calling setup.py install with the target Python dir.
1145+
calling pip install with the target Python dir.
11531146
'''
11541147
Recipe.build_arch(self, arch)
11551148
self.build_cython_components(arch)

pythonforandroid/recipes/android/src/setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from distutils.core import setup, Extension
1+
from setuptools import setup, Extension
22
from Cython.Build import cythonize
33
import os
44

pythonforandroid/recipes/apsw/__init__.py

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,16 @@
1-
from pythonforandroid.recipe import PythonRecipe
2-
from pythonforandroid.toolchain import current_directory, shprint
3-
import sh
1+
from pythonforandroid.recipe import PyProjectRecipe
42

53

6-
class ApswRecipe(PythonRecipe):
7-
version = '3.15.0-r1'
8-
url = 'https://github.com/rogerbinns/apsw/archive/{version}.tar.gz'
9-
depends = ['sqlite3', 'setuptools']
10-
call_hostpython_via_targetpython = False
4+
class ApswRecipe(PyProjectRecipe):
5+
version = '3.50.4.0'
6+
url = 'https://github.com/rogerbinns/apsw/releases/download/{version}/apsw-{version}.tar.gz'
7+
depends = ['sqlite3']
118
site_packages_name = 'apsw'
129

13-
def build_arch(self, arch):
14-
env = self.get_recipe_env(arch)
15-
with current_directory(self.get_build_dir(arch.arch)):
16-
# Build python bindings
17-
hostpython = sh.Command(self.hostpython_location)
18-
shprint(hostpython,
19-
'setup.py',
20-
'build_ext',
21-
'--enable=fts4', _env=env)
22-
# Install python bindings
23-
super().build_arch(arch)
24-
25-
def get_recipe_env(self, arch):
26-
env = super().get_recipe_env(arch)
10+
def get_recipe_env(self, arch, **kwargs):
11+
env = super().get_recipe_env(arch, **kwargs)
2712
sqlite_recipe = self.get_recipe('sqlite3', self.ctx)
2813
env['CFLAGS'] += ' -I' + sqlite_recipe.get_build_dir(arch.arch)
29-
env['LDFLAGS'] += ' -L' + sqlite_recipe.get_lib_dir(arch)
3014
env['LIBS'] = env.get('LIBS', '') + ' -lsqlite3'
3115
return env
3216

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,17 @@
1-
from pythonforandroid.recipe import PythonRecipe
1+
from pythonforandroid.recipe import PyProjectRecipe
22

33

4-
class FreetypePyRecipe(PythonRecipe):
5-
version = '2.2.0'
4+
class FreetypePyRecipe(PyProjectRecipe):
5+
version = '2.5.1'
66
url = 'https://github.com/rougier/freetype-py/archive/refs/tags/v{version}.tar.gz'
7+
patches = ["fix_import.patch"]
78
depends = ['freetype']
8-
patches = ['fall-back-to-distutils.patch']
99
site_packages_name = 'freetype'
1010

11+
def get_recipe_env(self, arch, **kwargs):
12+
env = super().get_recipe_env(arch, **kwargs)
13+
env["SETUPTOOLS_SCM_PRETEND_VERSION_FOR_freetype_py"] = self.version
14+
return env
15+
1116

1217
recipe = FreetypePyRecipe()

pythonforandroid/recipes/freetype-py/fall-back-to-distutils.patch

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
diff '--color=auto' -uNr freetype-py-2.5.1/MANIFEST.in freetype-py-2.5.1.mod/MANIFEST.in
2+
--- freetype-py-2.5.1/MANIFEST.in 2024-08-29 23:12:30.000000000 +0530
3+
+++ freetype-py-2.5.1.mod/MANIFEST.in 2025-10-26 11:54:45.052025521 +0530
4+
@@ -9,3 +9,4 @@
5+
include LICENSE.txt
6+
include README.rst
7+
include setup-build-freetype.py
8+
+recursive-include _custom_build *.py

pythonforandroid/recipes/freetype/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class FreetypeRecipe(Recipe):
2424
https://sourceforge.net/projects/freetype/files/freetype2/2.5.3/
2525
"""
2626

27-
version = '2.10.1'
27+
version = '2.14.1'
2828
url = 'https://download.savannah.gnu.org/releases/freetype/freetype-{version}.tar.gz' # noqa
2929
built_libraries = {'libfreetype.so': 'objs/.libs'}
3030

@@ -77,6 +77,7 @@ def build_arch(self, arch, with_harfbuzz=False):
7777
'--host={}'.format(arch.command_prefix),
7878
'--prefix={}'.format(prefix_path),
7979
'--without-bzip2',
80+
'--without-brotli',
8081
'--with-png=no',
8182
}
8283
if not harfbuzz_in_recipes:

pythonforandroid/recipes/hostpython3/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class HostPython3Recipe(Recipe):
3636
:class:`~pythonforandroid.python.HostPythonRecipe`
3737
'''
3838

39-
version = '3.11.13'
39+
version = '3.14.0'
4040

4141
url = 'https://github.com/python/cpython/archive/refs/tags/v{version}.tar.gz'
4242
'''The default url to download our host python recipe. This url will

pythonforandroid/recipes/python3/__init__.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class Python3Recipe(TargetPythonRecipe):
5454
:class:`~pythonforandroid.python.GuestPythonRecipe`
5555
'''
5656

57-
version = '3.11.13'
57+
version = '3.14.0'
5858
_p_version = Version(version)
5959
url = 'https://github.com/python/cpython/archive/refs/tags/v{version}.tar.gz'
6060
name = 'python3'
@@ -262,7 +262,7 @@ def add_flags(include_flags, link_dirs, link_libs):
262262
info('Activating flags for sqlite3')
263263
recipe = Recipe.get_recipe('sqlite3', self.ctx)
264264
add_flags(' -I' + recipe.get_build_dir(arch.arch),
265-
' -L' + recipe.get_lib_dir(arch), ' -lsqlite3')
265+
' -L' + recipe.get_build_dir(arch.arch), ' -lsqlite3')
266266

267267
info('Activating flags for libffi')
268268
recipe = Recipe.get_recipe('libffi', self.ctx)
@@ -388,19 +388,12 @@ def create_python_bundle(self, dirn, arch):
388388
copying all the modules and standard library to the right
389389
place.
390390
"""
391-
# Todo: find a better way to find the build libs folder
392-
modules_build_dir = join(
391+
modules_build_dir = glob.glob(join(
393392
self.get_build_dir(arch.arch),
394393
'android-build',
395394
'build',
396-
'lib.{}{}-{}-{}'.format(
397-
# android is now supported platform
398-
"android" if self._p_version.minor >= 13 else "linux",
399-
'2' if self.version[0] == '2' else '',
400-
arch.command_prefix.split('-')[0],
401-
self.major_minor_version_string
402-
))
403-
395+
'lib.*'
396+
))[0]
404397
# Compile to *.pyc the python modules
405398
self.compile_python_files(modules_build_dir)
406399
# Compile to *.pyc the standard python library

0 commit comments

Comments
 (0)