Add c++11 support (gcc10/gcc11) to p7zip
[oi-userland.git] / make-rules / setup.py.mk
blob3b30078dd8a81186d2f0f83ef4b1683f8abc127b
2 # CDDL HEADER START
4 # The contents of this file are subject to the terms of the
5 # Common Development and Distribution License (the "License").
6 # You may not use this file except in compliance with the License.
8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 # or http://www.opensolaris.org/os/licensing.
10 # See the License for the specific language governing permissions
11 # and limitations under the License.
13 # When distributing Covered Code, include this CDDL HEADER in each
14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 # If applicable, add the following below this CDDL HEADER, with the
16 # fields enclosed by brackets "[]" replaced with your own identifying
17 # information: Portions Copyright [yyyy] [name of copyright owner]
19 # CDDL HEADER END
21 # Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
25 # The Python build infrastructure in setup.py.mk and pyproject.mk files uses
26 # several Python projects to work properly. Since we cannot use these projects
27 # until they are actually built and installed we need to bootstrap.
29 # We do have several sequential bootstrap checkpoints during the process:
31 # (0) Nothing works yet.
33 # Just core Python runtime is available (with no additional projects).
34 # While here almost nothing works. We cannot do following tasks with
35 # regular Python projects:
36 # - detect their requirements,
37 # - build and publish them,
38 # - test them.
40 # (1) The bootstrapper is ready.
42 # The bootstrapper is special tool that requires just core Python with no
43 # dependency on other Python projects and it is able to build and publish
44 # itself and other Python projects.
46 # For projects using the 'setup.py' build style we do not need any
47 # special bootstrapper because such projects are built using their own
48 # 'setup.py' script. The only issue with the 'setup.py' build style
49 # projects is that their 'setup.py' script usually depends on some other
50 # projects (typically setuptools) to get successfully built.
52 # For 'pyproject'-style projects we use pyproject_installer as the
53 # bootstrapper.
55 # To achieve this checkpoint we just need to build pyproject_installer
56 # using pyproject_installer without detecting its requirements (they are
57 # none anyway) and without testing it (since no testing infrastructure is
58 # ready yet).
60 # (2) The python-requires script works.
62 # Once the python-requires script works we can start to detect runtime
63 # dependencie of other Python projects automatically.
65 # To achieve this checkpoint we need to build the packaging project
66 # (directly needed by the python-requires script) and all projects
67 # required by packaging. During this all projects' dependencies needs to
68 # be manually evaluated to make sure they are correct.
70 # (3) The build infrastructure is fully working.
72 # Once we are here we can build any Python project, but we cannot test it
73 # yet.
75 # For projects using the 'setup.py' build style we do not need any
76 # special build infrastructure. See checkpoint (1) above for detialed
77 # discussion about 'setup.py' build style projects.
79 # For 'pyproject'-style projects we need to build both 'build' and
80 # 'installer' projects and all projects they depends on.
82 # (4) The testing infrastructure is fully working.
84 # Once we are here we can finally use all features of the Python build
85 # framework. Including testing.
87 # To achieve this we need to build tox, tox-current-env, and pytest
88 # projects together with their dependencies.
90 # All projects needed to achieve checkpoints (1), (2), and (3) should set
91 # PYTHON_BOOTSTRAP to 'yes' in their Makefile to make sure the regular build
92 # infrastructure is not used for them and special set of build rules is applied
93 # instead.
95 # All projects needed to go from checkpoint (3) to checkpoint (4) should set
96 # PYTHON_TEST_BOOTSTRAP to 'yes' in their Makefile to let the build
97 # infrastructure know that testing for such projects might not work properly.
99 # The PYTHON_BOOTSTRAP set to 'yes' implies PYTHON_TEST_BOOTSTRAP set to 'yes'
100 # too.
102 ifeq ($(strip $(PYTHON_BOOTSTRAP)),yes)
103 PYTHON_TEST_BOOTSTRAP = yes
104 endif
107 # Lists of Python projects needed to achieve particular bootstrap checkpoint.
108 # Indentation shows project dependencies (e.g. packaging requires flit_core).
110 PYTHON_BOOTSTRAP_CHECKPOINT_1 += pyproject_installer
112 PYTHON_BOOTSTRAP_CHECKPOINT_2 += $(PYTHON_BOOTSTRAP_CHECKPOINT_1)
113 PYTHON_BOOTSTRAP_CHECKPOINT_2 += packaging
114 PYTHON_BOOTSTRAP_CHECKPOINT_2 += flit_core
116 # Particular python runtime is always required (at least to run setup.py)
117 PYTHON_REQUIRED_PACKAGES += runtime/python
119 define python-rule
120 $(BUILD_DIR)/%-$(1)/.built: PYTHON_VERSION=$(1)
121 $(BUILD_DIR)/%-$(1)/.installed: PYTHON_VERSION=$(1)
122 $(BUILD_DIR)/%-$(1)/.tested: PYTHON_VERSION=$(1)
123 $(BUILD_DIR)/%-$(1)/.tested-and-compared: PYTHON_VERSION=$(1)
124 endef
126 $(foreach pyver, $(PYTHON_VERSIONS), $(eval $(call python-rule,$(pyver))))
128 $(BUILD_DIR)/$(MACH32)-%/.built: BITS=32
129 $(BUILD_DIR)/$(MACH64)-%/.built: BITS=64
130 $(BUILD_DIR)/$(MACH32)-%/.installed: BITS=32
131 $(BUILD_DIR)/$(MACH64)-%/.installed: BITS=64
132 $(BUILD_DIR)/$(MACH32)-%/.tested: BITS=32
133 $(BUILD_DIR)/$(MACH64)-%/.tested: BITS=64
134 $(BUILD_DIR)/$(MACH32)-%/.tested-and-compared: BITS=32
135 $(BUILD_DIR)/$(MACH64)-%/.tested-and-compared: BITS=64
137 PYTHON_32_VERSIONS = $(filter-out $(PYTHON_64_ONLY_VERSIONS), $(PYTHON_VERSIONS))
139 BUILD_32 = $(PYTHON_32_VERSIONS:%=$(BUILD_DIR)/$(MACH32)-%/.built)
140 BUILD_64 = $(PYTHON_VERSIONS:%=$(BUILD_DIR)/$(MACH64)-%/.built)
141 BUILD_NO_ARCH = $(PYTHON_VERSIONS:%=$(BUILD_DIR)/$(MACH)-%/.built)
143 ifeq ($(filter-out $(PYTHON_64_ONLY_VERSIONS), $(PYTHON_VERSION)),)
144 BUILD_32_and_64 = $(BUILD_64)
145 endif
147 INSTALL_32 = $(PYTHON_32_VERSIONS:%=$(BUILD_DIR)/$(MACH32)-%/.installed)
148 INSTALL_64 = $(PYTHON_VERSIONS:%=$(BUILD_DIR)/$(MACH64)-%/.installed)
149 INSTALL_NO_ARCH = $(PYTHON_VERSIONS:%=$(BUILD_DIR)/$(MACH)-%/.installed)
151 PYTHON_ENV = CC="$(CC)"
152 PYTHON_ENV += CFLAGS="$(CFLAGS)"
153 PYTHON_ENV += PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)"
155 COMPONENT_BUILD_ENV += $(PYTHON_ENV)
156 # We need to set GIT_DIR to workaround the nasty poetry bug:
157 # https://github.com/python-poetry/poetry/issues/5547. Technically, we should
158 # set this on per-project basis, but we would need to check every newly
159 # integrated project to see if it is build by poetry backend or not. We would
160 # also need to do similar check on every version bump, because any project
161 # could switch to poetry anytime. Since this would be a lot of work we simply
162 # opted to set GIT_DIR for every python project.
163 COMPONENT_BUILD_ENV += GIT_DIR=$(BUILD_DIR)
164 COMPONENT_INSTALL_ENV += $(PYTHON_ENV)
165 COMPONENT_TEST_ENV += $(PYTHON_ENV)
167 # Make sure the default Python version is installed last and so is the
168 # canonical version. This is needed for components that keep PYTHON_VERSIONS
169 # set to more than single value, but deliver unversioned binaries in usr/bin or
170 # other overlapping files.
171 define python-order-rule
172 $(BUILD_DIR)/%-$(PYTHON_VERSION)/.installed: $(BUILD_DIR)/%-$(1)/.installed
173 endef
174 $(foreach pyver,$(filter-out $(PYTHON_VERSION),$(PYTHON_VERSIONS)),$(eval $(call python-order-rule,$(pyver))))
176 # We need to copy the source dir to avoid its modification by install target
177 # where egg-info is re-generated
178 CLONEY_ARGS = CLONEY_MODE="copy"
180 COMPONENT_BUILD_CMD = $(PYTHON) setup.py --no-user-cfg build
182 # build the configured source
183 $(BUILD_DIR)/%/.built: $(SOURCE_DIR)/.prep
184 $(RM) -r $(@D) ; $(MKDIR) $(@D)
185 $(ENV) $(CLONEY_ARGS) $(CLONEY) $(SOURCE_DIR) $(@D)
186 $(COMPONENT_PRE_BUILD_ACTION)
187 (cd $(@D)$(COMPONENT_SUBDIR:%=/%) ; $(ENV) $(COMPONENT_BUILD_ENV) \
188 $(COMPONENT_BUILD_CMD) $(COMPONENT_BUILD_ARGS))
189 $(COMPONENT_POST_BUILD_ACTION)
190 $(TOUCH) $@
193 COMPONENT_INSTALL_CMD = $(PYTHON) setup.py --no-user-cfg install
195 COMPONENT_INSTALL_ARGS += --root $(PROTO_DIR)
196 COMPONENT_INSTALL_ARGS += --install-lib=$(PYTHON_LIB)
197 COMPONENT_INSTALL_ARGS += --install-data=$(PYTHON_DATA)
198 COMPONENT_INSTALL_ARGS += --skip-build
199 COMPONENT_INSTALL_ARGS += --force
201 # install the built source into a prototype area
202 $(BUILD_DIR)/%/.installed: $(BUILD_DIR)/%/.built
203 $(COMPONENT_PRE_INSTALL_ACTION)
204 (cd $(@D)$(COMPONENT_SUBDIR:%=/%) ; $(ENV) $(COMPONENT_INSTALL_ENV) \
205 $(COMPONENT_INSTALL_CMD) $(COMPONENT_INSTALL_ARGS))
206 $(COMPONENT_POST_INSTALL_ACTION)
207 $(TOUCH) $@
209 ifeq ($(strip $(SINGLE_PYTHON_VERSION)),no)
210 # Rename binaries in /usr/bin to contain version number
211 COMPONENT_POST_INSTALL_ACTION += \
212 for f in $(PROTOUSRBINDIR)/* ; do \
213 [[ -f $$f ]] || continue ; \
214 for v in $(PYTHON_VERSIONS) ; do \
215 [[ "$$f" == "$${f%%$$v}" ]] || continue 2 ; \
216 done ; \
217 $(MV) $$f $$f-$(PYTHON_VERSION) ; \
218 done ;
219 endif
221 # Remove any previous dependency files
222 COMPONENT_POST_INSTALL_ACTION += $(RM) $(@D)/.depend-runtime $(@D)/.depend-test ;
224 # Define Python version specific filenames for tests.
225 ifeq ($(strip $(USE_COMMON_TEST_MASTER)),no)
226 COMPONENT_TEST_MASTER = $(COMPONENT_TEST_RESULTS_DIR)/results-$(PYTHON_VERSION).master
227 endif
228 COMPONENT_TEST_BUILD_DIR = $(BUILD_DIR)/test-$(PYTHON_VERSION)
229 COMPONENT_TEST_OUTPUT = $(COMPONENT_TEST_BUILD_DIR)/test-$(PYTHON_VERSION)-results
230 COMPONENT_TEST_DIFFS = $(COMPONENT_TEST_BUILD_DIR)/test-$(PYTHON_VERSION)-diffs
231 COMPONENT_TEST_SNAPSHOT = $(COMPONENT_TEST_BUILD_DIR)/results-$(PYTHON_VERSION).snapshot
232 COMPONENT_TEST_TRANSFORM_CMD = $(COMPONENT_TEST_BUILD_DIR)/transform-$(PYTHON_VERSION)-results
234 # Generic transforms for Python test results.
235 # See below for test style specific transforms.
236 COMPONENT_TEST_TRANSFORMS += "-e 's|$(PYTHON_DIR)|\$$(PYTHON_DIR)|g'"
238 # Make sure the test environment is prepared before we start tests
239 COMPONENT_TEST_DEP += component-test-environment-prep
240 # Testing depends on install target because we want to test installed modules
241 COMPONENT_TEST_DEP += $(BUILD_DIR)/%/.installed
242 # Point Python to the proto area so it is able to find installed modules there
243 COMPONENT_TEST_ENV += PYTHONPATH=$(PROTO_DIR)/$(PYTHON_LIB)
245 # determine the type of tests we want to run.
246 ifeq ($(strip $(wildcard $(COMPONENT_TEST_RESULTS_DIR)/results-*.master)),)
247 TEST_32 = $(PYTHON_32_VERSIONS:%=$(BUILD_DIR)/$(MACH32)-%/.tested)
248 TEST_64 = $(PYTHON_VERSIONS:%=$(BUILD_DIR)/$(MACH64)-%/.tested)
249 TEST_NO_ARCH = $(PYTHON_VERSIONS:%=$(BUILD_DIR)/$(MACH)-%/.tested)
250 else
251 TEST_32 = $(PYTHON_32_VERSIONS:%=$(BUILD_DIR)/$(MACH32)-%/.tested-and-compared)
252 TEST_64 = $(PYTHON_VERSIONS:%=$(BUILD_DIR)/$(MACH64)-%/.tested-and-compared)
253 TEST_NO_ARCH = $(PYTHON_VERSIONS:%=$(BUILD_DIR)/$(MACH)-%/.tested-and-compared)
254 endif
257 # Testing in the Python world is complex. Python projects usually do not
258 # support Makefile with common 'check' or 'test' target to get built bits
259 # tested.
261 # De facto standard way to test Python projects these days is tox which is
262 # designed and used primarily for release testing; to make sure the released
263 # python project runs on all supported Python versions, platforms, etc. tox
264 # does so using virtualenv and creates isolated test environments where the
265 # tested package together with all its dependencies is automatically installed
266 # (using pip) and tested. This is great for Python projects developers but it
267 # is hardly usable for operating system distributions like OpenIndiana.
269 # We do not need such release testing. Instead we need something closer to
270 # integration testing: we need to test the built component in our real
271 # environment without automatic installation of any dependencies using pip. In
272 # addition, we need to run tests only for Python versions we actually support
273 # and the component is built for.
275 # To achieve that we do few things. First, to avoid isolated environments
276 # (virtualenv) we run tox with the tox-current-env plugin. Second, to test
277 # only Python versions we are interested in we use -e option for tox to select
278 # single Python version only. Since we run separate test target per Python
279 # version this will make sure we test all needed Python versions.
281 # The tox tool itself uses some other tools under the hood to run tests, for
282 # example pytest. Some projects could even support pytest testing directly
283 # without support for tox. For such projects we offer separate "pytest"-style
284 # testing.
286 # For projects that do not support testing using neither tox nor pytest we
287 # offer either unittest or (deprecated) "setup.py test" testing too.
289 # The TEST_STYLE variable is used to select (or force) particular test style
290 # for Python projects. Valid values are:
292 # tox - "tox"-style testing
293 # pytest - "pytest"-style testing
294 # unittest - "unittest"-style testing
295 # setup.py - "setup.py test"-style testing
296 # none - no testing is supported (or desired) at all
299 TEST_STYLE ?= tox
300 ifeq ($(strip $(TEST_STYLE)),tox)
301 COMPONENT_TEST_ENV += PATH=$(PATH) # https://github.com/tox-dev/tox/issues/2538
302 COMPONENT_TEST_ENV += PYTEST_ADDOPTS="$(PYTEST_ADDOPTS)"
303 COMPONENT_TEST_ENV += NOSE_VERBOSE=2
304 COMPONENT_TEST_CMD = $(TOX)
305 COMPONENT_TEST_ARGS = --current-env --no-provision
306 COMPONENT_TEST_ARGS += --recreate
307 COMPONENT_TEST_ARGS += $(TOX_TESTENV)
308 COMPONENT_TEST_TARGETS =
310 TOX_TESTENV = -e py$(shell echo $(PYTHON_VERSION) | tr -d .)
312 # Make sure following tools are called indirectly to properly support tox-current-env
313 TOX_CALL_INDIRECTLY += py.test
314 TOX_CALL_INDIRECTLY += pytest
315 TOX_CALL_INDIRECTLY += coverage
316 TOX_CALL_INDIRECTLY += zope-testrunner
317 TOX_CALL_INDIRECTLY.zope-testrunner = zope.testrunner
318 TOX_CALL_INDIRECTLY += sphinx-build
319 TOX_CALL_INDIRECTLY.sphinx-build = sphinx.cmd.build
320 TOX_CALL_INDIRECTLY += nosetests
321 TOX_CALL_INDIRECTLY.nosetests = nose
322 $(foreach indirectly, $(TOX_CALL_INDIRECTLY), $(eval TOX_CALL_INDIRECTLY.$(indirectly) ?= $(indirectly)))
323 COMPONENT_PRE_TEST_ACTION += COMPONENT_TEST_DIR=$(COMPONENT_TEST_DIR) ;
324 COMPONENT_PRE_TEST_ACTION += \
325 $(foreach indirectly, $(TOX_CALL_INDIRECTLY), \
326 [ -f $$COMPONENT_TEST_DIR/tox.ini ] && \
327 $(GSED) -i -e '/^commands *=/,/^$$/{ \
328 s/^\(\(commands *=\)\{0,1\}[ \t]*\)'$(indirectly)'\([ \t]\{1,\}.*\)\{0,1\}$$/\1python -m '$(TOX_CALL_INDIRECTLY.$(indirectly))'\3/ \
329 }' $$COMPONENT_TEST_DIR/tox.ini ; \
331 COMPONENT_PRE_TEST_ACTION += true ;
333 # Normalize tox test results.
334 COMPONENT_TEST_TRANSFORMS += "-e 's/py$(shell echo $(PYTHON_VERSION) | tr -d .)/py\$$(PYV)/g'" # normalize PYV
335 COMPONENT_TEST_TRANSFORMS += "-e '/^py\$$(PYV) installed:/d'" # depends on set of installed packages
336 COMPONENT_TEST_TRANSFORMS += "-e '/PYTHONHASHSEED/d'" # this is random
338 # Normalize zope.testrunner test results
339 COMPONENT_TEST_TRANSFORMS += \
340 "-e 's/ in \([0-9]\{1,\} minutes \)\{0,1\}[0-9]\{1,\}\.[0-9]\{3\} seconds//'" # timing
342 # Remove timing for tox 4 test results
343 COMPONENT_TEST_TRANSFORMS += "-e 's/^\( py\$$(PYV): OK\) (.* seconds)$$/\1/'"
344 COMPONENT_TEST_TRANSFORMS += "-e 's/^\( congratulations :)\) (.* seconds)$$/\1/'"
346 # sort list of Sphinx doctest results
347 COMPONENT_TEST_TRANSFORMS += \
348 "| ( \
349 $(GSED) -u -e '/^running tests\.\.\.$$/q' ; \
350 $(GSED) -u -e '/^Doctest summary/Q' \
351 | $(NAWK) '/^$$/{\$$0=\"\\\\n\"}1' ORS='|' \
352 | $(GNU_GREP) -v '^|$$' \
353 | $(SORT) \
354 | tr -d '\\\\n' | tr '|' '\\\\n' \
355 | $(NAWK) '{print}END{if(NR>0)printf(\"\\\\nDoctest summary\\\\n\")}' ; \
356 $(CAT) \
357 ) | $(COMPONENT_TEST_TRANSFORMER)"
359 # tox package together with the tox-current-env plugin is needed
360 USERLAND_TEST_REQUIRED_PACKAGES += library/python/tox
361 USERLAND_TEST_REQUIRED_PACKAGES += library/python/tox-current-env
363 # Generate raw lists of test dependencies per Python version
364 # Please note we set PATH below four times for $(COMPONENT_TEST_CMD) (aka tox)
365 # to workaround https://github.com/tox-dev/tox/issues/2538
366 COMPONENT_POST_INSTALL_ACTION += \
367 if [ -x "$(COMPONENT_TEST_CMD)" ] ; then \
368 cd $(@D)$(COMPONENT_SUBDIR:%=/%) ; \
369 echo "Testing dependencies:" ; \
370 PATH=$(PATH) $(COMPONENT_TEST_CMD) -qq --no-provision --print-deps-to=- $(TOX_TESTENV) || exit 1 ; \
371 echo "Testing extras:" ; \
372 PATH=$(PATH) $(COMPONENT_TEST_CMD) -qq --no-provision --print-extras-to=- $(TOX_TESTENV) || exit 1 ; \
373 ( PATH=$(PATH) $(COMPONENT_TEST_CMD) -qq --no-provision --print-deps-to=- $(TOX_TESTENV) \
374 | $(WS_TOOLS)/python-resolve-deps \
375 PYTHONPATH=$(PROTO_DIR)/$(PYTHON_DIR)/site-packages:$(PROTO_DIR)/$(PYTHON_LIB) \
376 $(PYTHON) $(WS_TOOLS)/python-requires $(COMPONENT_NAME) \
377 | $(PYTHON) $(WS_TOOLS)/python-requires - ; \
378 for e in $$(PATH=$(PATH) $(COMPONENT_TEST_CMD) -qq --no-provision --print-extras-to=- $(TOX_TESTENV)) ; do \
379 PYTHONPATH=$(PROTO_DIR)/$(PYTHON_DIR)/site-packages:$(PROTO_DIR)/$(PYTHON_LIB) \
380 $(PYTHON) $(WS_TOOLS)/python-requires $(COMPONENT_NAME) $$e ; \
381 done ) | $(GSED) -e '/^tox\(-current-env\)\?$$/d' >> $(@D)/.depend-test ; \
382 fi ;
383 else ifeq ($(strip $(TEST_STYLE)),pytest)
384 COMPONENT_TEST_CMD = $(PYTHON) -m pytest
385 COMPONENT_TEST_ARGS = $(PYTEST_ADDOPTS)
386 COMPONENT_TEST_TARGETS =
388 # Force pytest to not use colored output so the results normalization is unaffected
389 PYTEST_ADDOPTS += --color=no
391 USERLAND_TEST_REQUIRED_PACKAGES += library/python/pytest
392 else ifeq ($(strip $(TEST_STYLE)),unittest)
393 COMPONENT_TEST_CMD = $(PYTHON) -m unittest
394 COMPONENT_TEST_ARGS =
395 COMPONENT_TEST_ARGS += --verbose
396 COMPONENT_TEST_TARGETS =
397 else ifeq ($(strip $(TEST_STYLE)),setup.py)
398 # Old and deprecated "setup.py test"-style testing
399 COMPONENT_TEST_CMD = $(PYTHON) setup.py
400 COMPONENT_TEST_ARGS = --no-user-cfg
401 COMPONENT_TEST_TARGETS = test
402 else ifeq ($(strip $(TEST_STYLE)),none)
403 TEST_TARGET = $(NO_TESTS)
404 endif
406 # Run pytest verbose to get separate line per test in results output
407 PYTEST_ADDOPTS += --verbose
409 # Normalize pytest test results. The pytest framework could be used either
410 # directly or via tox or setup.py so add these transforms for all test styles
411 # unconditionally.
412 COMPONENT_TEST_TRANSFORMS += \
413 "-e 's/^\(platform sunos5 -- Python \)$(shell echo $(PYTHON_VERSION) | $(GSED) -e 's/\./\\./g')\.[0-9]\{1,\}.*\( -- .*\)/\1\$$(PYTHON_VERSION).X\2/'"
414 COMPONENT_TEST_TRANSFORMS += "-e '/^Using --randomly-seed=[0-9]\{1,\}$$/d'" # this is random
415 COMPONENT_TEST_TRANSFORMS += "-e '/^benchmark: /d'" # line with version details
416 COMPONENT_TEST_TRANSFORMS += "-e '/^plugins: /d'" # order of listed plugins could vary
417 COMPONENT_TEST_TRANSFORMS += "-e '/^-\{1,\} coverage: /,/^$$/d'" # remove coverage report
418 # sort list of pytest unit tests and drop percentage
419 COMPONENT_TEST_TRANSFORMS += \
420 "| ( \
421 $(GSED) -u -e '/^=\{1,\} test session starts /q' ; \
422 $(GSED) -u -e '/^$$/q' ; \
423 $(GSED) -u -e 's/ *\[...%\]$$//' -e '/^$$/Q' | $(SORT) | $(NAWK) '{print}END{if(NR>0)printf(\"\\\\n\")}' ; \
424 $(CAT) \
425 ) | $(COMPONENT_TEST_TRANSFORMER)"
426 COMPONENT_TEST_TRANSFORMS += \
427 "-e 's/^=\{1,\} \(.*\) in [0-9]\{1,\}\.[0-9]\{1,\}s \(([^)]*) \)\?=\{1,\}$$/======== \1 ========/'" # remove timing
428 # Remove slowest durations report for projects that run pytest with --durations option
429 COMPONENT_TEST_TRANSFORMS += "-e '/^=\{1,\} slowest [0-9]\{1,\} durations =\{1,\}$$/,/^=/{/^=/!d}'"
430 # Remove short test summary info for projects that run pytest with -r option
431 COMPONENT_TEST_TRANSFORMS += "-e '/^=\{1,\} short test summary info =\{1,\}$$/,/^=/{/^=/!d}'"
433 # Normalize setup.py test results. The setup.py testing could be used either
434 # directly or via tox so add these transforms for all test styles
435 # unconditionally.
436 COMPONENT_TEST_TRANSFORMS += "-e '/SetuptoolsDeprecationWarning:/,+1d'" # depends on Python version and is useless
437 COMPONENT_TEST_TRANSFORMS += "-e 's/^\(Ran [0-9]\{1,\} tests\{0,1\}\) in .*$$/\1/'" # delete timing from test results
439 COMPONENT_TEST_DIR = $(@D)$(COMPONENT_SUBDIR:%=/%)
441 # test the built source
442 $(BUILD_DIR)/%/.tested-and-compared: $(COMPONENT_TEST_DEP)
443 $(RM) -rf $(COMPONENT_TEST_BUILD_DIR)
444 $(MKDIR) $(COMPONENT_TEST_BUILD_DIR)
445 $(COMPONENT_PRE_TEST_ACTION)
446 -(cd $(COMPONENT_TEST_DIR) ; \
447 $(COMPONENT_TEST_ENV_CMD) $(COMPONENT_TEST_ENV) \
448 $(COMPONENT_TEST_CMD) \
449 $(COMPONENT_TEST_ARGS) $(COMPONENT_TEST_TARGETS)) \
450 &> $(COMPONENT_TEST_OUTPUT)
451 $(COMPONENT_POST_TEST_ACTION)
452 $(COMPONENT_TEST_CREATE_TRANSFORMS)
453 $(COMPONENT_TEST_PERFORM_TRANSFORM)
454 $(COMPONENT_TEST_COMPARE)
455 $(COMPONENT_TEST_CLEANUP)
456 $(TOUCH) $@
458 $(BUILD_DIR)/%/.tested: SHELLOPTS=pipefail
459 $(BUILD_DIR)/%/.tested: $(COMPONENT_TEST_DEP)
460 $(RM) -rf $(COMPONENT_TEST_BUILD_DIR)
461 $(MKDIR) $(COMPONENT_TEST_BUILD_DIR)
462 $(COMPONENT_PRE_TEST_ACTION)
463 (cd $(COMPONENT_TEST_DIR) ; \
464 $(COMPONENT_TEST_ENV_CMD) $(COMPONENT_TEST_ENV) \
465 $(COMPONENT_TEST_CMD) \
466 $(COMPONENT_TEST_ARGS) $(COMPONENT_TEST_TARGETS)) \
467 |& $(TEE) $(COMPONENT_TEST_OUTPUT)
468 $(COMPONENT_POST_TEST_ACTION)
469 $(COMPONENT_TEST_CREATE_TRANSFORMS)
470 $(COMPONENT_TEST_PERFORM_TRANSFORM)
471 $(COMPONENT_TEST_CLEANUP)
472 $(TOUCH) $@
475 ifeq ($(strip $(SINGLE_PYTHON_VERSION)),no)
476 # We need to add -$(PYV) to package fmri
477 GENERATE_EXTRA_CMD += | \
478 $(GSED) -e 's/^\(set name=pkg.fmri [^@]*\)\(.*\)$$/\1-$$(PYV)\2/'
479 endif
481 # Add runtime dependencies from project metadata to generated manifest
482 GENERATE_EXTRA_DEPS += $(BUILD_DIR)/META.depend-runtime.res
483 GENERATE_EXTRA_CMD += | \
484 $(CAT) - <( \
485 echo "" ; \
486 echo "\# python modules are unusable without python runtime binary" ; \
487 echo "depend type=require fmri=__TBD pkg.debug.depend.file=python\$$(PYVER) \\" ; \
488 echo " pkg.debug.depend.path=usr/bin" ; \
489 echo "" ; \
490 echo "\# Automatically generated dependencies based on distribution metadata" ; \
491 $(CAT) $(BUILD_DIR)/META.depend-runtime.res \
494 # Add runtime dependencies from project metadata to REQUIRED_PACKAGES
495 REQUIRED_PACKAGES_RESOLVED += $(BUILD_DIR)/META.depend-runtime.res
498 # Generate raw lists of runtime dependencies per Python version
499 COMPONENT_POST_INSTALL_ACTION += \
500 PYTHONPATH=$(PROTO_DIR)/$(PYTHON_DIR)/site-packages:$(PROTO_DIR)/$(PYTHON_LIB) \
501 $(PYTHON) $(WS_TOOLS)/python-requires $(COMPONENT_NAME) >> $(@D)/.depend-runtime ;
503 # Convert raw per version lists of runtime dependencies to single resolved
504 # runtime dependency list. The dependency on META.depend-test.required here is
505 # purely to get the file created as a side effect of this target.
506 $(BUILD_DIR)/META.depend-runtime.res: $(INSTALL_$(MK_BITS)) $(BUILD_DIR)/META.depend-test.required
507 $(CAT) $(INSTALL_$(MK_BITS):%.installed=%.depend-runtime) | $(SORT) -u \
508 | $(GSED) -e 's/.*/depend type=require fmri=pkg:\/library\/python\/&-$$(PYV)/' > $@
510 # Generate raw lists of test dependencies per Python version
511 COMPONENT_POST_INSTALL_ACTION += \
512 cd $(@D)$(COMPONENT_SUBDIR:%=/%) ; \
513 for f in $(TEST_REQUIREMENTS) ; do \
514 $(CAT) $$f ; \
515 done | $(WS_TOOLS)/python-resolve-deps \
516 PYTHONPATH=$(PROTO_DIR)/$(PYTHON_DIR)/site-packages:$(PROTO_DIR)/$(PYTHON_LIB) \
517 $(PYTHON) $(WS_TOOLS)/python-requires $(COMPONENT_NAME) \
518 | $(PYTHON) $(WS_TOOLS)/python-requires - >> $(@D)/.depend-test ;
520 # Convert raw per version lists of test dependencies to single list of
521 # TEST_REQUIRED_PACKAGES entries
522 $(BUILD_DIR)/META.depend-test.required: $(INSTALL_$(MK_BITS))
523 $(CAT) $(INSTALL_$(MK_BITS):%.installed=%.depend-test) | $(SORT) -u \
524 | $(GSED) -e 's/.*/TEST_REQUIRED_PACKAGES.python += library\/python\/&/' > $@
526 # Add META.depend-test.required to the generated list of REQUIRED_PACKAGES
527 REQUIRED_PACKAGES_TRANSFORM += -e '$$r $(BUILD_DIR)/META.depend-test.required'
529 # The python-requires script requires importlib_metadata for Python 3.7 to
530 # provide useful output. Since we do fake bootstrap for Python 3.7 we require
531 # the package here unconditionally.
532 USERLAND_REQUIRED_PACKAGES += library/python/importlib-metadata-37
534 # The python-requires script requires packaging to provide useful output but
535 # packaging might be unavailable during bootstrap until we reach bootstrap
536 # checkpoint 2. So require it conditionally.
537 ifeq ($(filter $(strip $(COMPONENT_NAME)),$(PYTHON_BOOTSTRAP_CHECKPOINT_2)),)
538 PYTHON_USERLAND_REQUIRED_PACKAGES += library/python/packaging
539 endif
542 clean::
543 $(RM) -r $(SOURCE_DIR) $(BUILD_DIR)
545 # Make it easy to construct a URL for a pypi source download.
546 pypi_url_multi = pypi:///$(COMPONENT_NAME_$(1))==$(COMPONENT_VERSION_$(1))
547 pypi_url_single = pypi:///$(COMPONENT_NAME)==$(COMPONENT_VERSION)
548 pypi_url = $(if $(COMPONENT_NAME_$(1)),$(pypi_url_multi),$(pypi_url_single))