Skip to content

Commit 1ae14b9

Browse files
committed
Merge pull request #546 from kivy/python3_support
Add python3 support
2 parents deff096 + 590c377 commit 1ae14b9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+752
-6059
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212

1313
*.pyc
1414
*.pyo
15+
*.apk
1516
.packages
1617
python_for_android.egg-info
1718
/build/
19+
doc/build
1820
__pycache__/

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Broad goals of the revamp project include:
2424
- ✓ Support SDL2
2525
- ✓ Support multiple bootstraps (user-chosen java + NDK code, e.g. for
2626
multiple graphics backends or non-Kivy projects)
27-
- (WIP) Support python3 (recipe exists but crashes on android)
27+
- Support python3 (it finally works!)
2828
- (WIP) Support some kind of binary distribution, including on windows (semi-implemented, just needs finishing)
2929
- ✓ Be a standalone Pypi module (not on pypi yet but setup.py works)
3030
- ✓ Support multiple architectures (full multiarch builds not complete, but arm and x86 with different config both work now)

doc/source/bootstraps.rst

Lines changed: 2 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,56 +11,12 @@ components such as Android source code and various build files.
1111
If you do not want to modify p4a, you don't need to worry about
1212
bootstraps, just make sure you specify what modules you want to use
1313
(or specify an existing bootstrap manually), and p4a will
14-
automatically build everything appropriately.
14+
automatically build everything appropriately. The existing choices are
15+
explained on the :ref:`build options <bootstrap_build_options>` page.
1516

1617
This page describes the basics of how bootstraps work so that you can
1718
create and use your own if you like, making it easy to build new kinds
1819
of Python project for Android.
19-
20-
21-
Current bootstraps
22-
------------------
23-
24-
python-for-android includes the following bootstraps by default, which
25-
may be chosen by name with a build parameter, or (by default) are
26-
selected automatically in order to fulfil your build requirements. For
27-
instance, if you add 'sdl2' in the requirements, the sdl2 backend will
28-
be used.
29-
30-
p4a is designed to make it fairly easy to make your own bootstrap with a new backend,
31-
e.g. one that creates a webview interface and runs python in the
32-
background to serve a flask or django site from the phone itself.
33-
34-
35-
pygame
36-
%%%%%%
37-
38-
This builds APKs exactly like the old p4a toolchain, using Pygame as
39-
the windowing and input backend.
40-
41-
This bootstrap automatically includes pygame, kivy, and python. It
42-
could potentially be modified to work for non-Kivy projects.
43-
44-
sdl2
45-
%%%%
46-
47-
This builds APKs using SDL2 as the window and input backend. It is not
48-
fully developed compared to the Pygame backend, but has many
49-
advantages and will be the long term default.
50-
51-
This bootstrap automatically includes SDL2, but nothing else.
52-
53-
You can use the sdl2 bootstrap to seamlessly make a Kivy APK, but can
54-
also make Python apps using other libraries; for instance, using
55-
pysdl2 and pyopengl. `Vispy <http://vispy.org/>`_ also runs on android
56-
this way.
57-
58-
empty
59-
%%%%%
60-
61-
This bootstrap has no dependencies and cannot actually build an
62-
APK. It is useful for testing recipes without building unnecessary
63-
components.
6420

6521

6622
Creating a new bootstrap

doc/source/buildoptions.rst

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
2+
Build options
3+
=============
4+
5+
python-for-android provides several major choices for build
6+
components. This page describes the advantages and drawbacks, and
7+
extra technical details or requirements, in each case.
8+
9+
10+
Python version
11+
--------------
12+
13+
python-for-android now supports building APKs with either python2 or
14+
python3, but these have extra requirements or potential disadvantages
15+
as below.
16+
17+
18+
python2
19+
~~~~~~~
20+
21+
Select this by adding it in your requirements, e.g. ``--requirements=python2``.
22+
23+
This option builds Python 2.7.2 for your selected Android architecture, and
24+
includes it in the APK. There are no special requirements, all the
25+
building is done locally.
26+
27+
The python2 build is also the way python-for-android originally
28+
worked, even in the old toolchain.
29+
30+
31+
python3
32+
~~~~~~~
33+
34+
.. warning::
35+
Python3 support is experimental, and some of these details
36+
may change as it is improved and fully stabilised.
37+
38+
Select this by adding the ``python3crystax`` recipe to your
39+
requirements, e.g. ``--requirements=python3crystax``.
40+
41+
This uses the prebuilt Python from the `CrystaX NDK
42+
<https://www.crystax.net/android/ndk>`__, a drop-in replacement for
43+
Google's official NDK which includes many improvements. As such, you
44+
*must* use the CrystaX NDK 10.3.0 or higher when building with
45+
python3. You can get it `here
46+
<https://www.crystax.net/en/download>`__.
47+
48+
python3 inclusion should work fine, including all existing
49+
recipes, but internally this is handled quite differently to the
50+
locally built python2 so there may be bugs or surprising
51+
behaviours. If you come across any, feel free to `open an issue
52+
<https://github.com/kivy/python-for-android>`__.
53+
54+
The experimental status also means that some features are missing and
55+
the build is not fully optimised so APKs are probably a little larger
56+
and slower than they need to be. This is currently being addressed,
57+
though it's not clear how the final result will compare to python2.
58+
59+
.. _bootstrap_build_options:
60+
61+
Bootstrap
62+
---------
63+
64+
python-for-android supports multiple bootstraps, the Java and JNI code
65+
that starts the app and the python interpreter, then handles
66+
interactions with the Android OS.
67+
68+
Currently the following bootstraps are supported, but we hope that it
69+
it should be easy to add others if your project has different
70+
requirements. `Let us know
71+
<https://groups.google.com/forum/#!forum/python-android>`__ if there
72+
are any improvements that would help here.
73+
74+
sdl2
75+
~~~~
76+
77+
You can use this with ``--bootstrap=sdl2``, or simply include the
78+
``sdl2`` recipe in your ``--requirements``.
79+
80+
SDL2 is a popular cross-platform depelopment library, particularly for
81+
games. It has its own Android project support, which
82+
python-for-android uses as a bootstrap, and to which it adds the
83+
Python build and JNI code to start it.
84+
85+
From the point of view of a Python program, SDL2 should behave as
86+
normal. For instance, you can build apps with Kivy, Vispy, or PySDL2
87+
and have them work with this bootstrap. It should also be possible to
88+
use e.g. pygame_sdl2, but this would need a build recipe and doesn't
89+
yet have one.
90+
91+
.. note::
92+
The SDL2 bootstrap is newer, and does not support all the old
93+
features of the Pygame one. It is under active development to fix
94+
these omissions.
95+
96+
pygame
97+
~~~~~~
98+
99+
You can use this with ``--bootstrap=pygame``, or simply include the
100+
``pygame`` recipe in your ``--requirements``.
101+
102+
The pygame bootstrap is the original backend used by Kivy, and still
103+
works fine for use with Kivy apps. It may also work for pure pygame
104+
apps, but hasn't been developed with this in mind.
105+
106+
This bootstrap will eventually be deprecated in favour of sdl2, but
107+
not before the sdl2 bootstrap includes all the features that would be
108+
lost.

doc/source/commands.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,14 @@ supply those that you need.
7373
``--arch``
7474
The architecture to build for. Currently only one architecture can be
7575
targeted at a time, and a given distribution can only include one architecture.
76+
77+
``--bootstrap BOOTSTRAP``
78+
79+
The Java bootstrap to use for your application. You mostly don't
80+
need to worry about this or set it manually, as an appropriate
81+
bootstrap will be chosen from your ``--requirements``. Current
82+
choices are ``sdl2`` or ``pygame``; ``sdl2`` is experimental but
83+
preferable where possible.
7684

7785

7886
.. note:: These options are preliminary. Others will include toggles

doc/source/index.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ Contents
2727
:maxdepth: 2
2828

2929
quickstart
30+
buildoptions
3031
installation
3132
commands
3233
recipes
3334
bootstraps
3435
apis
3536
troubleshooting
36-
old_p4a
3737
contribute
3838
old_toolchain/index.rst
3939

doc/source/old_p4a.rst

Lines changed: 0 additions & 14 deletions
This file was deleted.

doc/source/quickstart.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ You can build an SDL2 APK similarly, creating a dist as follows::
144144
You can then make an APK in the same way, but this is more
145145
experimental and doesn't support as much customisation yet.
146146

147-
There is also experimental support for building APKs with Vispy, which
148-
do not include Kivy. The basic command for this would be e.g.::
147+
Your APKs are not limited to Kivy, for instance you can create apps
148+
using Vispy, or using PySDL2 directly. The basic command for this
149+
would be e.g.::
149150

150151
python-for-android create --dist_name=testvispy --bootstrap=sdl2 --requirements=vispy
151152

doc/source/recipes.rst

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ The basic declaration of a recipe is as follows::
3838
url = 'http://example.com/example-{version}.tar.gz'
3939
version = '2.0.3'
4040
md5sum = '4f3dc9a9d857734a488bcbefd9cd64ed'
41+
42+
patches = ['some_fix.patch'] # Paths relative to the recipe dir
4143

4244
depends = ['kivy', 'sdl2'] # These are just examples
4345
conflicts = ['pygame']
@@ -118,26 +120,35 @@ Methods and tools to help with compilation
118120
Patching modules before installation
119121
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
120122

121-
You can easily apply patches to your recipes with the ``apply_patch``
122-
method. For instance, you could do this in your prebuild method::
123+
You can easily apply patches to your recipes by adding them to the
124+
``patches`` declaration, e.g.::
125+
126+
patches = ['some_fix.patch',
127+
'another_fix.patch']
128+
129+
The paths should be relative to the recipe file. Patches are
130+
automatically applied just once (i.e. not reapplied the second time
131+
python-for-android is run).
132+
133+
You can also use the helper functions in ``pythonforandroid.patching``
134+
to apply patches depending on certain conditions, e.g.::
135+
136+
from pythonforandroid.patching import will_build, is_arch
123137

124-
import sh
125-
def prebuild_arch(self, arch):
126-
super(YourRecipe, self).prebuild_arch(arch)
127-
build_dir = self.get_build_dir(arch.arch)
128-
if exists(join(build_dir, '.patched')):
129-
print('Your recipe is already patched, skipping')
130-
return
131-
self.apply_patch('some_patch.patch')
132-
shprint(sh.touch, join(build_dir, '.patched'))
138+
...
133139

134-
The path to the patch should be in relation to your recipe code.
135-
In this case, ``some_path.patch`` must be in the same directory as the
136-
recipe.
140+
class YourRecipe(Recipe):
141+
142+
patches = [('x86_patch.patch', is_arch('x86')),
143+
('sdl2_compatibility.patch', will_build('sdl2'))]
144+
145+
...
146+
147+
You can include your own conditions by passing any function as the
148+
second entry of the tuple. It will receive the ``arch`` (e.g. x86,
149+
armeabi) and ``recipe`` (i.e. the Recipe object) as kwargs. The patch
150+
will be applied only if the function returns True.
137151

138-
This code also manually takes care to patch only once. You can use the
139-
same strategy yourself, though a more generic solution may be provided
140-
in the future.
141152

142153
Installing libs
143154
~~~~~~~~~~~~~~~
@@ -210,29 +221,28 @@ The should_build method
210221
~~~~~~~~~~~~~~~~~~~~~~~
211222

212223
The Recipe class has a ``should_build`` method, which returns a
213-
boolean. This is called before running ``build_arch``, and if it
214-
returns False then the build is skipped. This is useful to avoid
215-
building a recipe more than once for different dists.
224+
boolean. This is called for each architecture before running
225+
``build_arch``, and if it returns False then the build is
226+
skipped. This is useful to avoid building a recipe more than once for
227+
different dists.
216228

217229
By default, should_build returns True, but you can override it however
218230
you like. For instance, PythonRecipe and its subclasses all replace it
219231
with a check for whether the recipe is already installed in the Python
220232
distribution::
221233

222-
def should_build(self):
234+
def should_build(self, arch):
223235
name = self.site_packages_name
224236
if name is None:
225237
name = self.name
226-
if exists(join(self.ctx.get_site_packages_dir(), name)):
238+
if self.ctx.has_package(name):
227239
info('Python package already exists in site-packages')
228240
return False
229-
print('site packages', self.ctx.get_site_packages_dir())
230241
info('{} apparently isn\'t already in site-packages'.format(name))
231242
return True
232243

233244

234245

235-
236246
Using a PythonRecipe
237247
--------------------
238248

@@ -463,12 +473,11 @@ The above documentation has included a number of snippets
463473
demonstrating different behaviour. Together, these cover most of what
464474
is ever necessary to make a recipe work.
465475

466-
The following short sections further demonstrate a few full recipes from p4a's
467-
internal recipes folder. Unless your own module has some unusual
468-
complication, following these templates should be all you need to make
469-
your own recipes work.
476+
python-for-android includes many recipes for popular modules, which
477+
are an excellent resource to find out how to add your own. You can
478+
find these in the `python-for-android Github page
479+
<https://github.com/kivy/python-for-android/tree/master/pythonforandroid/recipes>`__.
470480

471-
TODO
472481

473482
.. _recipe_class:
474483

pythonforandroid/archs.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ def get_env(self):
8484
env['AR'] = '{}-ar'.format(command_prefix)
8585
env['RANLIB'] = '{}-ranlib'.format(command_prefix)
8686
env['LD'] = '{}-ld'.format(command_prefix)
87+
# env['LDSHARED'] = join(self.ctx.root_dir, 'tools', 'liblink')
88+
# env['LDSHARED'] = env['LD']
8789
env['STRIP'] = '{}-strip --strip-unneeded'.format(command_prefix)
8890
env['MAKE'] = 'make -j5'
8991
env['READELF'] = '{}-readelf'.format(command_prefix)
@@ -100,6 +102,9 @@ def get_env(self):
100102

101103
env['ARCH'] = self.arch
102104

105+
if self.ctx.python_recipe.from_crystax:
106+
env['CRYSTAX_PYTHON_VERSION'] = self.ctx.python_recipe.version
107+
103108
return env
104109

105110

0 commit comments

Comments
 (0)