xref: /OK3568_Linux_fs/buildroot/package/pkg-python.mk (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1################################################################################
2# Python package infrastructure
3#
4# This file implements an infrastructure that eases development of
5# package .mk files for Python packages. It should be used for all
6# packages that use Python setup.py/setuptools as their build system.
7#
8# See the Buildroot documentation for details on the usage of this
9# infrastructure
10#
11# In terms of implementation, this Python infrastructure requires the
12# .mk file to only specify metadata information about the package:
13# name, version, download URL, etc.
14#
15# We still allow the package .mk file to override what the different
16# steps are doing, if needed. For example, if <PKG>_BUILD_CMDS is
17# already defined, it is used as the list of commands to perform to
18# build the package, instead of the default Python behaviour. The
19# package can also define some post operation hooks.
20#
21################################################################################
22
23ifeq ($$($(2)_NEEDS_HOST_PYTHON),python2)
24$$(error "$(1): python2 is no longer supported!")
25endif
26
27ifeq ($(BR2_arm)$(BR2_armeb),y)
28PKG_PYTHON_ARCH = arm
29else
30PKG_PYTHON_ARCH = $(ARCH)
31endif
32PKG_PYTHON_HOST_PLATFORM = linux-$(PKG_PYTHON_ARCH)
33
34# basename does not evaluate if a file exists, so we must check to ensure
35# the _sysconfigdata__linux_*.py file exists. The "|| true" is added to return
36# an empty string if the file does not exist.
37PKG_PYTHON_SYSCONFIGDATA_PATH = $(PYTHON3_PATH)/_sysconfigdata__linux_*.py
38PKG_PYTHON_SYSCONFIGDATA_NAME = `{ [ -e $(PKG_PYTHON_SYSCONFIGDATA_PATH) ] && basename $(PKG_PYTHON_SYSCONFIGDATA_PATH) .py; } || true`
39
40# Target python packages
41PKG_PYTHON_ENV = \
42	_PYTHON_HOST_PLATFORM="$(PKG_PYTHON_HOST_PLATFORM)" \
43	_PYTHON_PROJECT_BASE="$(PYTHON3_DIR)" \
44	_PYTHON_SYSCONFIGDATA_NAME="$(PKG_PYTHON_SYSCONFIGDATA_NAME)" \
45	PATH=$(BR_PATH) \
46	$(TARGET_CONFIGURE_OPTS) \
47	PYTHONPATH="$(PYTHON3_PATH)" \
48	PYTHONNOUSERSITE=1 \
49	_python_sysroot=$(STAGING_DIR) \
50	_python_prefix=/usr \
51	_python_exec_prefix=/usr
52
53# Host python packages
54HOST_PKG_PYTHON_ENV = \
55	PATH=$(BR_PATH) \
56	PYTHONNOUSERSITE=1 \
57	$(HOST_CONFIGURE_OPTS)
58
59# Target distutils-based packages
60PKG_PYTHON_DISTUTILS_ENV = \
61	$(PKG_PYTHON_ENV) \
62	LDSHARED="$(TARGET_CROSS)gcc -shared" \
63	SETUPTOOLS_USE_DISTUTILS=stdlib \
64
65PKG_PYTHON_DISTUTILS_BUILD_OPTS = \
66	--executable=/usr/bin/python
67
68PKG_PYTHON_DISTUTILS_INSTALL_OPTS = \
69	--install-headers=/usr/include/python$(PYTHON3_VERSION_MAJOR) \
70	--prefix=/usr
71
72PKG_PYTHON_DISTUTILS_INSTALL_TARGET_OPTS = \
73	$(PKG_PYTHON_DISTUTILS_INSTALL_OPTS) \
74	--root=$(TARGET_DIR)
75
76PKG_PYTHON_DISTUTILS_INSTALL_STAGING_OPTS = \
77	$(PKG_PYTHON_DISTUTILS_INSTALL_OPTS) \
78	--root=$(STAGING_DIR)
79
80# Host distutils-based packages
81HOST_PKG_PYTHON_DISTUTILS_ENV = \
82	$(HOST_PKG_PYTHON_ENV) \
83	SETUPTOOLS_USE_DISTUTILS=stdlib
84
85HOST_PKG_PYTHON_DISTUTILS_INSTALL_OPTS = \
86	--prefix=$(HOST_DIR)
87
88# Target setuptools-based packages
89PKG_PYTHON_SETUPTOOLS_ENV = \
90	$(PKG_PYTHON_ENV) \
91	SETUPTOOLS_USE_DISTUTILS=stdlib
92
93PKG_PYTHON_SETUPTOOLS_CMD = \
94	$(if $(wildcard $($(PKG)_BUILDDIR)/setup.py),setup.py,-c 'from setuptools import setup;setup()')
95
96PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS = \
97	--install-headers=/usr/include/python$(PYTHON3_VERSION_MAJOR) \
98	--prefix=/usr \
99	--executable=/usr/bin/python \
100	--single-version-externally-managed
101
102PKG_PYTHON_SETUPTOOLS_INSTALL_TARGET_OPTS = \
103	$(PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS) \
104	--root=$(TARGET_DIR)
105
106PKG_PYTHON_SETUPTOOLS_INSTALL_STAGING_OPTS = \
107	$(PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS) \
108	--root=$(STAGING_DIR)
109
110# Host setuptools-based packages
111HOST_PKG_PYTHON_SETUPTOOLS_ENV = \
112	$(HOST_PKG_PYTHON_ENV) \
113	SETUPTOOLS_USE_DISTUTILS=stdlib
114
115HOST_PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS = \
116	--prefix=$(HOST_DIR) \
117	--root=/ \
118	--single-version-externally-managed
119
120# Target pep517-based packages
121PKG_PYTHON_PEP517_ENV = \
122	$(PKG_PYTHON_ENV)
123
124PKG_PYTHON_PEP517_INSTALL_OPTS = \
125	--interpreter=/usr/bin/python \
126	--script-kind=posix
127
128PKG_PYTHON_PEP517_INSTALL_TARGET_OPTS = \
129	$(PKG_PYTHON_PEP517_INSTALL_OPTS) \
130	--purelib=$(TARGET_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \
131	--headers=$(TARGET_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \
132	--scripts=$(TARGET_DIR)/usr/bin \
133	--data=$(TARGET_DIR)/usr
134
135PKG_PYTHON_PEP517_INSTALL_STAGING_OPTS = \
136	$(PKG_PYTHON_PEP517_INSTALL_OPTS) \
137	--purelib=$(STAGING_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \
138	--headers=$(STAGING_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \
139	--scripts=$(STAGING_DIR)/usr/bin \
140	--data=$(STAGING_DIR)/usr
141
142# Host pep517-based packages
143HOST_PKG_PYTHON_PEP517_ENV = \
144	$(HOST_PKG_PYTHON_ENV)
145
146HOST_PKG_PYTHON_PEP517_BOOTSTRAP_INSTALL_OPTS = \
147	--installdir=$(HOST_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages
148
149################################################################################
150# inner-python-package -- defines how the configuration, compilation
151# and installation of a Python package should be done, implements a
152# few hooks to tune the build process and calls the generic package
153# infrastructure to generate the necessary make targets
154#
155#  argument 1 is the lowercase package name
156#  argument 2 is the uppercase package name, including a HOST_ prefix
157#             for host packages
158#  argument 3 is the uppercase package name, without the HOST_ prefix
159#             for host packages
160#  argument 4 is the type (target or host)
161################################################################################
162
163define inner-python-package
164
165ifndef $(2)_SETUP_TYPE
166 ifdef $(3)_SETUP_TYPE
167  $(2)_SETUP_TYPE = $$($(3)_SETUP_TYPE)
168 else
169  $$(error "$(2)_SETUP_TYPE must be set")
170 endif
171endif
172
173# Distutils
174ifeq ($$($(2)_SETUP_TYPE),distutils)
175ifeq ($(4),target)
176$(2)_BASE_ENV = $$(PKG_PYTHON_DISTUTILS_ENV)
177$(2)_BASE_BUILD_CMD = setup.py build
178$(2)_BASE_BUILD_OPTS = $$(PKG_PYTHON_DISTUTILS_BUILD_OPTS)
179$(2)_BASE_INSTALL_TARGET_CMD  = setup.py install --no-compile $$(PKG_PYTHON_DISTUTILS_INSTALL_TARGET_OPTS)
180$(2)_BASE_INSTALL_STAGING_CMD = setup.py install $$(PKG_PYTHON_DISTUTILS_INSTALL_STAGING_OPTS)
181else
182$(2)_BASE_ENV         = $$(HOST_PKG_PYTHON_DISTUTILS_ENV)
183$(2)_BASE_BUILD_CMD   = setup.py build
184$(2)_BASE_INSTALL_CMD = setup.py install $$(HOST_PKG_PYTHON_DISTUTILS_INSTALL_OPTS)
185endif
186# Setuptools
187else ifeq ($$($(2)_SETUP_TYPE),setuptools)
188ifeq ($(4),target)
189$(2)_BASE_ENV = $$(PKG_PYTHON_SETUPTOOLS_ENV)
190$(2)_BASE_BUILD_CMD = $$(PKG_PYTHON_SETUPTOOLS_CMD) build
191$(2)_BASE_INSTALL_TARGET_CMD = $$(PKG_PYTHON_SETUPTOOLS_CMD) install --no-compile $$(PKG_PYTHON_SETUPTOOLS_INSTALL_TARGET_OPTS)
192$(2)_BASE_INSTALL_STAGING_CMD = $$(PKG_PYTHON_SETUPTOOLS_CMD) install $$(PKG_PYTHON_SETUPTOOLS_INSTALL_STAGING_OPTS)
193else
194$(2)_BASE_ENV = $$(HOST_PKG_PYTHON_SETUPTOOLS_ENV)
195$(2)_BASE_BUILD_CMD = $$(PKG_PYTHON_SETUPTOOLS_CMD) build
196$(2)_BASE_INSTALL_CMD = $$(PKG_PYTHON_SETUPTOOLS_CMD) install $$(HOST_PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS)
197endif
198else ifneq ($$(filter flit pep517,$$($(2)_SETUP_TYPE)),)
199ifeq ($(4),target)
200$(2)_BASE_ENV = $$(PKG_PYTHON_PEP517_ENV)
201$(2)_BASE_BUILD_CMD = -m build -n -w
202$(2)_BASE_INSTALL_TARGET_CMD = $(TOPDIR)/support/scripts/pyinstaller.py dist/* $$(PKG_PYTHON_PEP517_INSTALL_TARGET_OPTS)
203$(2)_BASE_INSTALL_STAGING_CMD = $(TOPDIR)/support/scripts/pyinstaller.py dist/* $$(PKG_PYTHON_PEP517_INSTALL_STAGING_OPTS)
204else
205$(2)_BASE_ENV = $$(HOST_PKG_PYTHON_PEP517_ENV)
206$(2)_BASE_BUILD_CMD = -m build -n -w
207$(2)_BASE_INSTALL_CMD = -m installer dist/*
208endif
209else ifeq ($$($(2)_SETUP_TYPE),flit-bootstrap)
210ifeq ($(4),target)
211$$(error flit-bootstrap setup type only supported for host packages)
212else
213$(2)_BASE_ENV = $$(HOST_PKG_PYTHON_PEP517_ENV)
214$(2)_BASE_BUILD_CMD = -m flit_core.wheel
215$(2)_BASE_INSTALL_CMD ?= -m installer dist/*
216endif
217else
218$$(error "Invalid $(2)_SETUP_TYPE. Valid options are 'distutils', 'setuptools', 'pep517' or 'flit'.")
219endif
220
221# Target packages need both the python interpreter on the target (for
222# runtime) and the python interpreter on the host (for
223# compilation). However, host packages only need the python
224# interpreter on the host.
225#
226ifeq ($(4),target)
227$(2)_DEPENDENCIES += host-python3 python3
228else
229$(2)_DEPENDENCIES += host-python3
230endif # ($(4),target)
231
232# Setuptools based packages will need setuptools for the host Python
233# interpreter (both host and target).
234#
235ifeq ($$($(2)_SETUP_TYPE),setuptools)
236$(2)_DEPENDENCIES += $$(if $$(filter host-python-setuptools,$(1)),,host-python-setuptools)
237else ifneq ($$(filter flit pep517,$$($(2)_SETUP_TYPE)),)
238$(2)_DEPENDENCIES += host-python-pypa-build host-python-installer
239ifeq ($$($(2)_SETUP_TYPE),flit)
240$(2)_DEPENDENCIES += host-python-flit-core
241endif
242else ifeq ($$($(2)_SETUP_TYPE),flit-bootstrap)
243# Don't add dependency on host-python-installer for
244# host-python-installer itself, and its dependencies.
245ifeq ($$(filter host-python-flit-core host-python-installer,$(1)),)
246$(2)_DEPENDENCIES += host-python-installer
247endif
248endif # SETUP_TYPE
249
250# Python interpreter to use for building the package.
251#
252$(2)_PYTHON_INTERPRETER = $$(HOST_DIR)/bin/python
253
254#
255# Build step. Only define it if not already defined by the package .mk
256# file.
257#
258ifndef $(2)_BUILD_CMDS
259define $(2)_BUILD_CMDS
260	(cd $$($$(PKG)_BUILDDIR)/; \
261		$$($$(PKG)_BASE_ENV) $$($$(PKG)_ENV) \
262		$$($(2)_PYTHON_INTERPRETER) \
263		$$($$(PKG)_BASE_BUILD_CMD) \
264		$$($$(PKG)_BASE_BUILD_OPTS) $$($$(PKG)_BUILD_OPTS))
265endef
266endif
267
268#
269# Host installation step. Only define it if not already defined by the
270# package .mk file.
271#
272ifndef $(2)_INSTALL_CMDS
273define $(2)_INSTALL_CMDS
274	(cd $$($$(PKG)_BUILDDIR)/; \
275		$$($$(PKG)_BASE_ENV) $$($$(PKG)_ENV) \
276		$$($(2)_PYTHON_INTERPRETER) \
277		$$($$(PKG)_BASE_INSTALL_CMD) \
278		$$($$(PKG)_INSTALL_OPTS))
279endef
280endif
281
282#
283# Target installation step. Only define it if not already defined by
284# the package .mk file.
285#
286ifndef $(2)_INSTALL_TARGET_CMDS
287define $(2)_INSTALL_TARGET_CMDS
288	(cd $$($$(PKG)_BUILDDIR)/; \
289		$$($$(PKG)_BASE_ENV) $$($$(PKG)_ENV) \
290		$$($(2)_PYTHON_INTERPRETER) \
291		$$($$(PKG)_BASE_INSTALL_TARGET_CMD) \
292		$$($$(PKG)_INSTALL_TARGET_OPTS))
293endef
294endif
295
296#
297# Staging installation step. Only define it if not already defined by
298# the package .mk file.
299#
300ifndef $(2)_INSTALL_STAGING_CMDS
301define $(2)_INSTALL_STAGING_CMDS
302	(cd $$($$(PKG)_BUILDDIR)/; \
303		$$($$(PKG)_BASE_ENV) $$($$(PKG)_ENV) \
304		$$($(2)_PYTHON_INTERPRETER) \
305		$$($$(PKG)_BASE_INSTALL_STAGING_CMD) \
306		$$($$(PKG)_INSTALL_STAGING_OPTS))
307endef
308endif
309
310# Call the generic package infrastructure to generate the necessary
311# make targets
312$(call inner-generic-package,$(1),$(2),$(3),$(4))
313
314endef
315
316################################################################################
317# python-package -- the target generator macro for Python packages
318################################################################################
319
320python-package = $(call inner-python-package,$(pkgname),$(call UPPERCASE,$(pkgname)),$(call UPPERCASE,$(pkgname)),target)
321host-python-package = $(call inner-python-package,host-$(pkgname),$(call UPPERCASE,host-$(pkgname)),$(call UPPERCASE,$(pkgname)),host)
322