@@ -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