Skip to content

Commit 901f9e4

Browse files
author
Jonas Thiem
committed
Add a document describing how p4a interacts with pip & python packages
1 parent f6f6f19 commit 901f9e4

File tree

1 file changed

+151
-0
lines changed

1 file changed

+151
-0
lines changed

doc/source/contribute.rst

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,154 @@ Release checklist
7979
- [ ] `armeabi-v7a`
8080
- [ ] `arm64-v8a`
8181
- [ ] Check that the version number is correct
82+
83+
84+
85+
How python-for-android uses `pip`
86+
---------------------------------
87+
88+
*Last update: July 2019*
89+
90+
This section is meant to provide a quick summary how
91+
p4a (=python-for-android) uses pip and python packages in
92+
its build process.
93+
**It is written for a python
94+
packagers point of view, not for regular end users or
95+
contributors,** to assist with making pip developers and
96+
other packaging experts aware of p4a's packaging needs.
97+
98+
Please note this section just attempts to neutrally list the
99+
current mechanisms, so some of this isn't necessarily meant
100+
to stay but just how things work inside p4a in
101+
this very moment.
102+
103+
104+
Basic concepts
105+
~~~~~~~~~~~~~~
106+
107+
*(This part repeats other parts of the docs, for the sake of
108+
making this a more independent read)*
109+
110+
p4a builds & packages a python application for use on Android.
111+
It does this by providing a Java wrapper, and for graphical applications
112+
an SDL2-based wrapper which can be used with the kivy UI toolkit if
113+
desired (or alternatively just plain PySDL2). Any such python application
114+
will of course have further library dependencies to do its work.
115+
116+
p4a supports two types of package dependencies for a project:
117+
118+
**Recipe:** install script in custom p4a format. Can either install
119+
C/C++ or other things that cannot be pulled in via pip, or things
120+
that can be installed via pip but break on android by default.
121+
These are maintained primarily inside the p4a source tree by p4a
122+
contributors and interested folks.
123+
124+
**Python package:** any random pip python package can be directly
125+
installed if it doesn't need adjustments to work for Android.
126+
127+
p4a will map any dependency to an internal recipe if present, and
128+
otherwise use pip to obtain it regularly from whatever external source.
129+
130+
131+
Install process regarding packages
132+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
133+
134+
The install/build process of a p4a project, as triggered by the
135+
`p4a apk` command, roughly works as follows in regards to python
136+
packages:
137+
138+
1. The user has specified a project folder to install. This is either
139+
just a folder with python scripts and a `main.py`, or it may
140+
also have a `pyproject.toml` for a more standardized install.
141+
142+
2. Dependencies are collected: they can be either specified via
143+
``--requirements`` as a list of names or pip-style URLs, or p4a
144+
can optionally scan them from a project folder via the
145+
pep517 library (if there is a `pyproject.toml` or `setup.py`).
146+
147+
3. The collected dependencies are mapped to p4a's recipes if any are
148+
available for them, otherwise they're kept around as external
149+
regular package references.
150+
151+
4. All the dependencies mapped to recipes are built via p4a's internal
152+
mechanisms to build these recipes. (This may or may not indirectly
153+
use pip, depending on whether the recipe wraps a python package
154+
or not and uses pip to install or not.)
155+
156+
5. **If the user has specified to install the project in standardized
157+
ways,** then the `setup.py`/whatever build system
158+
of the project will be run. This happens with cross compilation set up
159+
(`CC`/`CFLAGS`/... set to use the
160+
proper toolchain) and a custom site-packages location.
161+
The actual comand is a simple `pip install .` in the project folder
162+
with some extra options: e.g. all dependencies that were already
163+
installed by recipes will be pinned with a `-c` constraints file
164+
to make sure pip won't install them, and build isolation will be
165+
disabled via ``--no-build-isolation`` so pip doesn't reinstall
166+
recipe-packages on its own.
167+
168+
**If the user has not specified to use standardized build approaches**,
169+
p4a will simply install all the remaining dependencies that weren't
170+
mapped to recipes directly and just plain copy in the user project
171+
without installing. Any `setup.py` or `pyproject.toml` of the user
172+
project will then be ignored in this step.
173+
174+
6. Google's gradle is invoked to package it all up into an `.apk`.
175+
176+
177+
Overall process / package relevant notes for p4a
178+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
179+
180+
Here are some common things worth knowing about python-for-android's
181+
dealing with python packages:
182+
183+
- Packages will work fine without a recipe if they would also build
184+
on Linux ARM, don't use any API not available in the NDK if they
185+
use native code, and don't use any weird compiler flags the toolchain
186+
doesn't like if they use native code. The package also needs to
187+
work with cross compilation.
188+
189+
- There is currently no easy way for a package to know it is being
190+
cross-compiled (at least that we know of) other than examining the
191+
`CC` compiler that was set, or that it is being cross-compiled for
192+
Android specifically. If that breaks a package it currently needs
193+
to be worked around with a recipe.
194+
195+
- If a package does **not** work, p4a developers will often create a
196+
recipe instead of getting upstream to fix it because p4a simply
197+
is too niche.
198+
199+
- Most packages without native code will just work out of the box.
200+
Many with native code tend not to, especially if complex, e.g. numpy.
201+
202+
- Anything mapped to a p4a recipe cannot be just reinstalled by pip,
203+
specifically also not inside build isolation as a dependency.
204+
(It *may* work if the patches of the recipe are just relevant
205+
to fix runtime issues.)
206+
Therefore as of now, the best way to deal with this limitation seems
207+
to be to keep build isolation always off.
208+
209+
210+
Ideas for the future regarding packaging
211+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
212+
213+
- We in overall prefer to use the recipe mechanism less if we can.
214+
In overall the recipes are just a collection of workarounds.
215+
It may look quite hacky from the outside, since p4a
216+
version pins recipe-wrapped packages usually to make the patches reliably
217+
apply. This creates work for the recipes to be kept up-to-date, and
218+
obviously this approach doesn't scale too well. However, it has ended
219+
up as a quite practical interims solution until better ways are found.
220+
221+
- Obviously, it would be nice if packages could know they are being
222+
cross-compiled, and for Android specifically. We aren't currently aware
223+
of a good mechanism for that.
224+
225+
- If pip could actually run the recipes (instead of p4a wrapping pip and
226+
doing so) then this might even allow build isolation to work - but
227+
this might be too complex to get working. It might be more practical
228+
to just gradually reduce the reliance on recipes instead and make
229+
more packages work out of the box. This has been done e.g. with
230+
improvements to the cross-compile environment being set up automatically,
231+
and we're open for any ideas on how to improve this.
232+

0 commit comments

Comments
 (0)