blob: 3300f1beabe39c2c5651b100896c7f8c4369e108 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#
2# Copyright (C) 2007-2016 OpenWrt.org
3#
4# This is free software, licensed under the GNU General Public License v2.
5# See /LICENSE for more information.
6#
7
8# Note: include this file after `include $(TOPDIR)/rules.mk in your package Makefile
9
10python3_mk_path:=$(dir $(lastword $(MAKEFILE_LIST)))
11include $(python3_mk_path)python3-host.mk
12
13PYTHON3_DIR:=$(STAGING_DIR)/usr
14PYTHON3_INC_DIR:=$(PYTHON3_DIR)/include/python$(PYTHON3_VERSION)
15PYTHON3_LIB_DIR:=$(PYTHON3_DIR)/lib/python$(PYTHON3_VERSION)
16
17PYTHON3_PKG_DIR:=/usr/lib/python$(PYTHON3_VERSION)/site-packages
18
19PYTHON3:=python$(PYTHON3_VERSION)
20
21PYTHON3PATH:=$(PYTHON3_LIB_DIR):$(STAGING_DIR)/$(PYTHON3_PKG_DIR):$(PKG_INSTALL_DIR)/$(PYTHON3_PKG_DIR)
22
23-include $(PYTHON3_LIB_DIR)/openwrt/Makefile-vars
24
25# These configure args are needed in detection of path to Python header files
26# using autotools.
27CONFIGURE_ARGS += \
28 _python_sysroot="$(STAGING_DIR)" \
29 _python_prefix="/usr" \
30 _python_exec_prefix="/usr"
31
32PYTHON3_VARS = \
33 CC="$(TARGET_CC)" \
34 CCSHARED="$(TARGET_CC) $(FPIC)" \
35 CXX="$(TARGET_CXX)" \
36 LD="$(TARGET_CC)" \
37 LDSHARED="$(TARGET_CC) -shared" \
38 CFLAGS="$(TARGET_CFLAGS)" \
39 CPPFLAGS="$(TARGET_CPPFLAGS) -I$(PYTHON3_INC_DIR)" \
40 LDFLAGS="$(TARGET_LDFLAGS) -lpython$(PYTHON3_VERSION)" \
41 _PYTHON_HOST_PLATFORM="$(_PYTHON_HOST_PLATFORM)" \
42 _PYTHON_SYSCONFIGDATA_NAME="_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH)" \
43 PYTHONPATH="$(PYTHON3PATH)" \
44 PYTHONDONTWRITEBYTECODE=1 \
45 _python_sysroot="$(STAGING_DIR)" \
46 _python_prefix="/usr" \
47 _python_exec_prefix="/usr" \
48 $(CARGO_PKG_CONFIG_VARS) \
49 PYO3_CROSS_LIB_DIR="$(PYTHON3_LIB_DIR)" \
50 SETUPTOOLS_RUST_CARGO_PROFILE="$(CARGO_PKG_PROFILE)"
51
52# $(1) => directory of python script
53# $(2) => python script and its arguments
54# $(3) => additional variables
55define Python3/Run
56 cd "$(if $(strip $(1)),$(strip $(1)),.)" && \
57 $(PYTHON3_VARS) \
58 $(3) \
59 $(HOST_PYTHON3_BIN) $(2)
60endef
61
62define Python3/FixShebang
63 $(SED) "1"'!'"b;s,^#"'!'".*python.*,#"'!'"/usr/bin/python3," -i --follow-symlinks $(1)
64endef
65
66# default max recursion is 10
67PYTHON3_COMPILEALL_MAX_RECURSION_LEVEL:=20
68
69# $(1) => directory of python source files to compile
70#
71# XXX [So that you won't goof as I did]
72# Note: Yes, I tried to use the -O & -OO flags here.
73# However the generated byte-codes were not portable.
74# So, we just stuck to un-optimized byte-codes,
75# which is still way better/faster than running
76# Python sources all the time.
77#
78# Setting a fixed hash seed value is less secure than using
79# random seed values, but is necessary for reproducible builds
80# (for now).
81#
82# Should revisit this when https://bugs.python.org/issue37596
83# (and other related reproducibility issues) are fixed.
84define Python3/CompileAll
85 $(call Python3/Run,, \
86 -m compileall -r "$(PYTHON3_COMPILEALL_MAX_RECURSION_LEVEL)" -b -d '/' $(1),
87 $(if $(SOURCE_DATE_EPOCH),PYTHONHASHSEED="$(SOURCE_DATE_EPOCH)")
88 )
89endef
90
91# $(1) => target directory
92define Python3/DeleteSourceFiles
93 $(FIND) $(1) -type f -name '*.py' -delete
94endef
95
96# $(1) => target directory
97define Python3/DeleteNonSourceFiles
98 $(FIND) $(1) -not -type d -not -name '*.py' -delete
99endef
100
101# $(1) => target directory
102define Python3/DeleteEmptyDirs
103 $(FIND) $(1) -mindepth 1 -empty -type d -not -path '$(1)/CONTROL' -not -path '$(1)/CONTROL/*' -delete
104endef
105
106
107# Py3Package
108
109define Py3Package/filespec/Default
110+|$(PYTHON3_PKG_DIR)
111endef
112
113# $(1) => package name
114# $(2) => src directory
115# $(3) => dest directory
116define Py3Package/ProcessFilespec
117 $(eval $(call shexport,Py3Package/$(1)/filespec))
118 $(SHELL) $(python3_mk_path)python-package-install.sh \
119 "$(2)" "$(3)" "$$$$$(call shvar,Py3Package/$(1)/filespec)"
120endef
121
122define Py3Package
123 define Package/$(1)-src
124 $(call Package/$(1))
125 DEPENDS:=
126 CONFLICTS:=
127 PROVIDES:=
128 EXTRA_DEPENDS:=
129 TITLE+= (sources)
130 USERID:=
131 MENU:=
132 endef
133
134 define Package/$(1)-src/description
135 $$(call Package/$(1)/description)
136
137 This package contains the Python source files for $(1).
138 endef
139
140 define Package/$(1)-src/config
141 depends on PACKAGE_$(1)
142 endef
143
144 # Add default PyPackage filespec none defined
145 ifeq ($(origin Py3Package/$(1)/filespec),undefined)
146 Py3Package/$(1)/filespec=$$(Py3Package/filespec/Default)
147 endif
148
149 ifndef Py3Package/$(1)/install
150 define Py3Package/$(1)/install
151 if [ -d $(PKG_INSTALL_DIR)/usr/bin ]; then \
152 $(INSTALL_DIR) $$(1)/usr/bin ; \
153 $(CP) $(PKG_INSTALL_DIR)/usr/bin/* $$(1)/usr/bin/ ; \
154 fi
155 endef
156 endif
157
158 ifndef Package/$(1)/install
159 define Package/$(1)/install
160 $$(call Py3Package/$(1)/install,$$(1))
161 $$(call Py3Package/ProcessFilespec,$(1),$(PKG_INSTALL_DIR),$$(1))
162 $(FIND) $$(1) -name '*.exe' -delete
163 $$(call Python3/CompileAll,$$(1))
164 $$(call Python3/DeleteSourceFiles,$$(1))
165 $$(call Python3/DeleteEmptyDirs,$$(1))
166 if [ -d "$$(1)/usr/bin" ]; then \
167 $$(call Python3/FixShebang,$$(1)/usr/bin/*) ; \
168 fi
169 endef
170
171 define Package/$(1)-src/install
172 $$(call Py3Package/$(1)/install,$$(1))
173 $$(call Py3Package/ProcessFilespec,$(1),$(PKG_INSTALL_DIR),$$(1))
174 $$(call Python3/DeleteNonSourceFiles,$$(1))
175 $$(call Python3/DeleteEmptyDirs,$$(1))
176 endef
177 endif # Package/$(1)/install
178endef
179
180
181# Py3Build
182
183PYTHON3_PKG_BUILD?=1
184PYTHON3_PKG_FORCE_DISTUTILS_SETUP?=
185
186PYTHON3_PKG_SETUP_DIR?=
187PYTHON3_PKG_SETUP_GLOBAL_ARGS?=
188PYTHON3_PKG_SETUP_ARGS?=--single-version-externally-managed
189PYTHON3_PKG_SETUP_VARS?=
190
191PYTHON3_PKG_BUILD_CONFIG_SETTINGS?=
192PYTHON3_PKG_BUILD_VARS?=$(PYTHON3_PKG_SETUP_VARS)
193PYTHON3_PKG_BUILD_ARGS?=
194PYTHON3_PKG_BUILD_PATH?=$(PYTHON3_PKG_SETUP_DIR)
195
196PYTHON3_PKG_INSTALL_VARS?=
197
198PYTHON3_PKG_WHEEL_NAME?=$(subst -,_,$(if $(PYPI_SOURCE_NAME),$(PYPI_SOURCE_NAME),$(PKG_NAME)))
199PYTHON3_PKG_WHEEL_VERSION?=$(PKG_VERSION)
200
201PYTHON3_PKG_BUILD_DIR?=$(PKG_BUILD_DIR)/$(PYTHON3_PKG_BUILD_PATH)
202
203
204PYTHON3_PKG_HOST_PIP_INSTALL_ARGS = \
205 $(foreach req,$(HOST_PYTHON3_PACKAGE_BUILD_DEPENDS), \
206 --requirement \
207 $(if $(findstring /,$(req)),$(req),$(python3_mk_path)host-pip-requirements/$(req).txt) \
208 )
209
210define Py3Build/FindStdlibDepends
211 $(SHELL) $(python3_mk_path)python3-find-stdlib-depends.sh -n "$(PKG_NAME)" "$(PKG_BUILD_DIR)";
212endef
213
214ifneq ($(strip $(PYPI_NAME)),)
215define Py3Build/CheckHostPipVersionMatch
216 if [ -d "$(python3_mk_path)host-pip-requirements" ] && \
217 [ -n "$$$$($(FIND) $(python3_mk_path)host-pip-requirements -maxdepth 1 -mindepth 1 -name '*.txt' -print -quit 2>/dev/null)" ]; then \
218 if grep -q "$(PYPI_NAME)==" $(python3_mk_path)host-pip-requirements/*.txt ; then \
219 if ! grep -q "$(PYPI_NAME)==$(PKG_VERSION)" $(python3_mk_path)host-pip-requirements/*.txt ; then \
220 printf "\nPlease update version of $(PYPI_NAME) to $(PKG_VERSION) in 'host-pip-requirements'/\n\n" ; \
221 exit 1 ; \
222 fi \
223 fi \
224 fi
225endef
226endif
227
228define Py3Build/InstallBuildDepends
229 $(if $(PYTHON3_PKG_HOST_PIP_INSTALL_ARGS), \
230 $(call HostPython3/PipInstall,$(PYTHON3_PKG_HOST_PIP_INSTALL_ARGS)) \
231 )
232endef
233
234define Py3Build/Compile/Distutils
235 $(call Py3Build/InstallBuildDepends)
236 $(INSTALL_DIR) $(PKG_INSTALL_DIR)/$(PYTHON3_PKG_DIR)
237 $(call Python3/Run, \
238 $(PKG_BUILD_DIR)/$(strip $(PYTHON3_PKG_SETUP_DIR)), \
239 setup.py \
240 $(PYTHON3_PKG_SETUP_GLOBAL_ARGS) \
241 install \
242 --prefix="/usr" \
243 --root="$(PKG_INSTALL_DIR)" \
244 $(PYTHON3_PKG_SETUP_ARGS) \
245 , \
246 $(PYTHON3_PKG_SETUP_VARS) \
247 )
248endef
249
250define Py3Build/Compile/Default
251 $(call Py3Build/InstallBuildDepends)
252 $(call Python3/Run, \
253 $(PKG_BUILD_DIR), \
254 -m build \
255 --no-isolation \
256 --outdir "$(PYTHON3_PKG_BUILD_DIR)"/openwrt-build \
257 --wheel \
258 $(foreach setting,$(PYTHON3_PKG_BUILD_CONFIG_SETTINGS),--config-setting=$(setting)) \
259 $(PYTHON3_PKG_BUILD_ARGS) \
260 "$(PYTHON3_PKG_BUILD_DIR)" \
261 , \
262 $(PYTHON3_PKG_BUILD_VARS) \
263 )
264endef
265
266define Py3Build/Install/Default
267 $(call Python3/Run, \
268 $(PKG_BUILD_DIR), \
269 -m installer \
270 --destdir "$(PKG_INSTALL_DIR)" \
271 --no-compile-bytecode \
272 --prefix /usr \
273 "$(PYTHON3_PKG_BUILD_DIR)"/openwrt-build/$(PYTHON3_PKG_WHEEL_NAME)-$(PYTHON3_PKG_WHEEL_VERSION)-*.whl \
274 , \
275 $(PYTHON3_PKG_INSTALL_VARS) \
276 )
277endef
278
279Py3Build/Compile=$(Py3Build/Compile/Default)
280Py3Build/Install=$(Py3Build/Install/Default)
281
282ifeq ($(strip $(PYTHON3_PKG_FORCE_DISTUTILS_SETUP)),1)
283 Py3Build/Compile=$(Py3Build/Compile/Distutils)
284 Py3Build/Install:=:
285endif
286
287ifeq ($(strip $(PYTHON3_PKG_BUILD)),1)
288 ifeq ($(PY3),stdlib)
289 Hooks/Configure/Post+=Py3Build/FindStdlibDepends
290 endif
291 Hooks/Configure/Post+=Py3Build/CheckHostPipVersionMatch
292 Build/Compile=$(Py3Build/Compile)
293 Build/Install=$(Py3Build/Install)
294endif