eclass/distutils-r1: Sync with Gentoo

It's from Gentoo commit 67f008f6acc086e0a58dfebd1b019bcdad73620a.
This commit is contained in:
Flatcar Buildbot 2025-04-07 07:08:03 +00:00 committed by Krzesimir Nowak
parent 546fb74f12
commit 4db6012f49

View File

@ -1,4 +1,4 @@
# Copyright 1999-2024 Gentoo Authors # Copyright 1999-2025 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2 # Distributed under the terms of the GNU General Public License v2
# @ECLASS: distutils-r1.eclass # @ECLASS: distutils-r1.eclass
@ -137,6 +137,8 @@
# - standalone - standalone build systems without external deps # - standalone - standalone build systems without external deps
# (used for bootstrapping). # (used for bootstrapping).
# #
# - uv-build - uv-build backend (using dev-python/uv)
#
# The variable needs to be set before the inherit line. The eclass # The variable needs to be set before the inherit line. The eclass
# adds appropriate build-time dependencies and verifies the value. # adds appropriate build-time dependencies and verifies the value.
# #
@ -151,6 +153,20 @@
# files are found in ${BUILD_DIR}/install after python_install(), they # files are found in ${BUILD_DIR}/install after python_install(), they
# will be merged into ${D}. # will be merged into ${D}.
# @ECLASS_VARIABLE: DISTUTILS_UPSTREAM_PEP517
# @DESCRIPTION:
# Specifies the PEP517 build backend used upstream. It is used
# by the eclass to verify the correctness of DISTUTILS_USE_PEP517,
# and matches DISTUTILS_USE_PEP517 by default. However, it can be
# overriden to workaround the eclass check, when it is desirable
# to build the wheel using other backend than the one used upstream.
#
# Please note that even in packages using PEP621 metadata, there can
# be subtle differences between the behavior of different PEP517 build
# backends, for example regarding finding package files. When using
# this option, please make sure that the package is installed correctly.
: "${DISTUTILS_UPSTREAM_PEP517:=${DISTUTILS_USE_PEP517}}"
# @ECLASS_VARIABLE: DISTUTILS_USE_SETUPTOOLS # @ECLASS_VARIABLE: DISTUTILS_USE_SETUPTOOLS
# @DEFAULT_UNSET # @DEFAULT_UNSET
# @PRE_INHERIT # @PRE_INHERIT
@ -246,22 +262,23 @@ _distutils_set_globals() {
fi fi
bdep=' bdep='
>=dev-python/gpep517-15[${PYTHON_USEDEP}] >=dev-python/gpep517-16[${PYTHON_USEDEP}]
' '
case ${DISTUTILS_USE_PEP517} in case ${DISTUTILS_USE_PEP517} in
flit) flit)
bdep+=' bdep+='
>=dev-python/flit-core-3.9.0[${PYTHON_USEDEP}] >=dev-python/flit-core-3.11.0[${PYTHON_USEDEP}]
' '
;; ;;
flit_scm) flit_scm)
bdep+=' bdep+='
>=dev-python/flit-core-3.11.0[${PYTHON_USEDEP}]
>=dev-python/flit-scm-1.7.0[${PYTHON_USEDEP}] >=dev-python/flit-scm-1.7.0[${PYTHON_USEDEP}]
' '
;; ;;
hatchling) hatchling)
bdep+=' bdep+='
>=dev-python/hatchling-1.21.1[${PYTHON_USEDEP}] >=dev-python/hatchling-1.27.0[${PYTHON_USEDEP}]
' '
;; ;;
jupyter) jupyter)
@ -271,7 +288,7 @@ _distutils_set_globals() {
;; ;;
maturin) maturin)
bdep+=' bdep+='
>=dev-util/maturin-1.7.4[${PYTHON_USEDEP}] >=dev-util/maturin-1.8.2[${PYTHON_USEDEP}]
' '
;; ;;
no) no)
@ -280,41 +297,46 @@ _distutils_set_globals() {
;; ;;
meson-python) meson-python)
bdep+=' bdep+='
>=dev-python/meson-python-0.15.0[${PYTHON_USEDEP}] >=dev-python/meson-python-0.17.1[${PYTHON_USEDEP}]
' '
;; ;;
pbr) pbr)
bdep+=' bdep+='
>=dev-python/pbr-6.0.0[${PYTHON_USEDEP}] >=dev-python/pbr-6.1.1[${PYTHON_USEDEP}]
' '
;; ;;
pdm-backend) pdm-backend)
bdep+=' bdep+='
>=dev-python/pdm-backend-2.1.8[${PYTHON_USEDEP}] >=dev-python/pdm-backend-2.4.3[${PYTHON_USEDEP}]
' '
;; ;;
poetry) poetry)
bdep+=' bdep+='
>=dev-python/poetry-core-1.9.0[${PYTHON_USEDEP}] >=dev-python/poetry-core-2.1.1[${PYTHON_USEDEP}]
' '
;; ;;
scikit-build-core) scikit-build-core)
bdep+=' bdep+='
>=dev-python/scikit-build-core-0.9.4[${PYTHON_USEDEP}] >=dev-python/scikit-build-core-0.10.7[${PYTHON_USEDEP}]
' '
;; ;;
setuptools) setuptools)
bdep+=' bdep+='
>=dev-python/setuptools-69.0.3[${PYTHON_USEDEP}] >=dev-python/setuptools-75.8.2[${PYTHON_USEDEP}]
' '
;; ;;
sip) sip)
bdep+=' bdep+='
>=dev-python/sip-6.8.3[${PYTHON_USEDEP}] >=dev-python/sip-6.10.0[${PYTHON_USEDEP}]
' '
;; ;;
standalone) standalone)
;; ;;
uv-build)
bdep+='
dev-python/uv-build[${PYTHON_USEDEP}]
'
;;
*) *)
die "Unknown DISTUTILS_USE_PEP517=${DISTUTILS_USE_PEP517}" die "Unknown DISTUTILS_USE_PEP517=${DISTUTILS_USE_PEP517}"
;; ;;
@ -325,7 +347,7 @@ _distutils_set_globals() {
eqawarn "is enabled." eqawarn "is enabled."
fi fi
else else
local setuptools_dep='>=dev-python/setuptools-69.0.3[${PYTHON_USEDEP}]' local setuptools_dep='>=dev-python/setuptools-75.8.2[${PYTHON_USEDEP}]'
case ${DISTUTILS_USE_SETUPTOOLS:-bdepend} in case ${DISTUTILS_USE_SETUPTOOLS:-bdepend} in
no|manual) no|manual)
@ -501,7 +523,7 @@ distutils_enable_sphinx() {
_DISTUTILS_SPHINX_PLUGINS=( "${@}" ) _DISTUTILS_SPHINX_PLUGINS=( "${@}" )
local deps autodoc=1 d local deps autodoc=1 d
deps=">=dev-python/sphinx-7.2.6[\${PYTHON_USEDEP}]" deps=">=dev-python/sphinx-8.1.3[\${PYTHON_USEDEP}]"
for d; do for d; do
if [[ ${d} == --no-autodoc ]]; then if [[ ${d} == --no-autodoc ]]; then
autodoc= autodoc=
@ -525,7 +547,7 @@ distutils_enable_sphinx() {
use doc || return 0 use doc || return 0
local p local p
for p in ">=dev-python/sphinx-7.2.6" \ for p in ">=dev-python/sphinx-8.1.3" \
"${_DISTUTILS_SPHINX_PLUGINS[@]}" "${_DISTUTILS_SPHINX_PLUGINS[@]}"
do do
python_has_version "${p}[${PYTHON_USEDEP}]" || python_has_version "${p}[${PYTHON_USEDEP}]" ||
@ -533,7 +555,7 @@ distutils_enable_sphinx() {
done done
} }
else else
deps=">=dev-python/sphinx-7.2.6" deps=">=dev-python/sphinx-8.1.3"
fi fi
sphinx_compile_all() { sphinx_compile_all() {
@ -904,6 +926,12 @@ _distutils-r1_print_package_versions() {
dev-python/sip dev-python/sip
) )
;; ;;
uv-build)
packages+=(
dev-python/uv
dev-python/uv-build
)
;;
esac esac
else else
case ${DISTUTILS_USE_SETUPTOOLS} in case ${DISTUTILS_USE_SETUPTOOLS} in
@ -1050,55 +1078,57 @@ _distutils-r1_copy_egg_info() {
find -name '*.egg-info' -type d -exec cp -R -p {} "${BUILD_DIR}"/ ';' || die find -name '*.egg-info' -type d -exec cp -R -p {} "${BUILD_DIR}"/ ';' || die
} }
# @FUNCTION: _distutils-r1_backend_to_key # @FUNCTION: _distutils-r1_key_to_backend
# @USAGE: <backend> # @USAGE: <key>
# @INTERNAL # @INTERNAL
# @DESCRIPTION: # @DESCRIPTION:
# Print the DISTUTILS_USE_PEP517 value corresponding to the backend # Print the backend corresponding to the DISTUTILS_USE_PEP517 value.
# passed as the only argument. _distutils-r1_key_to_backend() {
_distutils-r1_backend_to_key() {
debug-print-function ${FUNCNAME} "$@" debug-print-function ${FUNCNAME} "$@"
local backend=${1} local key=${1}
case ${backend} in case ${key} in
flit_core.buildapi|flit.buildapi) flit)
echo flit echo flit_core.buildapi
;; ;;
flit_scm:buildapi) flit_scm)
echo flit_scm echo flit_scm:buildapi
;; ;;
hatchling.build) hatchling)
echo hatchling echo hatchling.build
;; ;;
jupyter_packaging.build_api) jupyter)
echo jupyter echo jupyter_packaging.build_api
;; ;;
maturin) maturin)
echo maturin echo maturin
;; ;;
mesonpy) meson-python)
echo meson-python echo mesonpy
;; ;;
pbr.build) pbr)
echo pbr echo pbr.build
;; ;;
pdm.backend|pdm.pep517.api) pdm-backend)
echo pdm-backend echo pdm.backend
;; ;;
poetry.core.masonry.api|poetry.masonry.api) poetry)
echo poetry echo poetry.core.masonry.api
;; ;;
scikit_build_core.build) scikit-build-core)
echo scikit-build-core echo scikit_build_core.build
;; ;;
setuptools.build_meta|setuptools.build_meta:__legacy__) setuptools)
echo setuptools echo setuptools.build_meta
;; ;;
sipbuild.api) sip)
echo sip echo sipbuild.api
;;
uv-build)
echo uv_build
;; ;;
*) *)
die "Unknown backend: ${backend}" die "Unknown DISTUTILS_USE_PEP517 key: ${key}"
;; ;;
esac esac
} }
@ -1111,65 +1141,61 @@ _distutils-r1_backend_to_key() {
_distutils-r1_get_backend() { _distutils-r1_get_backend() {
debug-print-function ${FUNCNAME} "$@" debug-print-function ${FUNCNAME} "$@"
local build_backend legacy_fallback local build_backend
if [[ -f pyproject.toml ]]; then if [[ -f pyproject.toml ]]; then
# if pyproject.toml exists, try getting the backend from it # if pyproject.toml exists, try getting the backend from it
# NB: this could fail if pyproject.toml doesn't list one # NB: this could fail if pyproject.toml doesn't list one
build_backend=$("${EPYTHON}" -m gpep517 get-backend) build_backend=$("${EPYTHON}" -m gpep517 get-backend)
fi fi
if [[ -z ${build_backend} && ${DISTUTILS_USE_PEP517} == setuptools &&
-f setup.py ]]
then
# use the legacy setuptools backend as a fallback
build_backend=setuptools.build_meta:__legacy__
legacy_fallback=1
fi
if [[ -z ${build_backend} ]]; then if [[ -z ${build_backend} ]]; then
die "Unable to obtain build-backend from pyproject.toml" if [[ ${DISTUTILS_USE_PEP517} == setuptools && -f setup.py ]]
then
# use the legacy setuptools backend as a fallback
echo setuptools.build_meta:__legacy__
return
else
die "Unable to obtain build-backend from pyproject.toml"
fi
fi fi
if [[ ${DISTUTILS_USE_PEP517} != standalone ]]; then if [[ ${DISTUTILS_USE_PEP517} == standalone ]]; then
# verify whether DISTUTILS_USE_PEP517 was set correctly echo "${build_backend}"
local expected_value=$(_distutils-r1_backend_to_key "${build_backend}") return
if [[ ${DISTUTILS_USE_PEP517} != ${expected_value} ]]; then fi
eerror "DISTUTILS_USE_PEP517 does not match pyproject.toml!"
eerror " have: DISTUTILS_USE_PEP517=${DISTUTILS_USE_PEP517}"
eerror "expected: DISTUTILS_USE_PEP517=${expected_value}"
eerror "(backend: ${build_backend})"
die "DISTUTILS_USE_PEP517 value incorrect"
fi
# fix deprecated backends up # verify that the ebuild correctly specifies the build backend
local new_backend= local expected_backend=$(_distutils-r1_key_to_backend "${DISTUTILS_UPSTREAM_PEP517}")
if [[ ${expected_backend} != ${build_backend} ]]; then
# special-case deprecated backends
case ${build_backend} in case ${build_backend} in
flit.buildapi) flit.buildapi)
new_backend=flit_core.buildapi
;; ;;
pdm.pep517.api) pdm.pep517.api)
new_backend=pdm.backend
;; ;;
poetry.masonry.api) poetry.masonry.api)
new_backend=poetry.core.masonry.api
;; ;;
setuptools.build_meta:__legacy__) setuptools.build_meta:__legacy__)
# this backend should only be used as implicit fallback
[[ ! ${legacy_fallback} ]] &&
new_backend=setuptools.build_meta
;; ;;
uv)
;;
*)
eerror "DISTUTILS_UPSTREAM_PEP517 does not match pyproject.toml!"
eerror " DISTUTILS_UPSTREAM_PEP517=${DISTUTILS_USE_PEP517}"
eerror " implies backend: ${expected_backend}"
eerror " pyproject.toml: ${build_backend}"
die "DISTUTILS_USE_PEP517 value incorrect"
esac esac
if [[ -n ${new_backend} ]]; then # if we didn't die, we're dealing with a deprecated backend
if [[ ! -f ${T}/.distutils_deprecated_backend_warned ]]; then if [[ ! -f ${T}/.distutils_deprecated_backend_warned ]]; then
eqawarn "${build_backend} backend is deprecated. Please see:" eqawarn "${build_backend} backend is deprecated. Please see:"
eqawarn "https://projects.gentoo.org/python/guide/qawarn.html#deprecated-pep-517-backends" eqawarn "https://projects.gentoo.org/python/guide/qawarn.html#deprecated-pep-517-backends"
eqawarn "The eclass will be using ${new_backend} instead." eqawarn "The project should use ${expected_backend} instead."
> "${T}"/.distutils_deprecated_backend_warned || die > "${T}"/.distutils_deprecated_backend_warned || die
fi
build_backend=${new_backend}
fi fi
fi fi
echo "${build_backend}" echo "$(_distutils-r1_key_to_backend "${DISTUTILS_USE_PEP517}")"
} }
# @FUNCTION: distutils_wheel_install # @FUNCTION: distutils_wheel_install
@ -1220,6 +1246,8 @@ distutils_wheel_install() {
-o -path '*.dist-info/licenses' \ -o -path '*.dist-info/licenses' \
-o -path '*.dist-info/zip-safe' \ -o -path '*.dist-info/zip-safe' \
\) -delete || die \) -delete || die
_DISTUTILS_WHL_INSTALLED=1
} }
# @VARIABLE: DISTUTILS_WHEEL_PATH # @VARIABLE: DISTUTILS_WHEEL_PATH
@ -1258,6 +1286,7 @@ distutils_pep517_install() {
fi fi
# set it globally in case we were using "standalone" wrapper # set it globally in case we were using "standalone" wrapper
local -x FLIT_ALLOW_INVALID=1
local -x HATCH_METADATA_CLASSIFIERS_NO_VERIFY=1 local -x HATCH_METADATA_CLASSIFIERS_NO_VERIFY=1
local -x VALIDATE_PYPROJECT_NO_NETWORK=1 local -x VALIDATE_PYPROJECT_NO_NETWORK=1
local -x VALIDATE_PYPROJECT_NO_TROVE_CLASSIFIERS=1 local -x VALIDATE_PYPROJECT_NO_TROVE_CLASSIFIERS=1
@ -1457,67 +1486,66 @@ distutils-r1_python_compile() {
_python_check_EPYTHON _python_check_EPYTHON
case ${DISTUTILS_USE_PEP517:-unset} in [[ ${DISTUTILS_USE_PEP517} == no ]] && return
no)
return
;;
unset)
# legacy mode
_distutils-r1_copy_egg_info
esetup.py build -j "$(makeopts_jobs "${MAKEOPTS} ${*}")" "${@}"
;;
*)
# we do this for all build systems, since other backends
# and custom hooks may wrap setuptools
mkdir -p "${BUILD_DIR}" || die
local -x DIST_EXTRA_CONFIG="${BUILD_DIR}/extra-setup.cfg"
cat > "${DIST_EXTRA_CONFIG}" <<-EOF || die
[build]
build_base = ${BUILD_DIR}/build
[build_ext] if [[ ! ${DISTUTILS_USE_PEP517} ]]; then
parallel = $(makeopts_jobs "${MAKEOPTS} ${*}") # legacy mode
EOF _distutils-r1_copy_egg_info
;; esetup.py build -j "$(makeopts_jobs "${MAKEOPTS} ${*}")" "${@}"
esac return
if [[ ${DISTUTILS_USE_PEP517} ]]; then
if [[ ${DISTUTILS_ALLOW_WHEEL_REUSE} ]]; then
local whl
for whl in "${!DISTUTILS_WHEELS[@]}"; do
# use only wheels corresponding to the current directory
if [[ ${PWD} != ${DISTUTILS_WHEELS["${whl}"]} ]]; then
continue
fi
# 1. Use pure Python wheels only if we're not expected
# to build extensions. Otherwise, we may end up
# not building the extension at all when e.g. PyPy3
# is built without one.
#
# 2. For CPython, we can reuse stable ABI wheels. Note
# that this relies on the assumption that we're building
# from the oldest to the newest implementation,
# and the wheels are forward-compatible.
if [[
( ! ${DISTUTILS_EXT} && ${whl} == *py3-none-any* ) ||
(
${EPYTHON} == python* &&
# freethreading does not support stable ABI
# at the moment
${EPYTHON} != *t &&
${whl} == *-abi3-*
)
]]; then
distutils_wheel_install "${BUILD_DIR}/install" "${whl}"
return
fi
done
fi
distutils_pep517_install "${BUILD_DIR}/install"
DISTUTILS_WHEELS+=( "${DISTUTILS_WHEEL_PATH}" "${PWD}" )
fi fi
# we do this for all build systems, since other backends
# and custom hooks may wrap setuptools
#
# we are appending a dynamic component so that
# distutils-r1_python_compile can be called multiple
# times and don't end up combining resulting packages
mkdir -p "${BUILD_DIR}" || die
local -x DIST_EXTRA_CONFIG="${BUILD_DIR}/extra-setup.cfg"
cat > "${DIST_EXTRA_CONFIG}" <<-EOF || die
[build]
build_base = ${BUILD_DIR}/build${#DISTUTILS_WHEELS[@]}
[build_ext]
parallel = $(makeopts_jobs "${MAKEOPTS} ${*}")
EOF
if [[ ${DISTUTILS_ALLOW_WHEEL_REUSE} ]]; then
local whl
for whl in "${!DISTUTILS_WHEELS[@]}"; do
# use only wheels corresponding to the current directory
if [[ ${PWD} != ${DISTUTILS_WHEELS["${whl}"]} ]]; then
continue
fi
# 1. Use pure Python wheels only if we're not expected
# to build extensions. Otherwise, we may end up
# not building the extension at all when e.g. PyPy3
# is built without one.
#
# 2. For CPython, we can reuse stable ABI wheels. Note
# that this relies on the assumption that we're building
# from the oldest to the newest implementation,
# and the wheels are forward-compatible.
if [[
( ! ${DISTUTILS_EXT} && ${whl} == *py3-none-any* ) ||
(
${EPYTHON} == python* &&
# freethreading does not support stable ABI
# at the moment
${EPYTHON} != *t &&
${whl} == *-abi3-*
)
]]; then
distutils_wheel_install "${BUILD_DIR}/install" "${whl}"
return
fi
done
fi
distutils_pep517_install "${BUILD_DIR}/install"
DISTUTILS_WHEELS+=( "${DISTUTILS_WHEEL_PATH}" "${PWD}" )
} }
# @FUNCTION: _distutils-r1_wrap_scripts # @FUNCTION: _distutils-r1_wrap_scripts
@ -1985,6 +2013,11 @@ _distutils-r1_compare_installed_files() {
_distutils-r1_post_python_compile() { _distutils-r1_post_python_compile() {
debug-print-function ${FUNCNAME} "$@" debug-print-function ${FUNCNAME} "$@"
if [[ ! ${_DISTUTILS_WHL_INSTALLED} && ${DISTUTILS_USE_PEP517:-no} != no ]]
then
die "No wheel installed in python_compile(), did you call distutils-r1_python_compile?"
fi
local root=${BUILD_DIR}/install local root=${BUILD_DIR}/install
if [[ ${DISTUTILS_USE_PEP517} && -d ${root} ]]; then if [[ ${DISTUTILS_USE_PEP517} && -d ${root} ]]; then
# copy executables to python-exec directory # copy executables to python-exec directory