| | |
| | | # Copyright 2022 Marcel Telka |
| | | # |
| | | |
| | | ifeq ($(strip $(PYTHON_BOOTSTRAP)),yes) |
| | | # Until we implement support for testing bootstrapped projects we simply |
| | | # disable tests for them because required packages (e.g. tox and/or pytest) are |
| | | # very likely not available during bootstrap so testing would very likely fail |
| | | # anyway. |
| | | TEST_STYLE = none |
| | | endif |
| | | |
| | | include $(WS_MAKE_RULES)/setup.py.mk |
| | | |
| | | PYTHON_BOOTSTRAP ?= no |
| | | |
| | | ifeq ($(strip $(PYTHON_BOOTSTRAP)),yes) |
| | | # |
| | | # The following Python projects needs to be build before any other Python |
| | | # project because they are needed by the Userland build framework itself. To |
| | | # build them we need special set of rules that uses limited functionality of |
| | | # the build framework just to bootstrap them together with their build time and |
| | | # runtime dependencies. |
| | | # |
| | | # - pyproject_installer (the bootstrapper) |
| | | # - build (to build packages) |
| | | # - installer (to install packages before publish) |
| | | # - packaging (to detect runtime dependencies) |
| | | # |
| | | # There are basically two ways how to bootstrap these projects: |
| | | # |
| | | # 1) defer to default 'setup.py' build style for projects that still supports |
| | | # it. The 'setup.py' build style usually does not require anything outside |
| | | # core Python modules. Also, it is likely that the set of projects that needs |
| | | # to be bootstrapped (like setuptools) will support the 'setup.py' build style |
| | | # for very long time (maybe forever). Anyway, the main problem with the |
| | | # 'setup.py' build style is that its results are not PEP 376 compliant. |
| | | # |
| | | # 2) use something else, preferably as simple as possible, to do the build. |
| | | # Such tool needs to be PEP 376 and PEP 517 compliant and it also must be able |
| | | # to build itself without requiring any other non-core Python modules. We use |
| | | # pyproject_installer to do the job. |
| | | # |
| | | |
| | | ifeq ($(strip $(COMPONENT_NAME)),pyproject_installer) |
| | | # To bootstrap the bootstrapper we need to make sure it finds its own modules |
| | | ifeq ($(strip $(COMPONENT_NAME)),pyproject_installer) |
| | | PYTHON_ENV += PYTHONPATH=$(@D)/src |
| | | endif |
| | | |
| | | # Since pyproject_installer requires Python >= 3.8 we need to defer to default |
| | | # setup.py build style for Python 3.7, so we will use pyproject_installer for |
| | | # Python 3.9 only. Once we obsolete Python 3.7 we should set |
| | | # COMPONENT_BUILD_CMD, COMPONENT_BUILD_ARGS, COMPONENT_INSTALL_CMD, and |
| | | # COMPONENT_INSTALL_ARGS unconditionally below and replace $(PYTHON.3.9) by |
| | | # $(PYTHON). |
| | | $(BUILD_DIR)/%-3.9/.built: COMPONENT_BUILD_CMD = $(PYTHON.3.9) -m pyproject_installer build |
| | | $(BUILD_DIR)/%-3.9/.built: COMPONENT_BUILD_ARGS = |
| | | COMPONENT_BUILD_CMD = $(PYTHON) -m pyproject_installer build |
| | | COMPONENT_BUILD_ARGS = |
| | | |
| | | $(BUILD_DIR)/%-3.9/.installed: COMPONENT_INSTALL_CMD = $(PYTHON.3.9) -m pyproject_installer install |
| | | $(BUILD_DIR)/%-3.9/.installed: COMPONENT_INSTALL_ARGS = |
| | | $(BUILD_DIR)/%-3.9/.installed: COMPONENT_INSTALL_ARGS += --destdir $(PROTO_DIR) |
| | | COMPONENT_INSTALL_CMD = $(PYTHON) -m pyproject_installer install |
| | | COMPONENT_INSTALL_ARGS = |
| | | COMPONENT_INSTALL_ARGS += --destdir $(PROTO_DIR) |
| | | |
| | | # pyproject_installer does not bytecompile after the install. Since we need |
| | | # pyc files we need to force that. |
| | | # |
| | | # Since pyproject_installer requires Python >= 3.8 we need to defer to default |
| | | # setup.py build style for Python 3.7, and so we do not need to compile for |
| | | # Python 3.7. Once we obsolete Python 3.7 we should set |
| | | # COMPONENT_POST_INSTALL_ACTION unconditionally below. |
| | | $(BUILD_DIR)/%-3.9/.installed: COMPONENT_POST_INSTALL_ACTION += $(PYTHON) -m compileall $(PROTO_DIR)/$(PYTHON_LIB) ; |
| | | |
| | | # Special transforms needed only until we drop support for Python 3.7 |
| | | BOOTSTRAP_TRANSFORMS = $(WS_TOP)/transforms/python-bootstrap |
| | | PUBLISH_TRANSFORMS += $(BOOTSTRAP_TRANSFORMS) |
| | | |
| | | ifeq ($(wildcard $(SOURCE_DIR)/setup.py),) |
| | | # If the component does not support setup.py build style we cannot defer to it |
| | | # for bootstrapping Python 3.7. We will use 'build' and 'installer' instead. |
| | | # Strictly speaking this is not true bootstrap, but since we do not need to |
| | | # bootstrap Python 3.7 from scratch we can afford this fake bootstrap keeping |
| | | # in mind that Python 3.7 should be EOLed in June 2023. |
| | | |
| | | $(BUILD_DIR)/%-3.7/.built: COMPONENT_BUILD_CMD = $(PYTHON) -m build |
| | | $(BUILD_DIR)/%-3.7/.built: COMPONENT_BUILD_ARGS = |
| | | $(BUILD_DIR)/%-3.7/.built: COMPONENT_BUILD_ARGS += --wheel |
| | | $(BUILD_DIR)/%-3.7/.built: COMPONENT_BUILD_ARGS += --no-isolation |
| | | |
| | | $(BUILD_DIR)/%-3.7/.installed: COMPONENT_INSTALL_CMD = $(PYTHON) -m installer |
| | | $(BUILD_DIR)/%-3.7/.installed: COMPONENT_INSTALL_ARGS = |
| | | $(BUILD_DIR)/%-3.7/.installed: COMPONENT_INSTALL_ARGS += --destdir $(PROTO_DIR) |
| | | $(BUILD_DIR)/%-3.7/.installed: COMPONENT_INSTALL_ARGS += $(@D)/dist/*.whl |
| | | |
| | | USERLAND_REQUIRED_PACKAGES += library/python/build-37 |
| | | USERLAND_REQUIRED_PACKAGES += library/python/installer-37 |
| | | |
| | | # We do not need special transforms for fake bootstrap |
| | | BOOTSTRAP_TRANSFORMS = |
| | | |
| | | # Remove all files from dist-info directory except METADATA to get similar |
| | | # layout as with pyproject_installer |
| | | $(BUILD_DIR)/%-3.7/.installed: COMPONENT_POST_INSTALL_ACTION += \ |
| | | ( cd $(PROTO_DIR)/$(PYTHON_LIB)/$(COMPONENT_NAME)-$(COMPONENT_VERSION).dist-info ; \ |
| | | for f in * ; do \ |
| | | [[ "$$f" == "METADATA" ]] && continue ; \ |
| | | [[ -f "$$f" ]] || continue ; \ |
| | | $(RM) $$f ; \ |
| | | done ) ; |
| | | endif |
| | | COMPONENT_POST_INSTALL_ACTION += \ |
| | | $(PYTHON) -m compileall $(PROTO_DIR)/$(PYTHON_DIR)/site-packages $(PROTO_DIR)/$(PYTHON_LIB) ; |
| | | else |
| | | COMPONENT_BUILD_CMD = $(PYTHON) -m build |
| | | COMPONENT_BUILD_ARGS = |
| | |
| | | COMPONENT_INSTALL_ARGS += --destdir $(PROTO_DIR) |
| | | COMPONENT_INSTALL_ARGS += $(@D)/dist/*.whl |
| | | |
| | | PYTHON_USERLAND_REQUIRED_PACKAGES += library/python/build |
| | | PYTHON_USERLAND_REQUIRED_PACKAGES += library/python/installer |
| | | USERLAND_REQUIRED_PACKAGES.python += library/python/build |
| | | USERLAND_REQUIRED_PACKAGES.python += library/python/installer |
| | | endif |
| | | |
| | | # Move all modules from default site-packages directory to vendor-packages |
| | |
| | | REQUIRED_PACKAGES_RESOLVED += $(BUILD_DIR)/META.depend.res |
| | | $(BUILD_DIR)/META.depend.res: $(SOURCE_DIR)/.prep |
| | | $(MKDIR) $(BUILD_DIR) |
| | | # PYTHON_ENV is needed here to have the PYTHONPATH set properly when we |
| | | # bootstrap the pyproject_installer bootstrapper. |
| | | # |
| | | # To make the package names comparable we normalize them here by |
| | | # following the PyPA Core metadata specifications and PEP 503. |
| | | # |
| | | # Once we obsolete Python 3.7 we should change $(PYTHON.3.9) to $(PYTHON) here |
| | | $(PYTHON_ENV) $(PYTHON.3.9) -c ' \ |
| | | from pathlib import Path; \ |
| | | from pyproject_installer.build_cmd._build import parse_build_system_spec; \ |
| | | [print(x) for x in parse_build_system_spec(Path("'$(SOURCE_DIR)'"))["requires"]]' \ |
| | | | $(GSED) -e $$'s/^[ \t]*''\([a-zA-Z0-9]\([a-zA-Z0-9._-]*[a-zA-Z0-9]\)\{0,1\}\).*/\1/' \ |
| | | | tr [A-Z] [a-z] | $(GSED) -e 's/[._-]\{1,\}/-/g' \ |
| | | # PYTHON_ENV is needed four times here to have the PYTHONPATH set |
| | | # properly when we bootstrap the pyproject_installer bootstrapper. |
| | | $(PYTHON_ENV) $(PYTHON) -m pyproject_installer deps --depsconfig $(BUILD_DIR)/pyproject_deps.json add build_pep517 pep517 |
| | | $(PYTHON_ENV) $(PYTHON) -m pyproject_installer deps --depsconfig $(BUILD_DIR)/pyproject_deps.json add build_pep518 pep518 |
| | | cd $(SOURCE_DIR) ; $(PYTHON_ENV) $(PYTHON) -m pyproject_installer deps --depsconfig $(BUILD_DIR)/pyproject_deps.json sync |
| | | $(PYTHON_ENV) $(PYTHON) -m pyproject_installer deps --depsconfig $(BUILD_DIR)/pyproject_deps.json eval --depformat '$$nname' \ |
| | | | $(GSED) -e 's/.*/depend type=require fmri=pkg:\/library\/python\/&-$$(PYV)/' \ |
| | | > $@ |
| | | # PYTHON_ENV (see above) needs BITS |
| | | $(BUILD_DIR)/META.depend.res: BITS = $(PREFERRED_BITS) |
| | | |
| | | # We need pyproject_installer for two purposes: |
| | | # - to detect build dependencies for all Python projects, and |
| | |
| | | # The pyproject_installer is not needed (and cannot be needed) for its own |
| | | # build. |
| | | ifneq ($(strip $(COMPONENT_NAME)),pyproject_installer) |
| | | # Once we obsolete Python 3.7 this should be changed to |
| | | # PYTHON_USERLAND_REQUIRED_PACKAGES and '-39' suffix should be removed |
| | | USERLAND_REQUIRED_PACKAGES += library/python/pyproject-installer-39 |
| | | USERLAND_REQUIRED_PACKAGES.python += library/python/pyproject-installer |
| | | endif |