summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>2017-04-11 18:39:00 +0200
committerMichael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>2017-04-11 18:39:00 +0200
commitd8836db9ef9e111f1c8791b0ed3a3ae3f4c39f28 (patch)
tree31e12d6d562568e928b5ca345ac83809869e6466
parentdev-libs/openssl: in prefix-chain do not hardcode EPREFIX to find perl (diff)
downloadprefix-d8836db9ef9e111f1c8791b0ed3a3ae3f4c39f28.tar.gz
prefix-d8836db9ef9e111f1c8791b0ed3a3ae3f4c39f28.tar.bz2
prefix-d8836db9ef9e111f1c8791b0ed3a3ae3f4c39f28.zip
clone eclasses for USE=prefix-chain: libtool, python-utils-r1
-rw-r--r--eclass/libtool.eclass509
-rw-r--r--eclass/python-utils-r1.eclass1454
2 files changed, 1963 insertions, 0 deletions
diff --git a/eclass/libtool.eclass b/eclass/libtool.eclass
new file mode 100644
index 0000000000..576abd3a5f
--- /dev/null
+++ b/eclass/libtool.eclass
@@ -0,0 +1,509 @@
+# Copyright 1999-2017 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: libtool.eclass
+# @MAINTAINER:
+# base-system@gentoo.org
+# @BLURB: quickly update bundled libtool code
+# @DESCRIPTION:
+# This eclass patches ltmain.sh distributed with libtoolized packages with the
+# relink and portage patch among others
+#
+# Note, this eclass does not require libtool as it only applies patches to
+# generated libtool files. We do not run the libtoolize program because that
+# requires a regeneration of the main autotool files in order to work properly.
+
+if [[ -z ${_LIBTOOL_ECLASS} ]]; then
+_LIBTOOL_ECLASS=1
+
+DEPEND=">=app-portage/elt-patches-20170317"
+
+libtool_elt_patch_dir() {
+ echo "${EPREFIX}/usr/share/elt-patches"
+}
+
+inherit multilib toolchain-funcs
+
+#
+# See if we can apply $2 on $1, and if so, do it
+#
+ELT_try_and_apply_patch() {
+ local ret=0
+ local file=$1
+ local patch=$2
+ local src=$3
+ local disp="${src} patch"
+ local log="${T}/elibtool.log"
+
+ if [[ -z ${_ELT_NOTED_TMP} ]] ; then
+ _ELT_NOTED_TMP=true
+ printf 'temp patch: %s\n' "${patch}" > "${log}"
+ fi
+ printf '\nTrying %s\n' "${disp}" >> "${log}"
+
+ if [[ ! -e ${file} ]] ; then
+ echo "File not found: ${file}" >> "${log}"
+ return 1
+ fi
+
+ # Save file for permission restoration. `patch` sometimes resets things.
+ # Ideally we'd want 'stat -c %a', but stat is highly non portable and we are
+ # guaranted to have GNU find, so use that instead.
+ local perms="$(find ${file} -maxdepth 0 -printf '%m')"
+ # We only support patchlevel of 0 - why worry if its static patches?
+ if patch -p0 --dry-run "${file}" "${patch}" >> "${log}" 2>&1 ; then
+ einfo " Applying ${disp} ..."
+ patch -p0 -g0 --no-backup-if-mismatch "${file}" "${patch}" >> "${log}" 2>&1
+ ret=$?
+ export ELT_APPLIED_PATCHES="${ELT_APPLIED_PATCHES} ${src}"
+ else
+ ret=1
+ fi
+ chmod "${perms}" "${file}"
+
+ return "${ret}"
+}
+
+#
+# Get string version of ltmain.sh or ltconfig (passed as $1)
+#
+ELT_libtool_version() {
+ (
+ unset VERSION
+ eval $(grep -e '^[[:space:]]*VERSION=' "$1")
+ echo "${VERSION:-0}"
+ )
+}
+
+#
+# Run through the patches in $2 and see if any
+# apply to $1 ...
+#
+ELT_walk_patches() {
+ local patch tmp
+ local ret=1
+ local file=$1
+ local patch_set=$2
+ local patch_dir="$(libtool_elt_patch_dir)/${patch_set}"
+ local rem_int_dep=$3
+
+ [[ -z ${patch_set} ]] && return 1
+ [[ ! -d ${patch_dir} ]] && return 1
+
+ # Allow patches to use @GENTOO_LIBDIR@ replacements
+ local sed_args=( -e "s:@GENTOO_LIBDIR@:$(get_libdir):g" )
+ if [[ -n ${rem_int_dep} ]] ; then
+ # replace @REM_INT_DEP@ with what was passed
+ # to --remove-internal-dep
+ sed_args+=( -e "s|@REM_INT_DEP@|${rem_int_dep}|g" )
+ fi
+
+ pushd "$(libtool_elt_patch_dir)" >/dev/null || die
+
+ # Go through the patches in reverse order (newer version to older)
+ for patch in $(find "${patch_set}" -maxdepth 1 -type f | LC_ALL=C sort -r) ; do
+ tmp="${T}/libtool-elt.patch"
+ sed "${sed_args[@]}" "${patch}" > "${tmp}" || die
+ if ELT_try_and_apply_patch "${file}" "${tmp}" "${patch}" ; then
+ # Break to unwind w/popd rather than return directly
+ ret=0
+ break
+ fi
+ done
+
+ popd >/dev/null
+ return ${ret}
+}
+
+# @FUNCTION: elibtoolize
+# @USAGE: [dirs] [--portage] [--reverse-deps] [--patch-only] [--remove-internal-dep=xxx] [--shallow] [--no-uclibc]
+# @DESCRIPTION:
+# Apply a smorgasbord of patches to bundled libtool files. This function
+# should always be safe to run. If no directories are specified, then
+# ${S} will be searched for appropriate files.
+#
+# If the --shallow option is used, then only ${S}/ltmain.sh will be patched.
+#
+# The other options should be avoided in general unless you know what's going on.
+elibtoolize() {
+ local x
+ local dirs=()
+ local do_portage="no"
+ local do_reversedeps="yes"
+ local do_only_patches="no"
+ local do_uclibc="yes"
+ local deptoremove=
+ local do_shallow="no"
+ local force="false"
+ local elt_patches="install-sh ltmain portage relink max_cmd_len sed test tmp cross as-needed target-nm ppc64le"
+
+ for x in "$@" ; do
+ case ${x} in
+ --portage)
+ # Only apply portage patch, and don't
+ # 'libtoolize --copy --force' if all patches fail.
+ do_portage="yes"
+ ;;
+ --reverse-deps)
+ # Apply the reverse-deps patch
+ # http://bugzilla.gnome.org/show_bug.cgi?id=75635
+ do_reversedeps="yes"
+ elt_patches+=" fix-relink"
+ ;;
+ --patch-only)
+ # Do not run libtoolize if none of the patches apply ..
+ do_only_patches="yes"
+ ;;
+ --remove-internal-dep=*)
+ # We will replace @REM_INT_DEP@ with what is needed
+ # in ELT_walk_patches() ...
+ deptoremove=${x#--remove-internal-dep=}
+
+ # Add the patch for this ...
+ [[ -n ${deptoremove} ]] && elt_patches+=" rem-int-dep"
+ ;;
+ --shallow)
+ # Only patch the ltmain.sh in ${S}
+ do_shallow="yes"
+ ;;
+ --no-uclibc)
+ do_uclibc="no"
+ ;;
+ --force)
+ force="true"
+ ;;
+ -*)
+ eerror "Invalid elibtoolize option: ${x}"
+ die "elibtoolize called with ${x} ??"
+ ;;
+ *) dirs+=( "${x}" )
+ esac
+ done
+
+ [[ ${do_uclibc} == "yes" ]] && elt_patches+=" uclibc-conf uclibc-ltconf"
+
+ case ${CHOST} in
+ *-aix*) elt_patches+=" hardcode aixrtl" ;; #213277
+ *-darwin*) elt_patches+=" darwin-ltconf darwin-ltmain darwin-conf" ;;
+ *-solaris*) elt_patches+=" sol2-conf sol2-ltmain" ;;
+ *-freebsd*) elt_patches+=" fbsd-conf fbsd-ltconf" ;;
+ *-hpux*) elt_patches+=" hpux-conf deplibs hc-flag-ld hardcode hardcode-relink relink-prog no-lc" ;;
+ *-irix*) elt_patches+=" irix-ltmain" ;;
+ *-mint*) elt_patches+=" mint-conf" ;;
+ esac
+
+ if $(tc-getLD) --version 2>&1 | grep -qs 'GNU gold'; then
+ elt_patches+=" gold-conf"
+ fi
+
+ # Find out what dirs to scan.
+ if [[ ${do_shallow} == "yes" ]] ; then
+ [[ ${#dirs[@]} -ne 0 ]] && die "Using --shallow with explicit dirs doesn't make sense"
+ [[ -f ${S}/ltmain.sh || -f ${S}/configure ]] && dirs+=( "${S}" )
+ else
+ [[ ${#dirs[@]} -eq 0 ]] && dirs+=( "${S}" )
+ dirs=( $(find "${dirs[@]}" '(' -name ltmain.sh -o -name configure ')' -printf '%h\n' | sort -u) )
+ fi
+
+ local d p ret
+ for d in "${dirs[@]}" ; do
+ export ELT_APPLIED_PATCHES=
+
+ if [[ -f ${d}/.elibtoolized ]] ; then
+ ${force} || continue
+ fi
+
+ local outfunc="einfo"
+ [[ -f ${d}/.elibtoolized ]] && outfunc="ewarn"
+ ${outfunc} "Running elibtoolize in: ${d#${WORKDIR}/}/"
+ if [[ ${outfunc} == "ewarn" ]] ; then
+ ewarn " We've already been run in this tree; you should"
+ ewarn " avoid this if possible (perhaps by filing a bug)"
+ fi
+
+ # patching ltmain.sh
+ [[ -f ${d}/ltmain.sh ]] &&
+ for p in ${elt_patches} ; do
+ ret=0
+
+ case ${p} in
+ portage)
+ # Stupid test to see if its already applied ...
+ if ! grep -qs 'We do not want portage' "${d}/ltmain.sh" ; then
+ ELT_walk_patches "${d}/ltmain.sh" "${p}"
+ ret=$?
+ fi
+ ;;
+ rem-int-dep)
+ ELT_walk_patches "${d}/ltmain.sh" "${p}" "${deptoremove}"
+ ret=$?
+ ;;
+ fix-relink)
+ # Do not apply if we do not have the relink patch applied ...
+ if grep -qs 'inst_prefix_dir' "${d}/ltmain.sh" ; then
+ ELT_walk_patches "${d}/ltmain.sh" "${p}"
+ ret=$?
+ fi
+ ;;
+ max_cmd_len)
+ # Do not apply if $max_cmd_len is not used ...
+ if grep -qs 'max_cmd_len' "${d}/ltmain.sh" ; then
+ ELT_walk_patches "${d}/ltmain.sh" "${p}"
+ ret=$?
+ fi
+ ;;
+ as-needed)
+ ELT_walk_patches "${d}/ltmain.sh" "${p}"
+ ret=$?
+ ;;
+ uclibc-ltconf)
+ # Newer libtoolize clears ltconfig, as not used anymore
+ if [[ -s ${d}/ltconfig ]] ; then
+ ELT_walk_patches "${d}/ltconfig" "${p}"
+ ret=$?
+ fi
+ ;;
+ fbsd-ltconf)
+ if [[ -s ${d}/ltconfig ]] ; then
+ ELT_walk_patches "${d}/ltconfig" "${p}"
+ ret=$?
+ fi
+ ;;
+ darwin-ltconf)
+ # Newer libtoolize clears ltconfig, as not used anymore
+ if [[ -s ${d}/ltconfig ]] ; then
+ ELT_walk_patches "${d}/ltconfig" "${p}"
+ ret=$?
+ fi
+ ;;
+ darwin-ltmain)
+ # special case to avoid false positives (failing to apply
+ # ltmain.sh path message), newer libtools have this patch
+ # built in, so not much to patch around then
+ if [[ -e ${d}/ltmain.sh ]] && \
+ ! grep -qs 'verstring="-compatibility_version' "${d}/ltmain.sh" ; then
+ ELT_walk_patches "${d}/ltmain.sh" "${p}"
+ ret=$?
+ fi
+ ;;
+ install-sh)
+ ELT_walk_patches "${d}/install-sh" "${p}"
+ ret=$?
+ ;;
+ cross)
+ if tc-is-cross-compiler ; then
+ ELT_walk_patches "${d}/ltmain.sh" "${p}"
+ ret=$?
+ fi
+ ;;
+ *)
+ ELT_walk_patches "${d}/ltmain.sh" "${p}"
+ ret=$?
+ ;;
+ esac
+
+ if [[ ${ret} -ne 0 ]] ; then
+ case ${p} in
+ relink)
+ local version=$(ELT_libtool_version "${d}/ltmain.sh")
+ # Critical patch, but could be applied ...
+ # FIXME: Still need a patch for ltmain.sh > 1.4.0
+ if ! grep -qs 'inst_prefix_dir' "${d}/ltmain.sh" && \
+ [[ $(VER_to_int "${version}") -ge $(VER_to_int "1.4.0") ]] ; then
+ ewarn " Could not apply relink.patch!"
+ fi
+ ;;
+ portage)
+ # Critical patch - for this one we abort, as it can really
+ # cause breakage without it applied!
+ if [[ ${do_portage} == "yes" ]] ; then
+ # Stupid test to see if its already applied ...
+ if ! grep -qs 'We do not want portage' "${d}/ltmain.sh" ; then
+ echo
+ eerror "Portage patch requested, but failed to apply!"
+ eerror "Please file a bug report to add a proper patch."
+ die "Portage patch requested, but failed to apply!"
+ fi
+ else
+ if grep -qs 'We do not want portage' "${d}/ltmain.sh" ; then
+ # ewarn " Portage patch seems to be already applied."
+ # ewarn " Please verify that it is not needed."
+ :
+ else
+ local version=$(ELT_libtool_version "${d}"/ltmain.sh)
+ echo
+ eerror "Portage patch failed to apply (ltmain.sh version ${version})!"
+ eerror "Please file a bug report to add a proper patch."
+ die "Portage patch failed to apply!"
+ fi
+ # We do not want to run libtoolize ...
+ ELT_APPLIED_PATCHES="portage"
+ fi
+ ;;
+ darwin-*)
+ [[ ${CHOST} == *"-darwin"* ]] && ewarn " Darwin patch set '${p}' failed to apply!"
+ ;;
+ esac
+ fi
+ done
+
+ # makes sense for ltmain.sh patches only
+ [[ -f ${d}/ltmain.sh ]] &&
+ if [[ -z ${ELT_APPLIED_PATCHES} ]] ; then
+ if [[ ${do_portage} == "no" && \
+ ${do_reversedeps} == "no" && \
+ ${do_only_patches} == "no" && \
+ ${deptoremove} == "" ]]
+ then
+ ewarn "Cannot apply any patches, please file a bug about this"
+ die
+ fi
+ fi
+
+ # patching configure
+ [[ -f ${d}/configure ]] &&
+ for p in ${elt_patches} ; do
+ ret=0
+
+ case ${p} in
+ uclibc-conf)
+ if grep -qs 'Transform linux' "${d}/configure" ; then
+ ELT_walk_patches "${d}/configure" "${p}"
+ ret=$?
+ fi
+ ;;
+ fbsd-conf)
+ if grep -qs 'version_type=freebsd-' "${d}/configure" ; then
+ ELT_walk_patches "${d}/configure" "${p}"
+ ret=$?
+ fi
+ ;;
+ darwin-conf)
+ if grep -qs '&& echo \.so ||' "${d}/configure" ; then
+ ELT_walk_patches "${d}/configure" "${p}"
+ ret=$?
+ fi
+ ;;
+ aixrtl|hpux-conf)
+ ret=1
+ local subret=0
+ # apply multiple patches as often as they match
+ while [[ $subret -eq 0 ]]; do
+ subret=1
+ if [[ -e ${d}/configure ]]; then
+ ELT_walk_patches "${d}/configure" "${p}"
+ subret=$?
+ fi
+ if [[ $subret -eq 0 ]]; then
+ # have at least one patch succeeded.
+ ret=0
+ fi
+ done
+ ;;
+ mint-conf|gold-conf|sol2-conf)
+ ELT_walk_patches "${d}/configure" "${p}"
+ ret=$?
+ ;;
+ target-nm)
+ ELT_walk_patches "${d}/configure" "${p}"
+ ret=$?
+ ;;
+ ppc64le)
+ ELT_walk_patches "${d}/configure" "${p}"
+ ret=$?
+ ;;
+ *)
+ # ltmain.sh patches are applied above
+ ;;
+ esac
+
+ if [[ ${ret} -ne 0 ]] ; then
+ case ${p} in
+ uclibc-*)
+ [[ ${CHOST} == *-uclibc ]] && ewarn " uClibc patch set '${p}' failed to apply!"
+ ;;
+ fbsd-*)
+ if [[ ${CHOST} == *-freebsd* ]] ; then
+ if [[ -z $(grep 'Handle Gentoo/FreeBSD as it was Linux' \
+ "${d}/configure" 2>/dev/null) ]]; then
+ eerror " FreeBSD patch set '${p}' failed to apply!"
+ die "FreeBSD patch set '${p}' failed to apply!"
+ fi
+ fi
+ ;;
+ darwin-*)
+ [[ ${CHOST} == *"-darwin"* ]] && ewarn " Darwin patch set '${p}' failed to apply!"
+ ;;
+ esac
+ fi
+ done
+
+ rm -f "${d}/libtool"
+
+ > "${d}/.elibtoolized"
+ done
+}
+
+uclibctoolize() { die "Use elibtoolize"; }
+darwintoolize() { die "Use elibtoolize"; }
+
+# char *VER_major(string)
+#
+# Return the Major (X of X.Y.Z) version
+#
+VER_major() {
+ [[ -z $1 ]] && return 1
+
+ local VER=$@
+ echo "${VER%%[^[:digit:]]*}"
+}
+
+# char *VER_minor(string)
+#
+# Return the Minor (Y of X.Y.Z) version
+#
+VER_minor() {
+ [[ -z $1 ]] && return 1
+
+ local VER=$@
+ VER=${VER#*.}
+ echo "${VER%%[^[:digit:]]*}"
+}
+
+# char *VER_micro(string)
+#
+# Return the Micro (Z of X.Y.Z) version.
+#
+VER_micro() {
+ [[ -z $1 ]] && return 1
+
+ local VER=$@
+ VER=${VER#*.*.}
+ echo "${VER%%[^[:digit:]]*}"
+}
+
+# int VER_to_int(string)
+#
+# Convert a string type version (2.4.0) to an int (132096)
+# for easy compairing or versions ...
+#
+VER_to_int() {
+ [[ -z $1 ]] && return 1
+
+ local VER_MAJOR=$(VER_major "$1")
+ local VER_MINOR=$(VER_minor "$1")
+ local VER_MICRO=$(VER_micro "$1")
+ local VER_int=$(( VER_MAJOR * 65536 + VER_MINOR * 256 + VER_MICRO ))
+
+ # We make version 1.0.0 the minimum version we will handle as
+ # a sanity check ... if its less, we fail ...
+ if [[ ${VER_int} -ge 65536 ]] ; then
+ echo "${VER_int}"
+ return 0
+ fi
+
+ echo 1
+ return 1
+}
+
+fi
diff --git a/eclass/python-utils-r1.eclass b/eclass/python-utils-r1.eclass
new file mode 100644
index 0000000000..a67e378d39
--- /dev/null
+++ b/eclass/python-utils-r1.eclass
@@ -0,0 +1,1454 @@
+# Copyright 1999-2017 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: python-utils-r1.eclass
+# @MAINTAINER:
+# Python team <python@gentoo.org>
+# @AUTHOR:
+# Author: Michał Górny <mgorny@gentoo.org>
+# Based on work of: Krzysztof Pawlik <nelchael@gentoo.org>
+# @BLURB: Utility functions for packages with Python parts.
+# @DESCRIPTION:
+# A utility eclass providing functions to query Python implementations,
+# install Python modules and scripts.
+#
+# This eclass does not set any metadata variables nor export any phase
+# functions. It can be inherited safely.
+#
+# For more information, please see the wiki:
+# https://wiki.gentoo.org/wiki/Project:Python/python-utils-r1
+
+case "${EAPI:-0}" in
+ 0|1|2|3|4|5|6)
+ ;;
+ *)
+ die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
+ ;;
+esac
+
+if [[ ${_PYTHON_ECLASS_INHERITED} ]]; then
+ die 'python-r1 suite eclasses can not be used with python.eclass.'
+fi
+
+if [[ ! ${_PYTHON_UTILS_R1} ]]; then
+
+[[ ${EAPI:-0} == [012345] ]] && inherit eutils multilib
+inherit toolchain-funcs
+
+# @ECLASS-VARIABLE: _PYTHON_ALL_IMPLS
+# @INTERNAL
+# @DESCRIPTION:
+# All supported Python implementations, most preferred last.
+_PYTHON_ALL_IMPLS=(
+ jython2_7
+ pypy pypy3
+ python2_7
+ python3_4 python3_5 python3_6
+)
+readonly _PYTHON_ALL_IMPLS
+
+# @FUNCTION: _python_impl_supported
+# @USAGE: <impl>
+# @INTERNAL
+# @DESCRIPTION:
+# Check whether the implementation <impl> (PYTHON_COMPAT-form)
+# is still supported.
+#
+# Returns 0 if the implementation is valid and supported. If it is
+# unsupported, returns 1 -- and the caller should ignore the entry.
+# If it is invalid, dies with an appopriate error messages.
+_python_impl_supported() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ [[ ${#} -eq 1 ]] || die "${FUNCNAME}: takes exactly 1 argument (impl)."
+
+ local impl=${1}
+
+ # keep in sync with _PYTHON_ALL_IMPLS!
+ # (not using that list because inline patterns shall be faster)
+ case "${impl}" in
+ python2_7|python3_[456]|jython2_7)
+ return 0
+ ;;
+ pypy1_[89]|pypy2_0|python2_[56]|python3_[123])
+ return 1
+ ;;
+ pypy|pypy3)
+ if [[ ${EAPI:-0} == [01234] ]]; then
+ die "PyPy is supported in EAPI 5 and newer only."
+ fi
+ ;;
+ *)
+ die "Invalid implementation in PYTHON_COMPAT: ${impl}"
+ esac
+}
+
+# @FUNCTION: _python_set_impls
+# @INTERNAL
+# @DESCRIPTION:
+# Check PYTHON_COMPAT for well-formedness and validity, then set
+# two global variables:
+#
+# - _PYTHON_SUPPORTED_IMPLS containing valid implementations supported
+# by the ebuild (PYTHON_COMPAT - dead implementations),
+#
+# - and _PYTHON_UNSUPPORTED_IMPLS containing valid implementations that
+# are not supported by the ebuild.
+#
+# Implementations in both variables are ordered using the pre-defined
+# eclass implementation ordering.
+#
+# This function must be called once in global scope by an eclass
+# utilizing PYTHON_COMPAT.
+_python_set_impls() {
+ local i
+
+ if ! declare -p PYTHON_COMPAT &>/dev/null; then
+ die 'PYTHON_COMPAT not declared.'
+ fi
+ if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then
+ die 'PYTHON_COMPAT must be an array.'
+ fi
+ for i in "${PYTHON_COMPAT[@]}"; do
+ # trigger validity checks
+ _python_impl_supported "${i}"
+ done
+
+ local supp=() unsupp=()
+
+ for i in "${_PYTHON_ALL_IMPLS[@]}"; do
+ if has "${i}" "${PYTHON_COMPAT[@]}"; then
+ supp+=( "${i}" )
+ else
+ unsupp+=( "${i}" )
+ fi
+ done
+
+ if [[ ! ${supp[@]} ]]; then
+ die "No supported implementation in PYTHON_COMPAT."
+ fi
+
+ if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} ]]; then
+ # set once already, verify integrity
+ if [[ ${_PYTHON_SUPPORTED_IMPLS[@]} != ${supp[@]} ]]; then
+ eerror "Supported impls (PYTHON_COMPAT) changed between inherits!"
+ eerror "Before: ${_PYTHON_SUPPORTED_IMPLS[*]}"
+ eerror "Now : ${supp[*]}"
+ die "_PYTHON_SUPPORTED_IMPLS integrity check failed"
+ fi
+ if [[ ${_PYTHON_UNSUPPORTED_IMPLS[@]} != ${unsupp[@]} ]]; then
+ eerror "Unsupported impls changed between inherits!"
+ eerror "Before: ${_PYTHON_UNSUPPORTED_IMPLS[*]}"
+ eerror "Now : ${unsupp[*]}"
+ die "_PYTHON_UNSUPPORTED_IMPLS integrity check failed"
+ fi
+ else
+ _PYTHON_SUPPORTED_IMPLS=( "${supp[@]}" )
+ _PYTHON_UNSUPPORTED_IMPLS=( "${unsupp[@]}" )
+ readonly _PYTHON_SUPPORTED_IMPLS _PYTHON_UNSUPPORTED_IMPLS
+ fi
+}
+
+# @ECLASS-VARIABLE: PYTHON
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The absolute path to the current Python interpreter.
+#
+# This variable is set automatically in the following contexts:
+#
+# python-r1: Set in functions called by python_foreach_impl() or after
+# calling python_export_best().
+#
+# python-single-r1: Set after calling python-single-r1_pkg_setup().
+#
+# distutils-r1: Set within any of the python sub-phase functions.
+#
+# Example value:
+# @CODE
+# /usr/bin/python2.7
+# @CODE
+
+# @ECLASS-VARIABLE: EPYTHON
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The executable name of the current Python interpreter.
+#
+# This variable is set automatically in the following contexts:
+#
+# python-r1: Set in functions called by python_foreach_impl() or after
+# calling python_export_best().
+#
+# python-single-r1: Set after calling python-single-r1_pkg_setup().
+#
+# distutils-r1: Set within any of the python sub-phase functions.
+#
+# Example value:
+# @CODE
+# python2.7
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_SITEDIR
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The path to Python site-packages directory.
+#
+# Set and exported on request using python_export().
+# Requires a proper build-time dependency on the Python implementation.
+#
+# Example value:
+# @CODE
+# /usr/lib64/python2.7/site-packages
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_INCLUDEDIR
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The path to Python include directory.
+#
+# Set and exported on request using python_export().
+# Requires a proper build-time dependency on the Python implementation.
+#
+# Example value:
+# @CODE
+# /usr/include/python2.7
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_LIBPATH
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The path to Python library.
+#
+# Set and exported on request using python_export().
+# Valid only for CPython. Requires a proper build-time dependency
+# on the Python implementation.
+#
+# Example value:
+# @CODE
+# /usr/lib64/libpython2.7.so
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_CFLAGS
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Proper C compiler flags for building against Python. Obtained from
+# pkg-config or python-config.
+#
+# Set and exported on request using python_export().
+# Valid only for CPython. Requires a proper build-time dependency
+# on the Python implementation and on pkg-config.
+#
+# Example value:
+# @CODE
+# -I/usr/include/python2.7
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_LIBS
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Proper C compiler flags for linking against Python. Obtained from
+# pkg-config or python-config.
+#
+# Set and exported on request using python_export().
+# Valid only for CPython. Requires a proper build-time dependency
+# on the Python implementation and on pkg-config.
+#
+# Example value:
+# @CODE
+# -lpython2.7
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_CONFIG
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# Path to the python-config executable.
+#
+# Set and exported on request using python_export().
+# Valid only for CPython. Requires a proper build-time dependency
+# on the Python implementation and on pkg-config.
+#
+# Example value:
+# @CODE
+# /usr/bin/python2.7-config
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_PKG_DEP
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The complete dependency on a particular Python package as a string.
+#
+# Set and exported on request using python_export().
+#
+# Example value:
+# @CODE
+# dev-lang/python:2.7[xml]
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_SCRIPTDIR
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The location where Python scripts must be installed for current impl.
+#
+# Set and exported on request using python_export().
+#
+# Example value:
+# @CODE
+# /usr/lib/python-exec/python2.7
+# @CODE
+
+# @FUNCTION: python_export
+# @USAGE: [<impl>] <variables>...
+# @DESCRIPTION:
+# Set and export the Python implementation-relevant variables passed
+# as parameters.
+#
+# The optional first parameter may specify the requested Python
+# implementation (either as PYTHON_TARGETS value, e.g. python2_7,
+# or an EPYTHON one, e.g. python2.7). If no implementation passed,
+# the current one will be obtained from ${EPYTHON}.
+#
+# The variables which can be exported are: PYTHON, EPYTHON,
+# PYTHON_SITEDIR. They are described more completely in the eclass
+# variable documentation.
+python_export() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local impl var
+
+ case "${1}" in
+ python*|jython*)
+ impl=${1/_/.}
+ shift
+ ;;
+ pypy|pypy3)
+ impl=${1}
+ shift
+ ;;
+ *)
+ impl=${EPYTHON}
+ if [[ -z ${impl} ]]; then
+ die "python_export called without a python implementation and EPYTHON is unset"
+ fi
+ ;;
+ esac
+ debug-print "${FUNCNAME}: implementation: ${impl}"
+
+ for var; do
+ case "${var}" in
+ EPYTHON)
+ export EPYTHON=${impl}
+ debug-print "${FUNCNAME}: EPYTHON = ${EPYTHON}"
+ ;;
+ PYTHON)
+ export PYTHON=${EPREFIX}/usr/bin/${impl}
+ debug-print "${FUNCNAME}: PYTHON = ${PYTHON}"
+ ;;
+ PYTHON_SITEDIR)
+ [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
+ # sysconfig can't be used because:
+ # 1) pypy doesn't give site-packages but stdlib
+ # 2) jython gives paths with wrong case
+ PYTHON_SITEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_lib())') || die
+ export PYTHON_SITEDIR
+ debug-print "${FUNCNAME}: PYTHON_SITEDIR = ${PYTHON_SITEDIR}"
+ ;;
+ PYTHON_INCLUDEDIR)
+ [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
+ PYTHON_INCLUDEDIR=$("${PYTHON}" -c 'import distutils.sysconfig; print(distutils.sysconfig.get_python_inc())') || die
+ export PYTHON_INCLUDEDIR
+ debug-print "${FUNCNAME}: PYTHON_INCLUDEDIR = ${PYTHON_INCLUDEDIR}"
+
+ # Jython gives a non-existing directory
+ if [[ ! -d ${PYTHON_INCLUDEDIR} ]]; then
+ die "${impl} does not install any header files!"
+ fi
+ ;;
+ PYTHON_LIBPATH)
+ [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
+ PYTHON_LIBPATH=$("${PYTHON}" -c 'import os.path, sysconfig; print(os.path.join(sysconfig.get_config_var("LIBDIR"), sysconfig.get_config_var("LDLIBRARY")) if sysconfig.get_config_var("LDLIBRARY") else "")') || die
+ export PYTHON_LIBPATH
+ debug-print "${FUNCNAME}: PYTHON_LIBPATH = ${PYTHON_LIBPATH}"
+
+ if [[ ! ${PYTHON_LIBPATH} ]]; then
+ die "${impl} lacks a (usable) dynamic library"
+ fi
+ ;;
+ PYTHON_CFLAGS)
+ local val
+
+ case "${impl}" in
+ python*)
+ # python-2.7, python-3.2, etc.
+ val=$($(tc-getPKG_CONFIG) --cflags ${impl/n/n-}) || die
+ ;;
+ *)
+ die "${impl}: obtaining ${var} not supported"
+ ;;
+ esac
+
+ export PYTHON_CFLAGS=${val}
+ debug-print "${FUNCNAME}: PYTHON_CFLAGS = ${PYTHON_CFLAGS}"
+ ;;
+ PYTHON_LIBS)
+ local val
+
+ case "${impl}" in
+ python*)
+ # python-2.7, python-3.2, etc.
+ val=$($(tc-getPKG_CONFIG) --libs ${impl/n/n-}) || die
+ ;;
+ *)
+ die "${impl}: obtaining ${var} not supported"
+ ;;
+ esac
+
+ export PYTHON_LIBS=${val}
+ debug-print "${FUNCNAME}: PYTHON_LIBS = ${PYTHON_LIBS}"
+ ;;
+ PYTHON_CONFIG)
+ local flags val
+
+ case "${impl}" in
+ python*)
+ [[ -n ${PYTHON} ]] || die "PYTHON needs to be set for ${var} to be exported, or requested before it"
+ flags=$("${PYTHON}" -c 'import sysconfig; print(sysconfig.get_config_var("ABIFLAGS") or "")') || die
+ val=${PYTHON}${flags}-config
+ ;;
+ *)
+ die "${impl}: obtaining ${var} not supported"
+ ;;
+ esac
+
+ export PYTHON_CONFIG=${val}
+ debug-print "${FUNCNAME}: PYTHON_CONFIG = ${PYTHON_CONFIG}"
+ ;;
+ PYTHON_PKG_DEP)
+ local d
+ case ${impl} in
+ python2.7)
+ PYTHON_PKG_DEP='>=dev-lang/python-2.7.5-r2:2.7';;
+ python3.3)
+ PYTHON_PKG_DEP='>=dev-lang/python-3.3.2-r2:3.3';;
+ python*)
+ PYTHON_PKG_DEP="dev-lang/python:${impl#python}";;
+ pypy)
+ PYTHON_PKG_DEP='>=virtual/pypy-5:0=';;
+ pypy3)
+ PYTHON_PKG_DEP='>=virtual/pypy3-5:0=';;
+ jython2.7)
+ PYTHON_PKG_DEP='dev-java/jython:2.7';;
+ *)
+ die "Invalid implementation: ${impl}"
+ esac
+
+ # use-dep
+ if [[ ${PYTHON_REQ_USE} ]]; then
+ PYTHON_PKG_DEP+=[${PYTHON_REQ_USE}]
+ fi
+
+ export PYTHON_PKG_DEP
+ debug-print "${FUNCNAME}: PYTHON_PKG_DEP = ${PYTHON_PKG_DEP}"
+ ;;
+ PYTHON_SCRIPTDIR)
+ local dir
+ export PYTHON_SCRIPTDIR=${EPREFIX}/usr/lib/python-exec/${impl}
+ debug-print "${FUNCNAME}: PYTHON_SCRIPTDIR = ${PYTHON_SCRIPTDIR}"
+ ;;
+ *)
+ die "python_export: unknown variable ${var}"
+ esac
+ done
+}
+
+# @FUNCTION: python_get_sitedir
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the 'site-packages' path for the given
+# implementation. If no implementation is provided, ${EPYTHON} will
+# be used.
+#
+# If you just need to have PYTHON_SITEDIR set (and exported), then it is
+# better to use python_export() directly instead.
+python_get_sitedir() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ python_export "${@}" PYTHON_SITEDIR
+ echo "${PYTHON_SITEDIR}"
+}
+
+# @FUNCTION: python_get_includedir
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the include path for the given implementation. If no
+# implementation is provided, ${EPYTHON} will be used.
+#
+# If you just need to have PYTHON_INCLUDEDIR set (and exported), then it
+# is better to use python_export() directly instead.
+python_get_includedir() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ python_export "${@}" PYTHON_INCLUDEDIR
+ echo "${PYTHON_INCLUDEDIR}"
+}
+
+# @FUNCTION: python_get_library_path
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the Python library path for the given implementation.
+# If no implementation is provided, ${EPYTHON} will be used.
+#
+# Please note that this function can be used with CPython only. Use
+# in another implementation will result in a fatal failure.
+python_get_library_path() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ python_export "${@}" PYTHON_LIBPATH
+ echo "${PYTHON_LIBPATH}"
+}
+
+# @FUNCTION: python_get_CFLAGS
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the compiler flags for building against Python,
+# for the given implementation. If no implementation is provided,
+# ${EPYTHON} will be used.
+#
+# Please note that this function can be used with CPython only.
+# It requires Python and pkg-config installed, and therefore proper
+# build-time dependencies need be added to the ebuild.
+python_get_CFLAGS() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ python_export "${@}" PYTHON_CFLAGS
+ echo "${PYTHON_CFLAGS}"
+}
+
+# @FUNCTION: python_get_LIBS
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the compiler flags for linking against Python,
+# for the given implementation. If no implementation is provided,
+# ${EPYTHON} will be used.
+#
+# Please note that this function can be used with CPython only.
+# It requires Python and pkg-config installed, and therefore proper
+# build-time dependencies need be added to the ebuild.
+python_get_LIBS() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ python_export "${@}" PYTHON_LIBS
+ echo "${PYTHON_LIBS}"
+}
+
+# @FUNCTION: python_get_PYTHON_CONFIG
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the PYTHON_CONFIG location for the given
+# implementation. If no implementation is provided, ${EPYTHON} will be
+# used.
+#
+# Please note that this function can be used with CPython only.
+# It requires Python installed, and therefore proper build-time
+# dependencies need be added to the ebuild.
+python_get_PYTHON_CONFIG() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ python_export "${@}" PYTHON_CONFIG
+ echo "${PYTHON_CONFIG}"
+}
+
+# @FUNCTION: python_get_scriptdir
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Obtain and print the script install path for the given
+# implementation. If no implementation is provided, ${EPYTHON} will
+# be used.
+python_get_scriptdir() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ python_export "${@}" PYTHON_SCRIPTDIR
+ echo "${PYTHON_SCRIPTDIR}"
+}
+
+# @FUNCTION: _python_ln_rel
+# @USAGE: <from> <to>
+# @INTERNAL
+# @DESCRIPTION:
+# Create a relative symlink.
+_python_ln_rel() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local target=${1}
+ local symname=${2}
+
+ local tgpath=${target%/*}/
+ local sympath=${symname%/*}/
+ local rel_target=
+
+ while [[ ${sympath} ]]; do
+ local tgseg= symseg=
+
+ while [[ ! ${tgseg} && ${tgpath} ]]; do
+ tgseg=${tgpath%%/*}
+ tgpath=${tgpath#${tgseg}/}
+ done
+
+ while [[ ! ${symseg} && ${sympath} ]]; do
+ symseg=${sympath%%/*}
+ sympath=${sympath#${symseg}/}
+ done
+
+ if [[ ${tgseg} != ${symseg} ]]; then
+ rel_target=../${rel_target}${tgseg:+${tgseg}/}
+ fi
+ done
+ rel_target+=${tgpath}${target##*/}
+
+ debug-print "${FUNCNAME}: ${symname} -> ${target}"
+ debug-print "${FUNCNAME}: rel_target = ${rel_target}"
+
+ ln -fs "${rel_target}" "${symname}"
+}
+
+# @FUNCTION: python_optimize
+# @USAGE: [<directory>...]
+# @DESCRIPTION:
+# Compile and optimize Python modules in specified directories (absolute
+# paths). If no directories are provided, the default system paths
+# are used (prepended with ${D}).
+python_optimize() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ if [[ ${EBUILD_PHASE} == pre* || ${EBUILD_PHASE} == post* ]]; then
+ eerror "The new Python eclasses expect the compiled Python files to"
+ eerror "be controlled by the Package Manager. For this reason,"
+ eerror "the python_optimize function can be used only during src_* phases"
+ eerror "(src_install most commonly) and not during pkg_* phases."
+ echo
+ die "python_optimize is not to be used in pre/post* phases"
+ fi
+
+ [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
+
+ local PYTHON=${PYTHON}
+ [[ ${PYTHON} ]] || python_export PYTHON
+
+ # default to sys.path
+ if [[ ${#} -eq 0 ]]; then
+ local f
+ while IFS= read -r -d '' f; do
+ # 1) accept only absolute paths
+ # (i.e. skip '', '.' or anything like that)
+ # 2) skip paths which do not exist
+ # (python2.6 complains about them verbosely)
+
+ if [[ ${f} == /* && -d ${D}${f} ]]; then
+ set -- "${D}${f}" "${@}"
+ fi
+ done < <("${PYTHON}" -c 'import sys; print("\0".join(sys.path))' || die)
+
+ debug-print "${FUNCNAME}: using sys.path: ${*/%/;}"
+ fi
+
+ local d
+ for d; do
+ # make sure to get a nice path without //
+ local instpath=${d#${D}}
+ instpath=/${instpath##/}
+
+ case "${EPYTHON}" in
+ python2.7|python3.[34])
+ "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
+ "${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
+ ;;
+ python*)
+ # both levels of optimization are separate since 3.5
+ "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
+ "${PYTHON}" -O -m compileall -q -f -d "${instpath}" "${d}"
+ "${PYTHON}" -OO -m compileall -q -f -d "${instpath}" "${d}"
+ ;;
+ *)
+ "${PYTHON}" -m compileall -q -f -d "${instpath}" "${d}"
+ ;;
+ esac
+ done
+}
+
+# @FUNCTION: python_scriptinto
+# @USAGE: <new-path>
+# @DESCRIPTION:
+# Set the directory to which files passed to python_doexe(),
+# python_doscript(), python_newexe() and python_newscript()
+# are going to be installed. The new value needs to be relative
+# to the installation root (${ED}).
+#
+# If not set explicitly, the directory defaults to /usr/bin.
+#
+# Example:
+# @CODE
+# src_install() {
+# python_scriptinto /usr/sbin
+# python_foreach_impl python_doscript foo
+# }
+# @CODE
+python_scriptinto() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ python_scriptroot=${1}
+}
+
+# @FUNCTION: python_doexe
+# @USAGE: <files>...
+# @DESCRIPTION:
+# Install the given executables into the executable install directory,
+# for the current Python implementation (${EPYTHON}).
+#
+# The executable will be wrapped properly for the Python implementation,
+# though no shebang mangling will be performed.
+python_doexe() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local f
+ for f; do
+ python_newexe "${f}" "${f##*/}"
+ done
+}
+
+# @FUNCTION: python_newexe
+# @USAGE: <path> <new-name>
+# @DESCRIPTION:
+# Install the given executable into the executable install directory,
+# for the current Python implementation (${EPYTHON}).
+#
+# The executable will be wrapped properly for the Python implementation,
+# though no shebang mangling will be performed. It will be renamed
+# to <new-name>.
+python_newexe() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
+ [[ ${#} -eq 2 ]] || die "Usage: ${FUNCNAME} <path> <new-name>"
+ if [[ ${EAPI:-0} == [0123] ]]; then
+ die "python_do* and python_new* helpers are banned in EAPIs older than 4."
+ fi
+
+ local wrapd=${python_scriptroot:-/usr/bin}
+
+ local f=${1}
+ local newfn=${2}
+
+ local PYTHON_SCRIPTDIR d
+ python_export PYTHON_SCRIPTDIR
+ d=${PYTHON_SCRIPTDIR#${EPREFIX}}
+
+ (
+ dodir "${wrapd}"
+ exeinto "${d}"
+ newexe "${f}" "${newfn}" || return ${?}
+ )
+
+ # install the wrapper
+ _python_ln_rel "${ED%/}"/usr/lib/python-exec/python-exec2 \
+ "${ED%/}/${wrapd}/${newfn}" || die
+
+ # don't use this at home, just call python_doscript() instead
+ if [[ ${_PYTHON_REWRITE_SHEBANG} ]]; then
+ python_fix_shebang -q "${ED%/}/${d}/${newfn}"
+ fi
+}
+
+# @FUNCTION: python_doscript
+# @USAGE: <files>...
+# @DESCRIPTION:
+# Install the given scripts into the executable install directory,
+# for the current Python implementation (${EPYTHON}).
+#
+# All specified files must start with a 'python' shebang. The shebang
+# will be converted, and the files will be wrapped properly
+# for the Python implementation.
+#
+# Example:
+# @CODE
+# src_install() {
+# python_foreach_impl python_doscript ${PN}
+# }
+# @CODE
+python_doscript() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local _PYTHON_REWRITE_SHEBANG=1
+ python_doexe "${@}"
+}
+
+# @FUNCTION: python_newscript
+# @USAGE: <path> <new-name>
+# @DESCRIPTION:
+# Install the given script into the executable install directory
+# for the current Python implementation (${EPYTHON}), and name it
+# <new-name>.
+#
+# The file must start with a 'python' shebang. The shebang will be
+# converted, and the file will be wrapped properly for the Python
+# implementation. It will be renamed to <new-name>.
+#
+# Example:
+# @CODE
+# src_install() {
+# python_foreach_impl python_newscript foo.py foo
+# }
+# @CODE
+python_newscript() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local _PYTHON_REWRITE_SHEBANG=1
+ python_newexe "${@}"
+}
+
+# @FUNCTION: python_moduleinto
+# @USAGE: <new-path>
+# @DESCRIPTION:
+# Set the Python module install directory for python_domodule().
+# The <new-path> can either be an absolute target system path (in which
+# case it needs to start with a slash, and ${ED} will be prepended to
+# it) or relative to the implementation's site-packages directory
+# (then it must not start with a slash).
+#
+# When not set explicitly, the modules are installed to the top
+# site-packages directory.
+#
+# Example:
+# @CODE
+# src_install() {
+# python_moduleinto bar
+# # installs ${PYTHON_SITEDIR}/bar/baz.py
+# python_foreach_impl python_domodule baz.py
+# }
+# @CODE
+
+# Set the current module root. The new value will be stored
+# in the 'python_moduleroot' environment variable. The new value need
+# be relative to the site-packages root.
+#
+# Alternatively, you can set the variable directly.
+python_moduleinto() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ python_moduleroot=${1}
+}
+
+# @FUNCTION: python_domodule
+# @USAGE: <files>...
+# @DESCRIPTION:
+# Install the given modules (or packages) into the current Python module
+# installation directory. The list can mention both modules (files)
+# and packages (directories). All listed files will be installed
+# for all enabled implementations, and compiled afterwards.
+#
+# Example:
+# @CODE
+# src_install() {
+# # (${PN} being a directory)
+# python_foreach_impl python_domodule ${PN}
+# }
+# @CODE
+python_domodule() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
+ if [[ ${EAPI:-0} == [0123] ]]; then
+ die "python_do* and python_new* helpers are banned in EAPIs older than 4."
+ fi
+
+ local d
+ if [[ ${python_moduleroot} == /* ]]; then
+ # absolute path
+ d=${python_moduleroot}
+ else
+ # relative to site-packages
+ local PYTHON_SITEDIR=${PYTHON_SITEDIR}
+ [[ ${PYTHON_SITEDIR} ]] || python_export PYTHON_SITEDIR
+
+ d=${PYTHON_SITEDIR#${EPREFIX}}/${python_moduleroot}
+ fi
+
+ (
+ insinto "${d}"
+ doins -r "${@}" || return ${?}
+ )
+
+ python_optimize "${ED}/${d}"
+}
+
+# @FUNCTION: python_doheader
+# @USAGE: <files>...
+# @DESCRIPTION:
+# Install the given headers into the implementation-specific include
+# directory. This function is unconditionally recursive, i.e. you can
+# pass directories instead of files.
+#
+# Example:
+# @CODE
+# src_install() {
+# python_foreach_impl python_doheader foo.h bar.h
+# }
+# @CODE
+python_doheader() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ [[ ${EPYTHON} ]] || die 'No Python implementation set (EPYTHON is null).'
+ if [[ ${EAPI:-0} == [0123] ]]; then
+ die "python_do* and python_new* helpers are banned in EAPIs older than 4."
+ fi
+
+ local d PYTHON_INCLUDEDIR=${PYTHON_INCLUDEDIR}
+ [[ ${PYTHON_INCLUDEDIR} ]] || python_export PYTHON_INCLUDEDIR
+
+ d=${PYTHON_INCLUDEDIR#${EPREFIX}}
+
+ (
+ insinto "${d}"
+ doins -r "${@}" || return ${?}
+ )
+}
+
+# @FUNCTION: python_wrapper_setup
+# @USAGE: [<path> [<impl>]]
+# @DESCRIPTION:
+# Create proper 'python' executable and pkg-config wrappers
+# (if available) in the directory named by <path>. Set up PATH
+# and PKG_CONFIG_PATH appropriately. <path> defaults to ${T}/${EPYTHON}.
+#
+# The wrappers will be created for implementation named by <impl>,
+# or for one named by ${EPYTHON} if no <impl> passed.
+#
+# If the named directory contains a python symlink already, it will
+# be assumed to contain proper wrappers already and only environment
+# setup will be done. If wrapper update is requested, the directory
+# shall be removed first.
+python_wrapper_setup() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local workdir=${1:-${T}/${EPYTHON}}
+ local impl=${2:-${EPYTHON}}
+
+ [[ ${workdir} ]] || die "${FUNCNAME}: no workdir specified."
+ [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON specified."
+
+ if [[ ! -x ${workdir}/bin/python ]]; then
+ _python_check_dead_variables
+
+ mkdir -p "${workdir}"/{bin,pkgconfig} || die
+
+ # Clean up, in case we were supposed to do a cheap update.
+ rm -f "${workdir}"/bin/python{,2,3}{,-config} || die
+ rm -f "${workdir}"/bin/2to3 || die
+ rm -f "${workdir}"/pkgconfig/python{,2,3}.pc || die
+
+ local EPYTHON PYTHON PYTHON_CONFIG
+ python_export "${impl}" EPYTHON PYTHON
+
+ local pyver pyother
+ if python_is_python3; then
+ pyver=3
+ pyother=2
+ else
+ pyver=2
+ pyother=3
+ fi
+
+ # Python interpreter
+ # note: we don't use symlinks because python likes to do some
+ # symlink reading magic that breaks stuff
+ # https://bugs.gentoo.org/show_bug.cgi?id=555752
+ cat > "${workdir}/bin/python" <<-_EOF_ || die
+ #!/bin/sh
+ exec "${PYTHON}" "\${@}"
+ _EOF_
+ cp "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
+ chmod +x "${workdir}/bin/python" "${workdir}/bin/python${pyver}" || die
+
+ local nonsupp=( "python${pyother}" "python${pyother}-config" )
+
+ # CPython-specific
+ if [[ ${EPYTHON} == python* ]]; then
+ python_export "${impl}" PYTHON_CONFIG
+
+ cat > "${workdir}/bin/python-config" <<-_EOF_ || die
+ #!/bin/sh
+ exec "${PYTHON_CONFIG}" "\${@}"
+ _EOF_
+ cp "${workdir}/bin/python-config" \
+ "${workdir}/bin/python${pyver}-config" || die
+ chmod +x "${workdir}/bin/python-config" \
+ "${workdir}/bin/python${pyver}-config" || die
+
+ # Python 2.6+.
+ ln -s "${PYTHON/python/2to3-}" "${workdir}"/bin/2to3 || die
+
+ # Python 2.7+.
+ ln -s "${EPREFIX}"/usr/$(get_libdir)/pkgconfig/${EPYTHON/n/n-}.pc \
+ "${workdir}"/pkgconfig/python.pc || die
+ ln -s python.pc "${workdir}"/pkgconfig/python${pyver}.pc || die
+ else
+ nonsupp+=( 2to3 python-config "python${pyver}-config" )
+ fi
+
+ local x
+ for x in "${nonsupp[@]}"; do
+ cat >"${workdir}"/bin/${x} <<-_EOF_ || die
+ #!/bin/sh
+ echo "${x} is not supported by ${EPYTHON}" >&2
+ exit 127
+ _EOF_
+ chmod +x "${workdir}"/bin/${x} || die
+ done
+ fi
+
+ # Now, set the environment.
+ # But note that ${workdir} may be shared with something else,
+ # and thus already on top of PATH.
+ if [[ ${PATH##:*} != ${workdir}/bin ]]; then
+ PATH=${workdir}/bin${PATH:+:${PATH}}
+ fi
+ if [[ ${PKG_CONFIG_PATH##:*} != ${workdir}/pkgconfig ]]; then
+ PKG_CONFIG_PATH=${workdir}/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}
+ fi
+ export PATH PKG_CONFIG_PATH
+}
+
+# @FUNCTION: python_is_python3
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Check whether <impl> (or ${EPYTHON}) is a Python3k variant
+# (i.e. uses syntax and stdlib of Python 3.*).
+#
+# Returns 0 (true) if it is, 1 (false) otherwise.
+python_is_python3() {
+ local impl=${1:-${EPYTHON}}
+ [[ ${impl} ]] || die "python_is_python3: no impl nor EPYTHON"
+
+ [[ ${impl} == python3* || ${impl} == pypy3 ]]
+}
+
+# @FUNCTION: python_is_installed
+# @USAGE: [<impl>]
+# @DESCRIPTION:
+# Check whether the interpreter for <impl> (or ${EPYTHON}) is installed.
+# Uses has_version with a proper dependency string.
+#
+# Returns 0 (true) if it is, 1 (false) otherwise.
+python_is_installed() {
+ local impl=${1:-${EPYTHON}}
+ [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EPYTHON"
+
+ # for has_version
+ local -x ROOT=/
+ case "${impl}" in
+ pypy|pypy3)
+ local append=
+ if [[ ${PYTHON_REQ_USE} ]]; then
+ append=[${PYTHON_REQ_USE}]
+ fi
+
+ # be happy with just the interpeter, no need for the virtual
+ has_version "dev-python/${impl}${append}" \
+ || has_version "dev-python/${impl}-bin${append}"
+ ;;
+ *)
+ local PYTHON_PKG_DEP
+ python_export "${impl}" PYTHON_PKG_DEP
+ has_version "${PYTHON_PKG_DEP}"
+ ;;
+ esac
+}
+
+# @FUNCTION: python_fix_shebang
+# @USAGE: [-f|--force] [-q|--quiet] <path>...
+# @DESCRIPTION:
+# Replace the shebang in Python scripts with the current Python
+# implementation (EPYTHON). If a directory is passed, works recursively
+# on all Python scripts.
+#
+# Only files having a 'python*' shebang will be modified. Files with
+# other shebang will either be skipped when working recursively
+# on a directory or treated as error when specified explicitly.
+#
+# Shebangs matching explicitly current Python version will be left
+# unmodified. Shebangs requesting another Python version will be treated
+# as fatal error, unless --force is given.
+#
+# --force causes the function to replace even shebangs that require
+# incompatible Python version. --quiet causes the function not to list
+# modified files verbosely.
+python_fix_shebang() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ [[ ${EPYTHON} ]] || die "${FUNCNAME}: EPYTHON unset (pkg_setup not called?)"
+
+ local force quiet
+ while [[ ${@} ]]; do
+ case "${1}" in
+ -f|--force) force=1; shift;;
+ -q|--quiet) quiet=1; shift;;
+ --) shift; break;;
+ *) break;;
+ esac
+ done
+
+ [[ ${1} ]] || die "${FUNCNAME}: no paths given"
+
+ local path f
+ for path; do
+ local any_correct any_fixed is_recursive
+
+ [[ -d ${path} ]] && is_recursive=1
+
+ while IFS= read -r -d '' f; do
+ local shebang i
+ local error= from=
+
+ # note: we can't ||die here since read will fail if file
+ # has no newline characters
+ IFS= read -r shebang <"${f}"
+
+ # First, check if it's shebang at all...
+ if [[ ${shebang} == '#!'* ]]; then
+ local split_shebang=()
+ read -r -a split_shebang <<<${shebang} || die
+
+ # Match left-to-right in a loop, to avoid matching random
+ # repetitions like 'python2.7 python2'.
+ for i in "${split_shebang[@]}"; do
+ case "${i}" in
+ *"${EPYTHON}")
+ debug-print "${FUNCNAME}: in file ${f#${D}}"
+ debug-print "${FUNCNAME}: shebang matches EPYTHON: ${shebang}"
+
+ # Nothing to do, move along.
+ any_correct=1
+ from=${EPYTHON}
+ break
+ ;;
+ *python|*python[23])
+ debug-print "${FUNCNAME}: in file ${f#${D}}"
+ debug-print "${FUNCNAME}: rewriting shebang: ${shebang}"
+
+ if [[ ${i} == *python2 ]]; then
+ from=python2
+ if [[ ! ${force} ]]; then
+ python_is_python3 "${EPYTHON}" && error=1
+ fi
+ elif [[ ${i} == *python3 ]]; then
+ from=python3
+ if [[ ! ${force} ]]; then
+ python_is_python3 "${EPYTHON}" || error=1
+ fi
+ else
+ from=python
+ fi
+ break
+ ;;
+ *python[23].[0123456789]|*pypy|*pypy3|*jython[23].[0123456789])
+ # Explicit mismatch.
+ if [[ ! ${force} ]]; then
+ error=1
+ else
+ case "${i}" in
+ *python[23].[0123456789])
+ from="python[23].[0123456789]";;
+ *pypy)
+ from="pypy";;
+ *pypy3)
+ from="pypy3";;
+ *jython[23].[0123456789])
+ from="jython[23].[0123456789]";;
+ *)
+ die "${FUNCNAME}: internal error in 2nd pattern match";;
+ esac
+ fi
+ break
+ ;;
+ esac
+ done
+ fi
+
+ if [[ ! ${error} && ! ${from} ]]; then
+ # Non-Python shebang. Allowed in recursive mode,
+ # disallowed when specifying file explicitly.
+ [[ ${is_recursive} ]] && continue
+ error=1
+ fi
+
+ if [[ ! ${quiet} ]]; then
+ einfo "Fixing shebang in ${f#${D}}."
+ fi
+
+ if [[ ! ${error} ]]; then
+ # We either want to match ${from} followed by space
+ # or at end-of-string.
+ if [[ ${shebang} == *${from}" "* ]]; then
+ sed -i -e "1s:${from} :${EPYTHON} :" "${f}" || die
+ else
+ sed -i -e "1s:${from}$:${EPYTHON}:" "${f}" || die
+ fi
+ any_fixed=1
+ else
+ eerror "The file has incompatible shebang:"
+ eerror " file: ${f#${D}}"
+ eerror " current shebang: ${shebang}"
+ eerror " requested impl: ${EPYTHON}"
+ die "${FUNCNAME}: conversion of incompatible shebang requested"
+ fi
+ done < <(find -H "${path}" -type f -print0 || die)
+
+ if [[ ! ${any_fixed} ]]; then
+ local cmd=eerror
+ [[ ${EAPI:-0} == [012345] ]] && cmd=eqawarn
+
+ "${cmd}" "QA warning: ${FUNCNAME}, ${path#${D}} did not match any fixable files."
+ if [[ ${any_correct} ]]; then
+ "${cmd}" "All files have ${EPYTHON} shebang already."
+ else
+ "${cmd}" "There are no Python files in specified directory."
+ fi
+
+ [[ ${cmd} == eerror ]] && die "${FUNCNAME} did not match any fixable files (QA warning fatal in EAPI ${EAPI})"
+ fi
+ done
+}
+
+# @FUNCTION: _python_check_locale_sanity
+# @USAGE: <locale>
+# @RETURN: 0 if sane, 1 otherwise
+# @DESCRIPTION:
+# Check whether the specified locale sanely maps between lowercase
+# and uppercase ASCII characters.
+_python_check_locale_sanity() {
+ local -x LC_ALL=${1}
+ local IFS=
+
+ local lc=( {a..z} )
+ local uc=( {A..Z} )
+ local input="${lc[*]}${uc[*]}"
+
+ local output=$(tr '[:lower:][:upper:]' '[:upper:][:lower:]' <<<"${input}")
+ [[ ${output} == "${uc[*]}${lc[*]}" ]]
+}
+
+# @FUNCTION: python_export_utf8_locale
+# @RETURN: 0 on success, 1 on failure.
+# @DESCRIPTION:
+# Attempts to export a usable UTF-8 locale in the LC_CTYPE variable. Does
+# nothing if LC_ALL is defined, or if the current locale uses a UTF-8 charmap.
+# This may be used to work around the quirky open() behavior of python3.
+python_export_utf8_locale() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ # If the locale program isn't available, just return.
+ type locale >/dev/null || return 0
+
+ if [[ $(locale charmap) != UTF-8 ]]; then
+ # Try English first, then everything else.
+ local lang locales="C.UTF-8 en_US.UTF-8 en_GB.UTF-8 $(locale -a)"
+
+ for lang in ${locales}; do
+ if [[ $(LC_ALL=${lang} locale charmap 2>/dev/null) == UTF-8 ]]; then
+ if _python_check_locale_sanity "${lang}"; then
+ export LC_CTYPE=${lang}
+ if [[ -n ${LC_ALL} ]]; then
+ export LC_NUMERIC=${LC_ALL}
+ export LC_TIME=${LC_ALL}
+ export LC_COLLATE=${LC_ALL}
+ export LC_MONETARY=${LC_ALL}
+ export LC_MESSAGES=${LC_ALL}
+ export LC_PAPER=${LC_ALL}
+ export LC_NAME=${LC_ALL}
+ export LC_ADDRESS=${LC_ALL}
+ export LC_TELEPHONE=${LC_ALL}
+ export LC_MEASUREMENT=${LC_ALL}
+ export LC_IDENTIFICATION=${LC_ALL}
+ export LC_ALL=
+ fi
+ return 0
+ fi
+ fi
+ done
+
+ ewarn "Could not find a UTF-8 locale. This may trigger build failures in"
+ ewarn "some python packages. Please ensure that a UTF-8 locale is listed in"
+ ewarn "/etc/locale.gen and run locale-gen."
+ return 1
+ fi
+
+ return 0
+}
+
+# -- python.eclass functions --
+
+_python_check_dead_variables() {
+ local v
+
+ for v in PYTHON_DEPEND PYTHON_USE_WITH{,_OR,_OPT} {RESTRICT,SUPPORT}_PYTHON_ABIS
+ do
+ if [[ ${!v} ]]; then
+ die "${v} is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Ebuild_head"
+ fi
+ done
+
+ for v in PYTHON_{CPPFLAGS,CFLAGS,CXXFLAGS,LDFLAGS}
+ do
+ if [[ ${!v} ]]; then
+ die "${v} is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#PYTHON_CFLAGS"
+ fi
+ done
+
+ for v in PYTHON_TESTS_RESTRICTED_ABIS PYTHON_EXPORT_PHASE_FUNCTIONS \
+ PYTHON_VERSIONED_{SCRIPTS,EXECUTABLES} PYTHON_NONVERSIONED_EXECUTABLES
+ do
+ if [[ ${!v} ]]; then
+ die "${v} is invalid for python-r1 suite"
+ fi
+ done
+
+ for v in DISTUTILS_USE_SEPARATE_SOURCE_DIRECTORIES DISTUTILS_SETUP_FILES \
+ DISTUTILS_GLOBAL_OPTIONS DISTUTILS_SRC_TEST PYTHON_MODNAME
+ do
+ if [[ ${!v} ]]; then
+ die "${v} is invalid for distutils-r1, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#${v}"
+ fi
+ done
+
+ if [[ ${DISTUTILS_DISABLE_TEST_DEPENDENCY} ]]; then
+ die "${v} is invalid for distutils-r1, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#DISTUTILS_SRC_TEST"
+ fi
+
+ # python.eclass::progress
+ for v in PYTHON_BDEPEND PYTHON_MULTIPLE_ABIS PYTHON_ABI_TYPE \
+ PYTHON_RESTRICTED_ABIS PYTHON_TESTS_FAILURES_TOLERANT_ABIS \
+ PYTHON_CFFI_MODULES_GENERATION_COMMANDS
+ do
+ if [[ ${!v} ]]; then
+ die "${v} is invalid for python-r1 suite"
+ fi
+ done
+}
+
+python_pkg_setup() {
+ die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
+}
+
+python_convert_shebangs() {
+ die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_convert_shebangs"
+}
+
+python_clean_py-compile_files() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_clean_installation_image() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_execute_function() {
+ die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#python_execute_function"
+}
+
+python_generate_wrapper_scripts() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_merge_intermediate_installation_images() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_set_active_version() {
+ die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#pkg_setup"
+}
+
+python_need_rebuild() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+PYTHON() {
+ die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#.24.28PYTHON.29.2C_.24.7BEPYTHON.7D"
+}
+
+python_get_implementation() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_get_implementational_package() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_get_libdir() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_get_library() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_get_version() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_get_implementation_and_version() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_execute_nosetests() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_execute_py.test() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_execute_trial() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_enable_pyc() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_disable_pyc() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_mod_optimize() {
+ die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation"
+}
+
+python_mod_cleanup() {
+ die "${FUNCNAME}() is invalid for python-r1 suite, please take a look @ https://wiki.gentoo.org/wiki/Project:Python/Python.eclass_conversion#Python_byte-code_compilation"
+}
+
+# python.eclass::progress
+
+python_abi_depend() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_install_executables() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_get_extension_module_suffix() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_byte-compile_modules() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_clean_byte-compiled_modules() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+python_generate_cffi_modules() {
+ die "${FUNCNAME}() is invalid for python-r1 suite"
+}
+
+_PYTHON_UTILS_R1=1
+fi