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 ($(BR2_arm)$(BR2_armeb),y) 24PKG_PYTHON_ARCH = arm 25else 26PKG_PYTHON_ARCH = $(ARCH) 27endif 28PKG_PYTHON_HOST_PLATFORM = linux-$(PKG_PYTHON_ARCH) 29 30# basename does not evaluate if a file exists, so we must check to ensure 31# the _sysconfigdata__linux_*.py file exists. The "|| true" is added to return 32# an empty string if the file does not exist. 33PKG_PYTHON_SYSCONFIGDATA_PATH = $(PYTHON3_PATH)/_sysconfigdata__linux_*.py 34PKG_PYTHON_SYSCONFIGDATA_NAME = `{ [ -e $(PKG_PYTHON_SYSCONFIGDATA_PATH) ] && basename $(PKG_PYTHON_SYSCONFIGDATA_PATH) .py; } || true` 35 36# Target python packages 37PKG_PYTHON_ENV = \ 38 _PYTHON_HOST_PLATFORM="$(PKG_PYTHON_HOST_PLATFORM)" \ 39 _PYTHON_PROJECT_BASE="$(PYTHON3_DIR)" \ 40 _PYTHON_SYSCONFIGDATA_NAME="$(PKG_PYTHON_SYSCONFIGDATA_NAME)" \ 41 PATH=$(BR_PATH) \ 42 $(TARGET_CONFIGURE_OPTS) \ 43 PYTHONPATH="$(PYTHON3_PATH)" \ 44 PYTHONNOUSERSITE=1 45 46# Host python packages 47HOST_PKG_PYTHON_ENV = \ 48 PATH=$(BR_PATH) \ 49 PYTHONNOUSERSITE=1 \ 50 $(HOST_CONFIGURE_OPTS) 51 52# Target pep517-based packages 53PKG_PYTHON_PEP517_ENV = \ 54 $(PKG_PYTHON_ENV) 55 56PKG_PYTHON_PEP517_BUILD_CMD = \ 57 -m build -n -w 58 59PKG_PYTHON_PEP517_INSTALL_OPTS = \ 60 --interpreter=/usr/bin/python \ 61 --script-kind=posix 62 63PKG_PYTHON_PEP517_INSTALL_TARGET_CMD = \ 64 $(TOPDIR)/support/scripts/pyinstaller.py \ 65 dist/* \ 66 $(PKG_PYTHON_PEP517_INSTALL_OPTS) \ 67 --purelib=$(TARGET_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \ 68 --headers=$(TARGET_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \ 69 --scripts=$(TARGET_DIR)/usr/bin \ 70 --data=$(TARGET_DIR)/usr 71 72PKG_PYTHON_PEP517_INSTALL_STAGING_CMD = \ 73 $(TOPDIR)/support/scripts/pyinstaller.py \ 74 dist/* \ 75 $(PKG_PYTHON_PEP517_INSTALL_OPTS) \ 76 --purelib=$(STAGING_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \ 77 --headers=$(STAGING_DIR)/usr/include/python$(PYTHON3_VERSION_MAJOR) \ 78 --scripts=$(STAGING_DIR)/usr/bin \ 79 --data=$(STAGING_DIR)/usr 80 81PKG_PYTHON_PEP517_DEPENDENCIES = \ 82 host-python-pypa-build \ 83 host-python-installer 84 85# Host pep517-based packages 86HOST_PKG_PYTHON_PEP517_ENV = \ 87 $(HOST_PKG_PYTHON_ENV) 88 89HOST_PKG_PYTHON_PEP517_BUILD_CMD = \ 90 -m build -n -w 91 92HOST_PKG_PYTHON_PEP517_INSTALL_CMD = \ 93 $(TOPDIR)/support/scripts/pyinstaller.py \ 94 dist/* \ 95 --interpreter=$(HOST_DIR)/bin/python \ 96 --script-kind=posix \ 97 --purelib=$(HOST_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages \ 98 --headers=$(HOST_DIR)/include/python$(PYTHON3_VERSION_MAJOR) \ 99 --scripts=$(HOST_DIR)/bin \ 100 --data=$(HOST_DIR) 101 102# Target setuptools-based packages 103PKG_PYTHON_SETUPTOOLS_ENV = \ 104 $(PKG_PYTHON_PEP517_ENV) 105 106PKG_PYTHON_SETUPTOOLS_BUILD_CMD = \ 107 $(PKG_PYTHON_PEP517_BUILD_CMD) 108 109PKG_PYTHON_SETUPTOOLS_INSTALL_OPTS = \ 110 --install-headers=/usr/include/python$(PYTHON3_VERSION_MAJOR) \ 111 --prefix=/usr \ 112 --executable=/usr/bin/python \ 113 --single-version-externally-managed 114 115PKG_PYTHON_SETUPTOOLS_INSTALL_TARGET_CMD = \ 116 $(PKG_PYTHON_PEP517_INSTALL_TARGET_CMD) 117 118PKG_PYTHON_SETUPTOOLS_INSTALL_STAGING_CMD = \ 119 $(PKG_PYTHON_PEP517_INSTALL_STAGING_CMD) 120 121PKG_PYTHON_SETUPTOOLS_DEPENDENCIES = \ 122 $(PKG_PYTHON_PEP517_DEPENDENCIES) \ 123 host-python-setuptools 124 125# Host setuptools-based packages 126HOST_PKG_PYTHON_SETUPTOOLS_ENV = \ 127 $(HOST_PKG_PYTHON_PEP517_ENV) 128 129HOST_PKG_PYTHON_SETUPTOOLS_BUILD_CMD = \ 130 $(HOST_PKG_PYTHON_PEP517_BUILD_CMD) 131 132HOST_PKG_PYTHON_SETUPTOOLS_INSTALL_CMD = \ 133 $(HOST_PKG_PYTHON_PEP517_INSTALL_CMD) 134 135# Target setuptools-rust-based packages 136PKG_PYTHON_SETUPTOOLS_RUST_ENV = \ 137 $(PKG_PYTHON_SETUPTOOLS_ENV) \ 138 $(PKG_CARGO_ENV) \ 139 PYO3_CROSS_LIB_DIR="$(STAGING_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)" 140 141PKG_PYTHON_SETUPTOOLS_RUST_BUILD_CMD = \ 142 $(PKG_PYTHON_SETUPTOOLS_BUILD_CMD) 143 144PKG_PYTHON_SETUPTOOLS_RUST_INSTALL_TARGET_CMD = \ 145 $(PKG_PYTHON_SETUPTOOLS_INSTALL_TARGET_CMD) 146 147PKG_PYTHON_SETUPTOOLS_RUST_INSTALL_STAGING_CMD = \ 148 $(PKG_PYTHON_SETUPTOOLS_INSTALL_STAGING_CMD) 149 150PKG_PYTHON_SETUPTOOLS_RUST_DEPENDENCIES = \ 151 $(PKG_PYTHON_SETUPTOOLS_DEPENDENCIES) \ 152 host-python-setuptools-rust 153 154# Host setuptools-rust-based packages 155HOST_PKG_PYTHON_SETUPTOOLS_RUST_ENV = \ 156 $(HOST_PKG_PYTHON_SETUPTOOLS_ENV) \ 157 $(HOST_PKG_CARGO_ENV) \ 158 PYO3_CROSS_LIB_DIR="$(HOST_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)" 159 160HOST_PKG_PYTHON_SETUPTOOLS_RUST_BUILD_CMD = \ 161 $(HOST_PKG_PYTHON_SETUPTOOLS_BUILD_CMD) 162 163HOST_PKG_PYTHON_SETUPTOOLS_RUST_INSTALL_CMD = \ 164 $(HOST_PKG_PYTHON_SETUPTOOLS_INSTALL_CMD) 165 166# Target flit packages 167PKG_PYTHON_FLIT_ENV = \ 168 $(PKG_PYTHON_PEP517_ENV) 169 170PKG_PYTHON_FLIT_BUILD_CMD = \ 171 $(PKG_PYTHON_PEP517_BUILD_CMD) 172 173PKG_PYTHON_FLIT_INSTALL_TARGET_CMD = \ 174 $(PKG_PYTHON_PEP517_INSTALL_TARGET_CMD) 175 176PKG_PYTHON_FLIT_INSTALL_STAGING_CMD = \ 177 $(PKG_PYTHON_PEP517_INSTALL_STAGING_CMD) 178 179PKG_PYTHON_FLIT_DEPENDENCIES = \ 180 $(PKG_PYTHON_PEP517_DEPENDENCIES) \ 181 host-python-flit-core 182 183# Host flit packages 184HOST_PKG_PYTHON_FLIT_ENV = \ 185 $(HOST_PKG_PYTHON_PEP517_ENV) 186 187HOST_PKG_PYTHON_FLIT_BUILD_CMD = \ 188 $(HOST_PKG_PYTHON_PEP517_BUILD_CMD) 189 190HOST_PKG_PYTHON_FLIT_INSTALL_CMD = \ 191 $(HOST_PKG_PYTHON_PEP517_INSTALL_CMD) 192 193# Host flit-bootstrap packages 194HOST_PKG_PYTHON_FLIT_BOOTSTRAP_ENV = \ 195 $(HOST_PKG_PYTHON_PEP517_ENV) 196 197HOST_PKG_PYTHON_FLIT_BOOTSTRAP_BUILD_CMD = \ 198 -m flit_core.wheel 199 200HOST_PKG_PYTHON_FLIT_BOOTSTRAP_INSTALL_CMD = \ 201 $(HOST_PKG_PYTHON_PEP517_INSTALL_CMD) 202 203# Target maturin packages 204PKG_PYTHON_MATURIN_ENV = \ 205 $(PKG_PYTHON_PEP517_ENV) \ 206 $(PKG_CARGO_ENV) \ 207 PYO3_CROSS_LIB_DIR="$(STAGING_DIR)/usr/lib/python$(PYTHON3_VERSION_MAJOR)" 208 209PKG_PYTHON_MATURIN_BUILD_CMD = \ 210 $(PKG_PYTHON_PEP517_BUILD_CMD) 211 212PKG_PYTHON_MATURIN_INSTALL_TARGET_CMD = \ 213 $(PKG_PYTHON_PEP517_INSTALL_TARGET_CMD) 214 215PKG_PYTHON_MATURIN_INSTALL_STAGING_CMD = \ 216 $(PKG_PYTHON_PEP517_INSTALL_STAGING_CMD) 217 218PKG_PYTHON_MATURIN_DEPENDENCIES = \ 219 $(PKG_PYTHON_PEP517_DEPENDENCIES) \ 220 host-python-maturin 221 222# Host maturin packages 223HOST_PKG_PYTHON_MATURIN_ENV = \ 224 $(HOST_PKG_PYTHON_PEP517_ENV) \ 225 $(HOST_PKG_CARGO_ENV) \ 226 PYO3_CROSS_LIB_DIR="$(HOST_DIR)/lib/python$(PYTHON3_VERSION_MAJOR)" 227 228HOST_PKG_PYTHON_MATURIN_BUILD_CMD = \ 229 $(HOST_PKG_PYTHON_PEP517_BUILD_CMD) 230 231HOST_PKG_PYTHON_MATURIN_INSTALL_CMD = \ 232 $(HOST_PKG_PYTHON_PEP517_INSTALL_CMD) 233 234################################################################################ 235# inner-python-package -- defines how the configuration, compilation 236# and installation of a Python package should be done, implements a 237# few hooks to tune the build process and calls the generic package 238# infrastructure to generate the necessary make targets 239# 240# argument 1 is the lowercase package name 241# argument 2 is the uppercase package name, including a HOST_ prefix 242# for host packages 243# argument 3 is the uppercase package name, without the HOST_ prefix 244# for host packages 245# argument 4 is the type (target or host) 246################################################################################ 247 248define inner-python-package 249 250ifndef $(2)_SETUP_TYPE 251 ifdef $(3)_SETUP_TYPE 252 $(2)_SETUP_TYPE = $$($(3)_SETUP_TYPE) 253 else 254 $$(error "$(2)_SETUP_TYPE must be set") 255 endif 256endif 257 258$(2)_SETUP_TYPE_UPPER = $$(call UPPERCASE,$$($(2)_SETUP_TYPE)) 259 260ifneq ($$(filter-out setuptools setuptools-rust pep517 flit flit-bootstrap maturin,$$($(2)_SETUP_TYPE)),) 261$$(error "Invalid $(2)_SETUP_TYPE. Valid options are 'maturin', 'setuptools', 'setuptools-rust', 'pep517' or 'flit'.") 262endif 263ifeq ($(4)-$$($(2)_SETUP_TYPE),target-flit-bootstrap) 264$$(error flit-bootstrap setup type only supported for host packages) 265endif 266 267# We need to vendor the Cargo crates at download time for pyo3 based 268# packages. 269# 270ifneq ($$(filter maturin setuptools-rust,$$($(2)_SETUP_TYPE)),) 271ifeq ($(4),target) 272$(2)_DL_ENV = $$(PKG_CARGO_ENV) 273else 274$(2)_DL_ENV = $$(HOST_PKG_CARGO_ENV) 275endif 276ifndef $(2)_CARGO_MANIFEST_PATH 277ifdef $(3)_CARGO_MANIFEST_PATH 278$(2)_DL_ENV += BR_CARGO_MANIFEST_PATH=$$($(3)_CARGO_MANIFEST_PATH) 279else 280ifneq ($$($(2)_SUBDIR),) 281$(2)_DL_ENV += BR_CARGO_MANIFEST_PATH=$$($(2)_SUBDIR)/Cargo.toml 282endif 283endif 284else 285$(2)_DL_ENV += BR_CARGO_MANIFEST_PATH=$$($(2)_CARGO_MANIFEST_PATH) 286endif 287endif 288 289# Target packages need both the python interpreter on the target (for 290# runtime) and the python interpreter on the host (for 291# compilation). However, host packages only need the python 292# interpreter on the host. 293# 294ifeq ($(4),target) 295$(2)_DEPENDENCIES += host-python3 python3 296else 297$(2)_DEPENDENCIES += host-python3 298endif # ($(4),target) 299 300# Setup type specific dependencies are the same whether we are 301# building for the host or the target. 302# 303ifeq ($$($(2)_SETUP_TYPE),flit-bootstrap) 304# Don't add dependency on host-python-installer for 305# host-python-installer itself, and its dependencies. 306ifeq ($$(filter host-python-flit-core host-python-installer,$(1)),) 307$(2)_DEPENDENCIES += host-python-installer 308endif 309else 310$(2)_DEPENDENCIES += $$(PKG_PYTHON_$$($(2)_SETUP_TYPE_UPPER)_DEPENDENCIES) 311endif 312 313# Pyo3 based packages(setuptools-rust and maturin) will need rust 314# toolchain dependencies for the host Python interpreter (both host 315# and target). 316# 317ifneq ($$(filter maturin setuptools-rust,$$($(2)_SETUP_TYPE)),) 318$(2)_DEPENDENCIES += host-rustc 319$(2)_DOWNLOAD_POST_PROCESS = cargo 320$(2)_DOWNLOAD_DEPENDENCIES = host-rustc 321endif # SETUP_TYPE 322 323ifeq ($(4),target) 324# 325# Build step. Only define it if not already defined by the package .mk 326# file. 327# 328ifndef $(2)_BUILD_CMDS 329define $(2)_BUILD_CMDS 330 (cd $$($$(PKG)_BUILDDIR)/; \ 331 $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \ 332 $$($$(PKG)_ENV) \ 333 $$(HOST_DIR)/bin/python3 \ 334 $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_BUILD_CMD) \ 335 $$($$(PKG)_BUILD_OPTS)) 336endef 337endif 338 339# 340# Target installation step. Only define it if not already defined by 341# the package .mk file. 342# 343ifndef $(2)_INSTALL_TARGET_CMDS 344define $(2)_INSTALL_TARGET_CMDS 345 (cd $$($$(PKG)_BUILDDIR)/; \ 346 $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \ 347 $$($$(PKG)_ENV) \ 348 $$(HOST_DIR)/bin/python3 \ 349 $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_INSTALL_TARGET_CMD) \ 350 $$($$(PKG)_INSTALL_TARGET_OPTS)) 351endef 352endif 353 354# 355# Staging installation step. Only define it if not already defined by 356# the package .mk file. 357# 358ifndef $(2)_INSTALL_STAGING_CMDS 359define $(2)_INSTALL_STAGING_CMDS 360 (cd $$($$(PKG)_BUILDDIR)/; \ 361 $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \ 362 $$($$(PKG)_ENV) \ 363 $$(HOST_DIR)/bin/python3 \ 364 $$(PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_INSTALL_STAGING_CMD) \ 365 $$($$(PKG)_INSTALL_STAGING_OPTS)) 366endef 367endif 368 369else # host 370 371# 372# Host build step. Only define it if not already defined by the package .mk 373# file. 374# 375ifndef $(2)_BUILD_CMDS 376define $(2)_BUILD_CMDS 377 (cd $$($$(PKG)_BUILDDIR)/; \ 378 $$(HOST_PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \ 379 $$($$(PKG)_ENV) \ 380 $$(HOST_DIR)/bin/python3 \ 381 $$(HOST_PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_BUILD_CMD) \ 382 $$($$(PKG)_BUILD_OPTS)) 383endef 384endif 385 386# 387# Host installation step. Only define it if not already defined by the 388# package .mk file. 389# 390ifndef $(2)_INSTALL_CMDS 391define $(2)_INSTALL_CMDS 392 (cd $$($$(PKG)_BUILDDIR)/; \ 393 $$(HOST_PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_ENV) \ 394 $$($$(PKG)_ENV) \ 395 $$(HOST_DIR)/bin/python3 \ 396 $$(HOST_PKG_PYTHON_$$($$(PKG)_SETUP_TYPE_UPPER)_INSTALL_CMD) \ 397 $$($$(PKG)_INSTALL_OPTS)) 398endef 399endif 400 401endif # host / target 402 403# Call the generic package infrastructure to generate the necessary 404# make targets 405$(call inner-generic-package,$(1),$(2),$(3),$(4)) 406 407endef 408 409################################################################################ 410# python-package -- the target generator macro for Python packages 411################################################################################ 412 413python-package = $(call inner-python-package,$(pkgname),$(call UPPERCASE,$(pkgname)),$(call UPPERCASE,$(pkgname)),target) 414host-python-package = $(call inner-python-package,host-$(pkgname),$(call UPPERCASE,host-$(pkgname)),$(call UPPERCASE,$(pkgname)),host) 415