blob: 4618cb86cde0d99c1c1b9df5448aed4378abd100 [file] [edit]
# Copyright 1999-2026 Gentoo Authors
# Distributed under the terms of the GNU General Public License v2
EAPI="7"
WANT_LIBTOOL="none"
inherit autotools check-reqs flag-o-matic linux-info multiprocessing pax-utils prefix python-utils-r1 toolchain-funcs verify-sig cros-sanitizers
MY_PV=${PV}
MY_P="Python-${MY_PV%_p*}"
PYVER=$(ver_cut 1-2)
PATCHSET="python-gentoo-patches-${MY_PV}"
DESCRIPTION="An interpreted, interactive, object-oriented programming language"
HOMEPAGE="
https://www.python.org/
https://github.com/python/cpython/
"
SRC_URI="
https://www.python.org/ftp/python/${PV%%_*}/${MY_P}.tar.xz
https://distfiles.gentoo.org/pub/proj/python/patchsets/${PYVER%t}/${PATCHSET}.tar.xz
verify-sig? (
https://www.python.org/ftp/python/${PV%%_*}/${MY_P}.tar.xz.asc
)
"
S="${WORKDIR}/${MY_P}"
LICENSE="PSF-2"
SLOT="${PYVER}"
KEYWORDS="*"
IUSE="
bluetooth debug +ensurepip examples gdbm libedit +ncurses pgo
+readline +sqlite +ssl test tk valgrind
"
RESTRICT="!test? ( test )"
# Do not add a dependency on dev-lang/python to this ebuild.
# If you need to apply a patch which requires python for bootstrapping, please
# run the bootstrap code on your dev box and include the results in the
# patchset. See bug 447752.
RDEPEND="
app-arch/bzip2:=
app-arch/xz-utils:=
app-crypt/libb2
app-misc/mime-types
>=dev-libs/expat-2.1:=
dev-libs/libffi:=
dev-libs/mpdecimal:=
dev-python/gentoo-common
>=virtual/zlib-1.1.3:=
virtual/libintl
gdbm? ( sys-libs/gdbm:=[berkdb] )
kernel_linux? ( sys-apps/util-linux:= )
ncurses? ( >=sys-libs/ncurses-5.2:= )
readline? (
!libedit? ( >=sys-libs/readline-4.1:= )
libedit? ( dev-libs/libedit:= )
)
sqlite? ( >=dev-db/sqlite-3.3.8:3= )
ssl? ( >=dev-libs/openssl-1.1.1:= )
tk? (
>=dev-lang/tcl-8.0:=
>=dev-lang/tk-8.0:=
dev-tcltk/blt:=
dev-tcltk/tix
)
"
# bluetooth requires headers from bluez
DEPEND="
${RDEPEND}
bluetooth? ( net-wireless/bluez )
test? (
dev-python/ensurepip-pip
dev-python/ensurepip-setuptools
)
valgrind? ( dev-debug/valgrind )
"
if [[ ${PV} != *_alpha* ]]; then
RDEPEND+="
dev-lang/python-exec[python_targets_python${PYVER/./_}(-)]
"
fi
PDEPEND="
ensurepip? ( dev-python/ensurepip-pip )
"
VERIFY_SIG_OPENPGP_KEY_PATH=/usr/share/openpgp-keys/python.org.asc
# large file tests involve a 2.5G file being copied (duplicated)
CHECKREQS_DISK_BUILD=5500M
QA_PKGCONFIG_VERSION=${PYVER}
# false positives -- functions specific to *BSD
QA_CONFIG_IMPL_DECL_SKIP=( chflags lchflags )
declare -rgA PYTHON_KERNEL_CHECKS=(
["CROSS_MEMORY_ATTACH"]="test_external_inspection" #bug 938589
["DNOTIFY"]="test_fcntl" # bug 938662
)
# Google-specific PGO bits
SRC_URI+=" pgo_use? ( gs://chromeos-localmirror/distfiles/python-$(ver_cut 1-2)-profile.tar.xz )"
IUSE+=" pgo_generate +pgo_use"
REQUIRED_USE+=" pgo_generate? ( !pgo_use )"
# CrOS: We use the SDK's Python for --with-build-python when cross-compiling.
IUSE+=" cros_host"
BDEPEND+=" !cros_host? ( dev-lang/python:${SLOT} )"
pkg_pretend() {
if use pgo || use test; then
check-reqs_pkg_pretend
fi
}
pkg_setup() {
if [[ ${MERGE_TYPE} != binary ]]; then
if use test || use pgo; then
check-reqs_pkg_setup
local CONFIG_CHECK
for f in "${!PYTHON_KERNEL_CHECKS[@]}"; do
CONFIG_CHECK+="~${f} "
done
linux-info_pkg_setup
fi
fi
}
src_unpack() {
if use verify-sig; then
verify-sig_verify_detached "${DISTDIR}"/${MY_P}.tar.xz{,.asc}
fi
default
}
src_prepare() {
local PATCHES=(
"${WORKDIR}/${PATCHSET}"
)
default
# START: ChromiumOS
# Note: Ensure these patch files have been rebased and renamed for 3.13 in your FILESDIR
eapply "${FILESDIR}/python-3.13-cross-python-config.patch"
eapply "${FILESDIR}/python-3.8-hash-compile-invalidation.patch"
# Support searching /usr/local for Python on dev/test images.
sed -i -e "s:sys.exec_prefix]:sys.exec_prefix, '/usr/local']:g" \
Lib/site.py || die "sed failed to add /usr/local to prefixes"
# Speed up the build and workaround b/240951449 by removing self tests.
if ! use test && ! use pgo_generate ; then
find "${S}/Lib/" -type f -name 'test_*.py' -delete || die
rm -rf "${S}/Lib/test" || die
rm -rf "${S}/Lib/"test_* || die
fi
# END: ChromiumOS
# force the correct number of jobs
# https://bugs.gentoo.org/737660
sed -i -e "s:-j0:-j$(makeopts_jobs):" Makefile.pre.in || die
# breaks tests when using --with-wheel-pkg-dir
rm -rf Lib/test/wheeldata || die
eautoreconf
}
src_configure() {
# disable automagic bluetooth headers detection
if ! use bluetooth; then
local -x ac_cv_header_bluetooth_bluetooth_h=no
fi
filter-flags -malign-double
# Export CXX so it ends up in /usr/lib/python3.X/config/Makefile.
# PKG_CONFIG needed for cross.
tc-export CXX PKG_CONFIG
local dbmliborder=
if use gdbm; then
dbmliborder+="${dbmliborder:+:}gdbm"
fi
# Set baseline test skip flags.
COMMON_TEST_SKIPS=(
-x test_gdb
-x test_pretty_print
-x test_perf_profiler
)
# Arch-specific skips.
case ${CHOST} in
alpha*)
COMMON_TEST_SKIPS+=( -x test_builtin -x test_capi -x test_cmath -x test_float -x test_free_threading -x test_math -x test_numeric_tower -x test_random -x test_statistics -x test_resource -x test_strtod )
;;
mips*)
COMMON_TEST_SKIPS+=( -x test_ctypes -x test_external_inspection -x test_statistics )
;;
riscv*)
COMMON_TEST_SKIPS+=( -x test_urllib2 )
;;
sparc*)
COMMON_TEST_SKIPS+=( -x test_multiprocessing_fork -x test_multiprocessing_forkserver -x test_multiprocessing_spawn -x test_ctypes -x test_exceptions )
;;
esac
for option in "${!PYTHON_KERNEL_CHECKS[@]}"; do
if ! linux_config_exists || ! linux_chkconfig_present "${option}"; then
COMMON_TEST_SKIPS+=( -x "${PYTHON_KERNEL_CHECKS[${option}]}" )
fi
done
use elibc_musl && COMMON_TEST_SKIPS+=( -x test__locale -x test_c_locale_coercion -x test_locale -x test_re -x test_ctypes -x test_os )
if use pgo; then
local profile_task_flags=(
-m test
"-j$(makeopts_jobs)"
--pgo-extended
--verbose3
-u-network
--timeout 1200
"${COMMON_TEST_SKIPS[@]}"
-x test_dtrace
-x test_asyncio
-x test_httpservers
-x test_logging
-x test_multiprocessing_fork
-x test_socket
-x test_xmlrpc
-x test_tools
)
if has_version "app-arch/rpm" ; then
profile_task_flags+=( -x test_distutils )
fi
local -x PROFILE_TASK="${profile_task_flags[*]} || true"
fi
local myeconfargs=(
ac_cv_header_stropts_h=no
--enable-shared
--without-static-libpython
--enable-ipv6
--infodir='${prefix}/share/info'
--mandir='${prefix}/share/man'
--with-dbmliborder="${dbmliborder}"
--with-libc=
--enable-loadable-sqlite-extensions
--without-ensurepip
--without-lto
--with-system-expat
--with-system-libmpdec
--with-platlibdir=lib
--with-pkg-config=yes
--with-wheel-pkg-dir="${EPREFIX}"/usr/lib/python/ensurepip
--enable-gil
$(use_with debug assertions)
$(use_enable pgo optimizations)
$(use_with readline readline "$(usex libedit editline readline)")
$(use_with valgrind)
)
if tc-is-lto; then
myeconfargs+=( --with-lto )
fi
if use pgo_use && ! use coverage; then
append-cppflags "-fprofile-use=${WORKDIR}/code.profclangd"
elif use pgo_generate; then
myeconfargs+=(
"LLVM_PROFDATA=$(which llvm-profdata)"
--enable-optimizations
)
fi
cat > Modules/Setup.local <<-EOF || die
*disabled*
nis
$(use gdbm || echo '_gdbm _dbm')
$(use sqlite || echo '_sqlite3')
$(use ssl || echo '_hashlib _ssl')
$(use ncurses || echo '_curses _curses_panel')
$(use readline || echo 'readline')
$(use tk || echo '_tkinter')
EOF
local -x OPT=
if tc-is-cross-compiler ; then
myeconfargs+=(
# CrOS: Use Python from the SDK.
--with-build-python="/usr/bin/python${PYVER}"
)
fi
# pass system CFLAGS & LDFLAGS as _NODIST, otherwise they'll get
# propagated to sysconfig for built extensions
local -x CFLAGS_NODIST=${CFLAGS}
local -x LDFLAGS_NODIST=${LDFLAGS}
local -x CFLAGS= LDFLAGS=
# CrOS: When building for sanitizers, we must preserve the sanitizer flags
sanitizers-setup-env
if use ncurses; then
append-cppflags -I"${ESYSROOT}"/usr/include/ncursesw
fi
econf "${myeconfargs[@]}"
if grep -q "#define POSIX_SEMAPHORES_NOT_ENABLED 1" pyconfig.h; then
eerror "configure has detected that the sem_open function is broken."
eerror "Please ensure that /dev/shm is mounted as a tmpfs with mode 1777."
die "Broken sem_open function (bug 496328)"
fi
echo "EPYTHON='python${PYVER}'" > Lib/epython.py || die
}
src_compile() {
local -x LC_ALL=C
export PYTHONSTRICTEXTENSIONBUILD=1
local -x _PYTHONDONTWRITEBYTECODE=${PYTHONDONTWRITEBYTECODE}
export GENTOO_CPYTHON_BUILD=1
if use pgo ; then
local -x COLUMNS=80
local -x PYTHONDONTWRITEBYTECODE=
local -x TMPDIR=/var/tmp
fi
emake CPPFLAGS= CFLAGS= LDFLAGS=
local -x PYTHONDONTWRITEBYTECODE=${_PYTHONDONTWRITEBYTECODE}
if has_version dev-libs/libffi[pax-kernel]; then
pax-mark E python
else
pax-mark m python
fi
}
src_test() {
if tc-is-cross-compiler; then
elog "Disabling tests due to crosscompiling."
return
fi
local -x LOGNAME=buildbot
local test_opts=(
--verbose3
-u-network
-j "$(makeopts_jobs)"
"${COMMON_TEST_SKIPS[@]}"
)
local -x COLUMNS=80
local -x PYTHONDONTWRITEBYTECODE=
local -x TMPDIR=/var/tmp
nonfatal emake -Onone test EXTRATESTOPTS="${test_opts[*]}" \
CPPFLAGS= CFLAGS= LDFLAGS= < /dev/tty
local ret=${?}
[[ ${ret} -eq 0 ]] || die "emake test failed"
}
src_install() {
local libdir=${ED}/usr/lib/python${PYVER}
# -j1 hack for now for bug #843458
emake -j1 DESTDIR="${D}" TEST_MODULES=no altinstall
# Fix collisions between different slots of Python.
rm "${ED}/usr/$(get_libdir)/libpython3.so" || die
local abiver=$(cd "${ED}/usr/include"; echo python*)
if [[ ${abiver} != python${PYVER} ]]; then
rm "${ED}/usr/bin/python${PYVER}" || die
dosym "${abiver}" "/usr/bin/python${PYVER}"
dosym "${abiver}-config" "/usr/bin/python${PYVER}-config"
dosym "python-${PYVER}.pc" "/usr/$(get_libdir)/pkgconfig/${abiver/${PYVER}/-${PYVER}}.pc"
fi
if has_version dev-libs/libffi[pax-kernel]; then
pax-mark E "${ED}/usr/bin/${abiver}"
else
pax-mark m "${ED}/usr/bin/${abiver}"
fi
rm -rf "${libdir}"/ensurepip/_bundled || die
if ! use sqlite; then
rm -rf "${libdir}/"sqlite3 || die
fi
if ! use tk; then
rm -rf "${ED}/usr/bin/idle${PYVER}" || die
rm -rf "${libdir}/"{idlelib,tkinter} || die
fi
ln -s ../python/EXTERNALLY-MANAGED "${libdir}/EXTERNALLY-MANAGED" || die
dodoc Misc/{ACKS,HISTORY,NEWS}
if use examples; then
docinto examples
find Tools -name __pycache__ -exec rm -fr {} + || die
dodoc -r Tools
fi
insinto /usr/share/gdb/auto-load/usr/$(get_libdir) #443510
local libname=$(
printf 'e:\n\t@echo $(INSTSONAME)\ninclude Makefile\n' |
emake --no-print-directory -s -f - 2>/dev/null
)
newins Tools/gdb/libpython.py "${libname}"-gdb.py
newconfd "${FILESDIR}/pydoc.conf" pydoc-${PYVER}
newinitd "${FILESDIR}/pydoc.init" pydoc-${PYVER}
sed \
-e "s:@PYDOC_PORT_VARIABLE@:PYDOC${PYVER/./_}_PORT:" \
-e "s:@PYDOC@:pydoc${PYVER}:" \
-i "${ED}/etc/conf.d/pydoc-${PYVER}" \
"${ED}/etc/init.d/pydoc-${PYVER}" || die "sed failed"
local pymajor=${PYVER%.*}
local EPYTHON=python${PYVER}
local scriptdir=${D}$(python_get_scriptdir)
mkdir -p "${scriptdir}" || die
ln -s "../../../bin/${abiver}" "${scriptdir}/python${pymajor}" || die
ln -s "python${pymajor}" "${scriptdir}/python" || die
cat > "${scriptdir}/python${pymajor}-config" <<-EOF || die
#!/bin/sh
exec "${abiver}-config" "\${@}"
EOF
chmod +x "${scriptdir}/python${pymajor}-config" || die
ln -s "python${pymajor}-config" "${scriptdir}/python-config" || die
ln -s "../../../bin/pydoc${PYVER}" "${scriptdir}/pydoc" || die
if use tk; then
ln -s "../../../bin/idle${PYVER}" "${scriptdir}/idle" || die
fi
# In python3.13, the "pipes" module was removed. We use "shlex" intead.
# Inject backwards compatibility hack for legacy k8s scripts
insinto "/usr/lib/python${PYVER}/site-packages"
doins "${FILESDIR}/pipes.py"
}