pkg-python.mk 11 KB

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