pkg-python.mk 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  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. PKG_PYTHON_DISTUTILS_BUILD_CMD = \
  55. setup.py build \
  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_CMD = \
  61. setup.py install --no-compile \
  62. $(PKG_PYTHON_DISTUTILS_INSTALL_OPTS) \
  63. --root=$(TARGET_DIR)
  64. PKG_PYTHON_DISTUTILS_INSTALL_STAGING_CMD = \
  65. setup.py install \
  66. $(PKG_PYTHON_DISTUTILS_INSTALL_OPTS) \
  67. --root=$(STAGING_DIR)
  68. # Host distutils-based packages
  69. HOST_PKG_PYTHON_DISTUTILS_ENV = \
  70. $(HOST_PKG_PYTHON_ENV)
  71. HOST_PKG_PYTHON_DISTUTILS_BUILD_CMD = \
  72. setup.py build \
  73. HOST_PKG_PYTHON_DISTUTILS_INSTALL_CMD = \
  74. setup.py install \
  75. --prefix=$(HOST_DIR)
  76. # Target setuptools-based packages
  77. PKG_PYTHON_SETUPTOOLS_ENV = \
  78. $(PKG_PYTHON_ENV)
  79. PKG_PYTHON_SETUPTOOLS_CMD = \
  80. $(if $(wildcard $($(PKG)_BUILDDIR)/setup.py),setup.py,-c 'from setuptools import setup;setup()')
  81. PKG_PYTHON_SETUPTOOLS_BUILD_CMD = \
  82. $(PKG_PYTHON_SETUPTOOLS_CMD) build
  83. PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS = \
  84. --install-headers=/usr/include/python$(PYTHON3_VERSION_MAJOR) \
  85. --prefix=/usr \
  86. --executable=/usr/bin/python \
  87. --single-version-externally-managed
  88. PKG_PYTHON_SETUPTOOLS_INSTALL_TARGET_CMD = \
  89. $(PKG_PYTHON_SETUPTOOLS_CMD) \
  90. install --no-compile \
  91. $(PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS) \
  92. --root=$(TARGET_DIR)
  93. PKG_PYTHON_SETUPTOOLS_INSTALL_STAGING_CMD = \
  94. $(PKG_PYTHON_SETUPTOOLS_CMD) \
  95. install \
  96. $(PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS) \
  97. --root=$(STAGING_DIR)
  98. # Host setuptools-based packages
  99. HOST_PKG_PYTHON_SETUPTOOLS_ENV = \
  100. $(HOST_PKG_PYTHON_ENV)
  101. HOST_PKG_PYTHON_SETUPTOOLS_BUILD_CMD = \
  102. $(PKG_PYTHON_SETUPTOOLS_CMD) build
  103. HOST_PKG_PYTHON_SETUPTOOLS_INSTALL_CMD = \
  104. $(PKG_PYTHON_SETUPTOOLS_CMD) \
  105. install \
  106. --prefix=$(HOST_DIR) \
  107. --root=/ \
  108. --single-version-externally-managed
  109. # Target setuptools-rust-based packages
  110. PKG_PYTHON_SETUPTOOLS_RUST_ENV = \
  111. $(PKG_PYTHON_SETUPTOOLS_ENV) \
  112. $(PKG_CARGO_ENV) \
  113. PYO3_CROSS_LIB_DIR="$(STAGING_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)"
  114. PKG_PYTHON_SETUPTOOLS_RUST_BUILD_CMD = \
  115. $(PKG_PYTHON_SETUPTOOLS_BUILD_CMD)
  116. PKG_PYTHON_SETUPTOOLS_RUST_INSTALL_TARGET_CMD = \
  117. $(PKG_PYTHON_SETUPTOOLS_INSTALL_TARGET_CMD)
  118. PKG_PYTHON_SETUPTOOLS_RUST_INSTALL_STAGING_CMD = \
  119. $(PKG_PYTHON_SETUPTOOLS_INSTALL_STAGING_CMD)
  120. # Host setuptools-rust-based packages
  121. HOST_PKG_PYTHON_SETUPTOOLS_RUST_ENV = \
  122. $(HOST_PKG_PYTHON_SETUPTOOLS_ENV) \
  123. $(HOST_PKG_CARGO_ENV) \
  124. PYO3_CROSS_LIB_DIR="$(HOST_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)"
  125. HOST_PKG_PYTHON_SETUPTOOLS_RUST_BUILD_CMD = \
  126. $(HOST_PKG_PYTHON_SETUPTOOLS_BUILD_CMD)
  127. HOST_PKG_PYTHON_SETUPTOOLS_RUST_INSTALL_CMD = \
  128. $(HOST_PKG_PYTHON_SETUPTOOLS_INSTALL_CMD)
  129. # Target pep517-based packages
  130. PKG_PYTHON_PEP517_ENV = \
  131. $(PKG_PYTHON_ENV)
  132. PKG_PYTHON_PEP517_BUILD_CMD = \
  133. -m build -n -w
  134. PKG_PYTHON_PEP517_INSTALL_OPTS = \
  135. --interpreter=/usr/bin/python \
  136. --script-kind=posix
  137. PKG_PYTHON_PEP517_INSTALL_TARGET_CMD = \
  138. $(TOPDIR)/support/scripts/pyinstaller.py \
  139. dist/* \
  140. $(PKG_PYTHON_PEP517_INSTALL_OPTS) \
  141. --purelib=$(TARGET_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \
  142. --headers=$(TARGET_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \
  143. --scripts=$(TARGET_DIR)/usr/bin \
  144. --data=$(TARGET_DIR)/usr
  145. PKG_PYTHON_PEP517_INSTALL_STAGING_CMD = \
  146. $(TOPDIR)/support/scripts/pyinstaller.py \
  147. dist/* \
  148. $(PKG_PYTHON_PEP517_INSTALL_OPTS) \
  149. --purelib=$(STAGING_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \
  150. --headers=$(STAGING_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \
  151. --scripts=$(STAGING_DIR)/usr/bin \
  152. --data=$(STAGING_DIR)/usr
  153. # Host pep517-based packages
  154. HOST_PKG_PYTHON_PEP517_ENV = \
  155. $(HOST_PKG_PYTHON_ENV)
  156. HOST_PKG_PYTHON_PEP517_BUILD_CMD = \
  157. -m build -n -w
  158. HOST_PKG_PYTHON_PEP517_INSTALL_CMD = \
  159. $(TOPDIR)/support/scripts/pyinstaller.py \
  160. dist/* \
  161. --interpreter=$(HOST_DIR)/bin/python \
  162. --script-kind=posix \
  163. --purelib=$(HOST_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \
  164. --headers=$(HOST_DIR)/include/python$(PYTHON3_VERSION_MAJOR) \
  165. --scripts=$(HOST_DIR)/bin \
  166. --data=$(HOST_DIR)
  167. # Target flit packages
  168. PKG_PYTHON_FLIT_ENV = \
  169. $(PKG_PYTHON_PEP517_ENV)
  170. PKG_PYTHON_FLIT_BUILD_CMD = \
  171. $(PKG_PYTHON_PEP517_BUILD_CMD)
  172. PKG_PYTHON_FLIT_INSTALL_TARGET_CMD = \
  173. $(PKG_PYTHON_PEP517_INSTALL_TARGET_CMD)
  174. PKG_PYTHON_FLIT_INSTALL_STAGING_CMD = \
  175. $(PKG_PYTHON_PEP517_INSTALL_STAGING_CMD)
  176. # Host flit packages
  177. HOST_PKG_PYTHON_FLIT_ENV = \
  178. $(HOST_PKG_PYTHON_PEP517_ENV)
  179. HOST_PKG_PYTHON_FLIT_BUILD_CMD = \
  180. $(HOST_PKG_PYTHON_PEP517_BUILD_CMD)
  181. HOST_PKG_PYTHON_FLIT_INSTALL_CMD = \
  182. $(HOST_PKG_PYTHON_PEP517_INSTALL_CMD)
  183. # Host flit-bootstrap packages
  184. HOST_PKG_PYTHON_FLIT_BOOTSTRAP_ENV = \
  185. $(HOST_PKG_PYTHON_PEP517_ENV)
  186. HOST_PKG_PYTHON_FLIT_BOOTSTRAP_BUILD_CMD = \
  187. -m flit_core.wheel
  188. HOST_PKG_PYTHON_FLIT_BOOTSTRAP_INSTALL_CMD = \
  189. $(HOST_PKG_PYTHON_PEP517_INSTALL_CMD)
  190. # Target maturin packages
  191. PKG_PYTHON_MATURIN_ENV = \
  192. $(PKG_PYTHON_PEP517_ENV) \
  193. $(PKG_CARGO_ENV) \
  194. PYO3_CROSS_LIB_DIR="$(STAGING_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)"
  195. PKG_PYTHON_MATURIN_BUILD_CMD = \
  196. $(PKG_PYTHON_PEP517_BUILD_CMD)
  197. PKG_PYTHON_MATURIN_INSTALL_TARGET_CMD = \
  198. $(PKG_PYTHON_PEP517_INSTALL_TARGET_CMD)
  199. PKG_PYTHON_MATURIN_INSTALL_STAGING_CMD = \
  200. $(PKG_PYTHON_PEP517_INSTALL_STAGING_CMD)
  201. # Host maturin packages
  202. HOST_PKG_PYTHON_MATURIN_ENV = \
  203. $(HOST_PKG_PYTHON_PEP517_ENV) \
  204. $(HOST_PKG_CARGO_ENV) \
  205. PYO3_CROSS_LIB_DIR="$(HOST_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)"
  206. HOST_PKG_PYTHON_MATURIN_BUILD_CMD = \
  207. $(HOST_PKG_PYTHON_PEP517_BUILD_CMD)
  208. PKG_PYTHON_MATURIN_INSTALL_CMD = \
  209. $(PKG_PYTHON_PEP517_INSTALL_CMD)
  210. ################################################################################
  211. # inner-python-package -- defines how the configuration, compilation
  212. # and installation of a Python package should be done, implements a
  213. # few hooks to tune the build process and calls the generic package
  214. # infrastructure to generate the necessary make targets
  215. #
  216. # argument 1 is the lowercase package name
  217. # argument 2 is the uppercase package name, including a HOST_ prefix
  218. # for host packages
  219. # argument 3 is the uppercase package name, without the HOST_ prefix
  220. # for host packages
  221. # argument 4 is the type (target or host)
  222. ################################################################################
  223. define inner-python-package
  224. ifndef $(2)_SETUP_TYPE
  225. ifdef $(3)_SETUP_TYPE
  226. $(2)_SETUP_TYPE = $$($(3)_SETUP_TYPE)
  227. else
  228. $$(error "$(2)_SETUP_TYPE must be set")
  229. endif
  230. endif
  231. $(2)_SETUP_TYPE_UPPER = $$(call UPPERCASE,$$($(2)_SETUP_TYPE))
  232. ifneq ($$(filter-out distutils setuptools setuptools-rust pep517 flit flit-bootstrap maturin,$$($(2)_SETUP_TYPE)),)
  233. $$(error "Invalid $(2)_SETUP_TYPE. Valid options are 'distutils', 'maturin', 'setuptools', 'setuptools-rust', 'pep517' or 'flit'.")
  234. endif
  235. ifeq ($(4)-$$($(2)_SETUP_TYPE),target-flit-bootstrap)
  236. $$(error flit-bootstrap setup type only supported for host packages)
  237. endif
  238. # We need to vendor the Cargo crates at download time for pyo3 based
  239. # packages.
  240. #
  241. ifneq ($$(filter maturin setuptools-rust,$$($(2)_SETUP_TYPE)),)
  242. ifeq ($(4),target)
  243. $(2)_DL_ENV = $$(PKG_CARGO_ENV)
  244. else
  245. $(2)_DL_ENV = $$(HOST_PKG_CARGO_ENV)
  246. endif
  247. ifndef $(2)_CARGO_MANIFEST_PATH
  248. ifdef $(3)_CARGO_MANIFEST_PATH
  249. $(2)_DL_ENV += BR_CARGO_MANIFEST_PATH=$$($(3)_CARGO_MANIFEST_PATH)
  250. else
  251. ifneq ($$($(2)_SUBDIR),)
  252. $(2)_DL_ENV += BR_CARGO_MANIFEST_PATH=$$($(2)_SUBDIR)/Cargo.toml
  253. endif
  254. endif
  255. else
  256. $(2)_DL_ENV += BR_CARGO_MANIFEST_PATH=$$($(2)_CARGO_MANIFEST_PATH)
  257. endif
  258. endif
  259. # Target packages need both the python interpreter on the target (for
  260. # runtime) and the python interpreter on the host (for
  261. # compilation). However, host packages only need the python
  262. # interpreter on the host.
  263. #
  264. ifeq ($(4),target)
  265. $(2)_DEPENDENCIES += host-python3 python3
  266. else
  267. $(2)_DEPENDENCIES += host-python3
  268. endif # ($(4),target)
  269. # Setuptools based packages will need setuptools for the host Python
  270. # interpreter (both host and target).
  271. #
  272. ifneq ($$(filter setuptools setuptools-rust,$$($(2)_SETUP_TYPE)),)
  273. $(2)_DEPENDENCIES += host-python-setuptools
  274. ifeq ($$($(2)_SETUP_TYPE),setuptools-rust)
  275. $(2)_DEPENDENCIES += host-python-setuptools-rust
  276. endif
  277. else ifneq ($$(filter flit maturin pep517,$$($(2)_SETUP_TYPE)),)
  278. $(2)_DEPENDENCIES += host-python-pypa-build host-python-installer
  279. ifeq ($$($(2)_SETUP_TYPE),flit)
  280. $(2)_DEPENDENCIES += host-python-flit-core
  281. endif
  282. ifeq ($$($(2)_SETUP_TYPE),maturin)
  283. $(2)_DEPENDENCIES += host-python-maturin
  284. endif
  285. else ifeq ($$($(2)_SETUP_TYPE),flit-bootstrap)
  286. # Don't add dependency on host-python-installer for
  287. # host-python-installer itself, and its dependencies.
  288. ifeq ($$(filter host-python-flit-core host-python-installer,$(1)),)
  289. $(2)_DEPENDENCIES += host-python-installer
  290. endif
  291. endif
  292. # Pyo3 based packages(setuptools-rust and maturin) will need rust
  293. # toolchain dependencies for the host Python interpreter (both host
  294. # and target).
  295. #
  296. ifneq ($$(filter maturin setuptools-rust,$$($(2)_SETUP_TYPE)),)
  297. $(2)_DEPENDENCIES += host-rustc
  298. $(2)_DOWNLOAD_POST_PROCESS = cargo
  299. $(2)_DOWNLOAD_DEPENDENCIES = host-rustc
  300. endif # SETUP_TYPE
  301. ifeq ($(4),target)
  302. #
  303. # Build step. Only define it if not already defined by the package .mk
  304. # file.
  305. #
  306. ifndef $(2)_BUILD_CMDS
  307. define $(2)_BUILD_CMDS
  308. (cd $$($$(PKG)_BUILDDIR)/; \
  309. $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \
  310. $$($$(PKG)_ENV) \
  311. $$(HOST_DIR)/bin/python3 \
  312. $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_BUILD_CMD) \
  313. $$($$(PKG)_BUILD_OPTS))
  314. endef
  315. endif
  316. #
  317. # Target installation step. Only define it if not already defined by
  318. # the package .mk file.
  319. #
  320. ifndef $(2)_INSTALL_TARGET_CMDS
  321. define $(2)_INSTALL_TARGET_CMDS
  322. (cd $$($$(PKG)_BUILDDIR)/; \
  323. $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \
  324. $$($$(PKG)_ENV) \
  325. $$(HOST_DIR)/bin/python3 \
  326. $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_INSTALL_TARGET_CMD) \
  327. $$($$(PKG)_INSTALL_TARGET_OPTS))
  328. endef
  329. endif
  330. #
  331. # Staging installation step. Only define it if not already defined by
  332. # the package .mk file.
  333. #
  334. ifndef $(2)_INSTALL_STAGING_CMDS
  335. define $(2)_INSTALL_STAGING_CMDS
  336. (cd $$($$(PKG)_BUILDDIR)/; \
  337. $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \
  338. $$($$(PKG)_ENV) \
  339. $$(HOST_DIR)/bin/python3 \
  340. $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_INSTALL_STAGING_CMD) \
  341. $$($$(PKG)_INSTALL_STAGING_OPTS))
  342. endef
  343. endif
  344. else # host
  345. #
  346. # Host build step. Only define it if not already defined by the package .mk
  347. # file.
  348. #
  349. ifndef $(2)_BUILD_CMDS
  350. define $(2)_BUILD_CMDS
  351. (cd $$($$(PKG)_BUILDDIR)/; \
  352. $$(HOST_PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \
  353. $$($$(PKG)_ENV) \
  354. $$(HOST_DIR)/bin/python3 \
  355. $$(HOST_PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_BUILD_CMD) \
  356. $$($$(PKG)_BUILD_OPTS))
  357. endef
  358. endif
  359. #
  360. # Host installation step. Only define it if not already defined by the
  361. # package .mk file.
  362. #
  363. ifndef $(2)_INSTALL_CMDS
  364. define $(2)_INSTALL_CMDS
  365. (cd $$($$(PKG)_BUILDDIR)/; \
  366. $$(HOST_PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \
  367. $$($$(PKG)_ENV) \
  368. $$(HOST_DIR)/bin/python3 \
  369. $$(HOST_PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_INSTALL_CMD) \
  370. $$($$(PKG)_INSTALL_OPTS))
  371. endef
  372. endif
  373. endif # host / target
  374. # Call the generic package infrastructure to generate the necessary
  375. # make targets
  376. $(call inner-generic-package,$(1),$(2),$(3),$(4))
  377. endef
  378. ################################################################################
  379. # python-package -- the target generator macro for Python packages
  380. ################################################################################
  381. python-package = $(call inner-python-package,$(pkgname),$(call UPPERCASE,$(pkgname)),$(call UPPERCASE,$(pkgname)),target)
  382. host-python-package = $(call inner-python-package,host-$(pkgname),$(call UPPERCASE,host-$(pkgname)),$(call UPPERCASE,$(pkgname)),host)