udptunnel: new package
[feed/packages.git] / lang / python / README.md
1 # Python packages folder
2
3 ## Table of contents
4
5 1. [Description](#description)
6 2. [Introduction](#introduction)
7 3. [Build considerations](#build-considerations)
8 4. [General folder structure](#general-folder-structure)
9 5. [Building a Python[3] package](#building-a-python3-package)
10 1. [PKG_BUILD_DIR](#pkg_build_dir)
11 2. [PKG_UNPACK](#pkg_unpack)
12 3. [Include python[3]-package.mk](#include-python3-packagemk)
13 4. [Add Package/<PKG_NAME> OpenWrt definitions](#add-packagepkg_name-openwrt-definitions)
14 5. [Wrapping things up so that they build](#wrapping-things-up-so-that-they-build)
15 6. [Customizing things](#customizing-things)
16 7. [Host-side Python packages for build](#host-side-python-packages-for-build)
17
18 ## Description
19
20 This section describes specifics for the Python packages that are present in this repo, and how things are structured.
21
22 In terms of license, contributing guide, etc, all of that information is described in the top [README.md](README.md) file, and it applies here as well. This document attempts to cover only technical aspects of Python/Python3 packages, and maybe some explanations about how things are (and why they are as they are).
23
24 ## Introduction
25
26 This sub-tree came to exist after a number of contributions (Python packages) were made to this repo, and the [lang](lang) subtree grew to a point where a decision was made to move all Python packages under [lang/python](lang/python).
27
28 It contains the 2 Python interpreters (Python & Python3) and Python packages. Most of the Python packages are downloaded from [pypi.org](https://pypi.org/). Python packages from [pypi.org](https://pypi.org/) are typically preferred when adding new packages.
29
30 If more packages (than the ones packaged here) are needed, they can be downloaded via [pip or pip3](https://pip.pypa.io). Note that the versions of `pip` & `setuptools` [available in this repo] are the ones that are packaged inside the Python & Python3 packages (yes, Python & Python3 come packaged with `pip` & `setuptools`).
31
32 ## Build considerations
33
34 In order to build the Python[3] interpreters, a host Python/Python3 interpreter needs to be built, in order to process some of the build for the target Python/Python3 build. The host Python[3] interpreters are also needed so that Python bytecodes are generated, so the host interpreters need to be the exact versions as on the target. And finally, the host Python[3] interpreters also provide pip & pip3, so that they may be used to install some Python[3] packages that are required to build other Python[3] packages.
35 That's why you'll also see a Python/Python3 build & staging directories.
36
37 As you're probably thinking, this sounds [and is] somewhat too much complication [just for packaging], but the status of things is-as-it-is, and it's probably much worse than what's currently visible on the surface [with respect to packaging Python[3] & packages].
38
39 As mentioned earlier, Python[3] packages are shipped with bytecodes, and the reason for this is simply performance & size.
40 The thought/discussion matrix derives a bit like this:
41 * shipping both Python source-code & bytecodes takes too much space on some devices ; Python source code & byte-code take about similar disk-size
42 * shipping only Python source code has a big performance penalty [on some lower end systems] ; something like 500 msecs (Python source-only) -> 70 msecs (Python byte-codes) time reduction for a simple "Hello World" script
43 * shipping only Python byte-codes seems like a good trade-off, and this means that `python-src` & `python3-src` can be provided for people that want the source code
44
45 By default, automatic Python[3] byte-code generation is disabled when running a Python script, in order to prevent a disk from accidentally filling up. Since some disks reside in RAM, this also means not filling up the RAM. If someone wants to convert Python source to byte-code then he/she is free to compile it [directly on the device] manually via the Python interpreter & library.
46
47 ## General folder structure
48
49 The basis of all these packages are:
50 * [lang/python/python](lang/python/python) - The Python 2.7.y interpreter (supposedly, there won't ever by a 2.8.y)
51 * [lang/python/python3](lang/python/python3) - The Python 3.x.y interpreter
52
53 These 2 are normal OpenWrt packages, which will build the Python interpreters. They also provide `python[3]-pip` & `python[3]-setuptools`. Each Python or Python3 package is actually split into multiple sub-packages [e.g. python-email, python-sqlite3, etc]. This can be viewed inside [lang/python/python/files](lang/python/python/files) & [lang/python/python3/files](lang/python/python3/files).
54
55 The reason for this splitting, is purely to offer a way for some people to package Python/Python3 in as-minimal-as-possible-and-still-runable way, and also to be somewhat maintainable when packaging. A standard Python[3] installation can take ~20-30 MBs of disk, which can be somewhat big for some people, so there are the `python[3]-base` packages which bring that down to ~5 MBs. This seems to be good enough (and interesting) for a number of people.
56
57 The Python[3] interpreters are structured like this:
58 * `python-base` (and `python3-base`), which is just the minimal package to startup Python[3] and run basic commands
59 * `python` (and `python3`) are meta-packages, which install almost everything (python[3]-base [plus] Python[3] library [minus] some unit-tests & some windows-y things)
60 * `python-light` (and `python3-light`) are `python` (and `python3`) [minus] packages that are in [lang/python/python/files](lang/python/python/files) or [lang/python/python3/files](lang/python/python3/files) ; the size of these 2 packages may be sensible (and interesting) to another group of people
61
62 All other Python & Python3 packages (aside from the 2 intepreters) typically use these files:
63 * **python[3]-host.mk** - this file contains paths and build rules for running the Python[3] interpreters on the host-side; they also provide paths to host interprete, host Python lib-dir & so on
64 * **python[3]-package.mk**
65 * includes **python[3]-host.mk**
66 * contains all the default build rules for Python[3] packages; these will be detailed below in the [Building a Python[3] package](#Building a Python[3] package) section
67
68 **Note** that Python/Python3 packages don't need to use these files (i.e. `python[3]-package.mk` & `python[3]-host.mk`), but they do provide some ease-of-use & reduction of duplicate code, especially when packaging for both Python & Python3. And they do contain some learned-lessons about packaging Python/Python3 packages, so it's a good idea to use them.
69
70 ## Building a Python[3] package
71
72 A Python package can be packaged for either Python or Python3 or both.
73
74 This section will describe both, and then it can be inferred which is for which.
75
76 Packaging for both Python & Python3 uses the `VARIANT` mechanism for packaging inside OpenWrt. (#### FIXME: find a link for this later if it exists)
77
78 ### PKG_BUILD_DIR
79
80 It's important when packaging for both Python & Python3 to override this variable, so that the build directory differs for each variant.
81
82 Typically it's just something like:
83 ```
84 PKG_BUILD_DIR:=$(BUILD_DIR)/$(BUILD_VARIANT)-pyasn1-$(PKG_VERSION)
85 ```
86 Where `pyasn1` should be some other name, or maybe `PKG_NAME`
87
88 This should be added before this include:
89 ```
90 include $(INCLUDE_DIR)/package.mk
91 ```
92
93 ### PKG_UNPACK
94
95 In many cases, this needs to be overriden. This is usually because the way Python packages are archived, don't follow the convention of other `tar.gz` packages.
96
97 So, something like:
98 ```
99 PKG_UNPACK=$(HOST_TAR) -C $(PKG_BUILD_DIR) --strip-components=1 -xzf $(DL_DIR)/$(PKG_SOURCE)
100 ```
101 should be added.
102
103 It's not important whether this is after or before `include $(INCLUDE_DIR)/package.mk`
104
105 ### Include python[3]-package.mk
106
107 If packaging for Python, add this after `include $(INCLUDE_DIR)/package.mk`
108 ```
109 include ../python-package.mk
110 ```
111
112 If packaging for Python3, add this after `include $(INCLUDE_DIR)/package.mk`
113 ```
114 include ../python3-package.mk
115 ```
116
117 Order doesn't matter between `python-package.mk` & `python3-package.mk`.
118
119 These will make sure that build rules for Python or Python3 can be specified and picked up for build.
120
121 ### Add Package/<PKG_NAME> OpenWrt definitions
122
123 This part is similar to default OpenWrt packages.
124 It's usually recommended to have a `Package/<PKG_NAME>/Default` section that's common for both Python & Python3.
125
126 Example:
127 ```
128 define Package/python-lxml/Default
129 SECTION:=lang
130 CATEGORY:=Languages
131 SUBMENU:=Python
132 URL:=https://lxml.de
133 DEPENDS:=+libxml2 +libxslt +libexslt
134 endef
135 ```
136
137 Then for each variant do something like:
138 ```
139 define Package/python-lxml
140 $(call Package/python-lxml/Default)
141 TITLE:=python-lxml
142 DEPENDS+=+PACKAGE_python-lxml:python-light +PACKAGE_python-lxml:python-codecs
143 VARIANT:=python
144 endef
145
146 define Package/python3-lxml
147 $(call Package/python-lxml/Default)
148 TITLE:=python3-lxml
149 DEPENDS+=+PACKAGE_python3-lxml:python3-light
150 VARIANT:=python3
151 endef
152 ```
153
154 Some considerations here (based on the example above):
155 * be sure to make sure that `DEPENDS` are correct for both variants; as seen in the example above, `python-codecs` is needed only for `python-lxml` ; that's because `python3-codecs` doesn't exist and is included in `python3-base` ; most of the times they are similar, sometimes they are not
156 * consider adding conditional DEPENDS for each variant ; so for each Python[3] package add `+PACKAGE_python-lxml:<dep>` as seen in the above example ; the reason for this is build-time reduction ; if you want to build Python3 only packages, this won't build Python & Python packages + dependencies ; this is a known functionality of OpenWrt build deps
157 * there is an exception to the above consideration: if adding `+PACKAGE_python-lxml` conditional deps creates circular dependencies [for some weird reason], then this can be omitted
158 * `VARIANT=python` or `VARIANT=python3` must be added
159 * typically each variant package is named `Package/python3-<something>` & `Package/python3-<something>` ; this convention makes things easier to follow, though it could work without naming things this this
160 * `TITLE` can be something a bit more verbose/neat ; typically the name is short as seen above
161
162 Following these, 2 more definitions are required:
163 ```
164 define Package/python-lxml/description
165 The lxml XML toolkit is a Pythonic binding
166 for the C libraries libxml2 and libxslt.
167 endef
168
169 define Package/python3-lxml/description
170 $(call Package/python-lxml/description)
171 .
172 (Variant for Python3)
173 endef
174 ```
175
176 Typically, the description is the same for both, so just mentioning that one is a variant of the other is sufficient.
177
178 ### Wrapping things up so that they build
179
180 If all the above prerequisites have been met, all that's left is:
181
182 ```
183 $(eval $(call PyPackage,python-lxml))
184 $(eval $(call BuildPackage,python-lxml))
185
186 $(eval $(call Py3Package,python3-lxml))
187 $(eval $(call BuildPackage,python3-lxml))
188 ```
189
190 The `$(eval $(call PyPackage,python-lxml))` part will instantiate all the default Python build rules so that the final Python package is packaged into an OpenWrt.
191 And `$(eval $(call BuildPackage,python-lxml))` will bind all the rules generated with `$(eval $(call PyPackage,python-lxml))` into the OpenWrt build system.
192
193 These packages will contain byte-codes and binaries (shared libs & other stuff).
194
195 If a user wishes to ship source code, adding 2 more lines creates 2 more packages that ship Python source code:
196 ```
197 $(eval $(call PyPackage,python-lxml))
198 $(eval $(call PyPackage,python-lxml-src))
199 $(eval $(call BuildPackage,python-lxml))
200
201 $(eval $(call Py3Package,python3-lxml))
202 $(eval $(call Py3Package,python3-lxml-src))
203 $(eval $(call BuildPackage,python3-lxml))
204 ```
205
206 The name `*-src` must be the Python package name; so for `python-lxml-src` a equivalent `python-lxml` name must exist.
207
208 ### Customizing things
209
210 Some packages need custom build rules (because they do).
211
212 For building, if a user specifies a `PyBuild/Compile` & `Py3Build/Compile` rule, this will be used to build/compile the package, instead of the default one defined in `python[3]-package.mk`.
213
214 For installing files on the target, 2 build rules are used:
215 * `PyPackage/$(1)/filespec` & `Py3Package/$(1)/filespec` which are Python library files relative to `/usr/lib/pythonX.Y` ; by default this is `/usr/lib/python$(PYTHON[3]_VERSION)/site-packages` ; most Python[3] packages generate files that get installed in this sub-folder
216 * `PyPackage/$(1)/install` & `Py3Package/$(1)/install` is similar to `Package/$(1)/install` ; these allow binary (or other files) to be installed on the target
217
218 Both the 2 above rules generate a `Package/$(1)/install` build rule, which gets picked up by the build system. Both can be used together (they are not mutually exclusive), and provide a good enough flexibility for specifying Python[3] packages.
219
220 ### Host-side Python packages for build
221
222 These can be installed via pip and ideally they should only be installed like this, because it's a bit simpler than running them through the OpenWrt build system. Build variants on the host-side build are more complicated (and nearly impossible to do sanely) in the current OpenWrt build system.
223
224 Which is why [for example] if you need python cffi on the host build, it's easier to just add it via:
225 ```
226 HOST_PYTHON_PACKAGE_BUILD_DEPENDS:="cffi==$(PKG_VERSION)"
227 HOST_PYTHON3_PACKAGE_BUILD_DEPENDS:="cffi==$(PKG_VERSION)"
228 ```
229 [cffi is one of those packages that needs a host-side package installed for both Python & Python3].
230
231 This works reasonably well in the current OpenWrt build system, as binaries get built for this package and get installed in the staging-dir `$(STAGING_DIR)/usr/lib/pythonX.Y/site-packages`.