summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'eclass/python-single-r1.eclass')
-rw-r--r--eclass/python-single-r1.eclass468
1 files changed, 468 insertions, 0 deletions
diff --git a/eclass/python-single-r1.eclass b/eclass/python-single-r1.eclass
new file mode 100644
index 000000000000..0f21fb7e354b
--- /dev/null
+++ b/eclass/python-single-r1.eclass
@@ -0,0 +1,468 @@
+# Copyright 1999-2015 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+# @ECLASS: python-single-r1
+# @MAINTAINER:
+# Python team <python@gentoo.org>
+# @AUTHOR:
+# Author: Michał Górny <mgorny@gentoo.org>
+# Based on work of: Krzysztof Pawlik <nelchael@gentoo.org>
+# @BLURB: An eclass for Python packages not installed for multiple implementations.
+# @DESCRIPTION:
+# An extension of the python-r1 eclass suite for packages which
+# don't support being installed for multiple Python implementations.
+# This mostly includes tools embedding Python.
+#
+# This eclass extends the IUSE and REQUIRED_USE set by python-r1
+# to request the PYTHON_SINGLE_TARGET when the inheriting ebuild
+# can be supported by more than one Python implementation. It also
+# replaces PYTHON_USEDEP and PYTHON_DEPS with a more suitable form.
+#
+# Please note that packages support multiple Python implementations
+# (using python-r1 eclass) can not depend on packages not supporting
+# them (using this eclass).
+#
+# Please note that python-single-r1 will always inherit python-utils-r1
+# as well. Thus, all the functions defined there can be used
+# in the packages using python-single-r1, and there is no need ever
+# to inherit both.
+#
+# For more information, please see the wiki:
+# https://wiki.gentoo.org/wiki/Project:Python/python-single-r1
+
+case "${EAPI:-0}" in
+ 0|1|2|3)
+ die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
+ ;;
+ 4)
+ # EAPI=4 is only allowed on legacy packages
+ if [[ ${CATEGORY}/${P} == app-arch/threadzip-1.2 ]]; then
+ :
+ elif [[ ${CATEGORY}/${P} == media-libs/lv2-1.8.0 ]]; then
+ :
+ elif [[ ${CATEGORY}/${P} == media-libs/lv2-1.10.0 ]]; then
+ :
+ elif [[ ${CATEGORY}/${P} == sys-apps/paludis-1* ]]; then
+ :
+ elif [[ ${CATEGORY}/${P} == sys-apps/paludis-2.[02].0 ]]; then
+ :
+ elif [[ ${CATEGORY}/${P} == sys-apps/util-linux-2.2[456]* ]]; then
+ :
+ elif [[ ${CATEGORY}/${P} == */gdb-7.[78]* ]]; then
+ :
+ else
+ die "Unsupported EAPI=${EAPI:-4} (too old, allowed only on restricted set of packages) for ${ECLASS}"
+ fi
+ ;;
+ 5)
+ # EAPI=5 is required for sane USE_EXPAND dependencies
+ ;;
+ *)
+ die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
+ ;;
+esac
+
+if [[ ! ${_PYTHON_SINGLE_R1} ]]; then
+
+if [[ ${_PYTHON_R1} ]]; then
+ die 'python-single-r1.eclass can not be used with python-r1.eclass.'
+elif [[ ${_PYTHON_ANY_R1} ]]; then
+ die 'python-single-r1.eclass can not be used with python-any-r1.eclass.'
+fi
+
+inherit python-utils-r1
+
+fi
+
+EXPORT_FUNCTIONS pkg_setup
+
+if [[ ! ${_PYTHON_SINGLE_R1} ]]; then
+
+# @ECLASS-VARIABLE: PYTHON_COMPAT
+# @REQUIRED
+# @DESCRIPTION:
+# This variable contains a list of Python implementations the package
+# supports. It must be set before the `inherit' call. It has to be
+# an array.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_5,2_6,2_7} )
+# @CODE
+if ! declare -p PYTHON_COMPAT &>/dev/null; then
+ die 'PYTHON_COMPAT not declared.'
+fi
+
+# @ECLASS-VARIABLE: PYTHON_REQ_USE
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# The list of USEflags required to be enabled on the chosen Python
+# implementations, formed as a USE-dependency string. It should be valid
+# for all implementations in PYTHON_COMPAT, so it may be necessary to
+# use USE defaults.
+#
+# This should be set before calling `inherit'.
+#
+# Example:
+# @CODE
+# PYTHON_REQ_USE="gdbm,ncurses(-)?"
+# @CODE
+#
+# It will cause the Python dependencies to look like:
+# @CODE
+# python_single_target_pythonX_Y? ( dev-lang/python:X.Y[gdbm,ncurses(-)?] )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_DEPS
+# @DESCRIPTION:
+# This is an eclass-generated Python dependency string for all
+# implementations listed in PYTHON_COMPAT.
+#
+# The dependency string is conditional on PYTHON_SINGLE_TARGET.
+#
+# Example use:
+# @CODE
+# RDEPEND="${PYTHON_DEPS}
+# dev-foo/mydep"
+# DEPEND="${RDEPEND}"
+# @CODE
+#
+# Example value:
+# @CODE
+# dev-lang/python-exec:=
+# python_single_target_python2_6? ( dev-lang/python:2.6[gdbm] )
+# python_single_target_python2_7? ( dev-lang/python:2.7[gdbm] )
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_USEDEP
+# @DESCRIPTION:
+# This is an eclass-generated USE-dependency string which can be used to
+# depend on another Python package being built for the same Python
+# implementations.
+#
+# The generate USE-flag list is compatible with packages using python-r1,
+# python-single-r1 and python-distutils-ng eclasses. It must not be used
+# on packages using python.eclass.
+#
+# Example use:
+# @CODE
+# RDEPEND="dev-python/foo[${PYTHON_USEDEP}]"
+# @CODE
+#
+# Example value:
+# @CODE
+# python_targets_python2_7(-)?,python_single_target_python2_7(+)?
+# @CODE
+
+# @ECLASS-VARIABLE: PYTHON_REQUIRED_USE
+# @DESCRIPTION:
+# This is an eclass-generated required-use expression which ensures the following
+# when more than one python implementation is possible:
+# 1. Exactly one PYTHON_SINGLE_TARGET value has been enabled.
+# 2. The selected PYTHON_SINGLE_TARGET value is enabled in PYTHON_TARGETS.
+#
+# This expression should be utilized in an ebuild by including it in
+# REQUIRED_USE, optionally behind a use flag.
+#
+# Example use:
+# @CODE
+# REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
+# @CODE
+#
+# Example value:
+# @CODE
+# python_single_target_python2_6? ( python_targets_python2_6 )
+# python_single_target_python2_7? ( python_targets_python2_7 )
+# ^^ ( python_single_target_python2_6 python_single_target_python2_7 )
+# @CODE
+
+_python_single_set_globals() {
+ local impls=()
+ local unimpls=()
+
+ PYTHON_DEPS=
+ local i PYTHON_PKG_DEP
+ for i in "${_PYTHON_ALL_IMPLS[@]}"; do
+ has "${i}" "${PYTHON_COMPAT[@]}" \
+ && impls+=( "${i}" ) \
+ || unimpls+=( "${i}" )
+ done
+
+ if [[ ${#impls[@]} -eq 0 ]]; then
+ die "No supported implementation in PYTHON_COMPAT."
+ fi
+
+ local flags_mt=( "${impls[@]/#/python_targets_}" )
+ local flags=( "${impls[@]/#/python_single_target_}" )
+ local unflags=( "${unimpls[@]/#/-python_single_target_}" )
+
+ local optflags=${flags_mt[@]/%/(-)?},${unflags[@]/%/(-)}
+
+ IUSE="${flags_mt[*]}"
+
+ if [[ ${#impls[@]} -eq 1 ]]; then
+ # There is only one supported implementation; set IUSE and other
+ # variables without PYTHON_SINGLE_TARGET.
+ PYTHON_REQUIRED_USE="${flags_mt[*]}"
+ python_export "${impls[0]}" PYTHON_PKG_DEP
+ PYTHON_DEPS="${PYTHON_PKG_DEP} "
+ # Force on the python_single_target_* flag for this impl, so
+ # that any dependencies that inherit python-single-r1 and
+ # happen to have multiple implementations will still need
+ # to bound by the implementation used by this package.
+ optflags+=,${flags[0]/%/(+)}
+ else
+ # Multiple supported implementations; honor PYTHON_SINGLE_TARGET.
+ IUSE+=" ${flags[*]}"
+ PYTHON_REQUIRED_USE="^^ ( ${flags[*]} )"
+ # Ensure deps honor the same python_single_target_* flag as is set
+ # on this package.
+ optflags+=,${flags[@]/%/(+)?}
+
+ for i in "${impls[@]}"; do
+ # The chosen targets need to be in PYTHON_TARGETS as well.
+ # This is in order to enforce correct dependencies on packages
+ # supporting multiple implementations.
+ PYTHON_REQUIRED_USE+=" python_single_target_${i}? ( python_targets_${i} )"
+
+ python_export "${i}" PYTHON_PKG_DEP
+ PYTHON_DEPS+="python_single_target_${i}? ( ${PYTHON_PKG_DEP} ) "
+ done
+ fi
+ PYTHON_USEDEP=${optflags// /,}
+
+ # 1) well, python-exec would suffice as an RDEP
+ # but no point in making this overcomplex, BDEP doesn't hurt anyone
+ # 2) python-exec should be built with all targets forced anyway
+ # but if new targets were added, we may need to force a rebuild
+ # 3) use whichever python-exec slot installed in EAPI 5. For EAPI 4,
+ # just fix :2 since := deps are not supported.
+ if [[ ${_PYTHON_WANT_PYTHON_EXEC2} == 0 ]]; then
+ die "python-exec:0 is no longer supported, please fix your ebuild to work with python-exec:2"
+ elif [[ ${EAPI} != 4 ]]; then
+ PYTHON_DEPS+=">=dev-lang/python-exec-2:=[${PYTHON_USEDEP}]"
+ else
+ PYTHON_DEPS+="dev-lang/python-exec:2[${PYTHON_USEDEP}]"
+ fi
+}
+_python_single_set_globals
+
+# @FUNCTION: python_gen_usedep
+# @USAGE: <pattern> [...]
+# @DESCRIPTION:
+# Output a USE dependency string for Python implementations which
+# are both in PYTHON_COMPAT and match any of the patterns passed
+# as parameters to the function.
+#
+# Remember to escape or quote the patterns to prevent shell filename
+# expansion.
+#
+# When all implementations are requested, please use ${PYTHON_USEDEP}
+# instead. Please also remember to set an appropriate REQUIRED_USE
+# to avoid ineffective USE flags.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_7,3_4} )
+# DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep 'python2*')] )"
+# @CODE
+#
+# It will cause the dependency to look like:
+# @CODE
+# DEPEND="doc? ( dev-python/epydoc[python_targets_python2_7(-)?,...] )"
+# @CODE
+python_gen_usedep() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local impl pattern
+ local matches=()
+
+ for impl in "${PYTHON_COMPAT[@]}"; do
+ _python_impl_supported "${impl}" || continue
+
+ for pattern; do
+ if [[ ${impl} == ${pattern} ]]; then
+ matches+=(
+ "python_targets_${impl}(-)?"
+ "python_single_target_${impl}(+)?"
+ )
+ break
+ fi
+ done
+ done
+
+ [[ ${matches[@]} ]] || die "No supported implementations match python_gen_usedep patterns: ${@}"
+
+ local out=${matches[@]}
+ echo "${out// /,}"
+}
+
+# @FUNCTION: python_gen_useflags
+# @USAGE: <pattern> [...]
+# @DESCRIPTION:
+# Output a list of USE flags for Python implementations which
+# are both in PYTHON_COMPAT and match any of the patterns passed
+# as parameters to the function.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_7,3_4} )
+# REQUIRED_USE="doc? ( ^^ ( $(python_gen_useflags 'python2*') ) )"
+# @CODE
+#
+# It will cause the variable to look like:
+# @CODE
+# REQUIRED_USE="doc? ( ^^ ( python_single_target_python2_7 ) )"
+# @CODE
+python_gen_useflags() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local impl pattern
+ local matches=()
+
+ for impl in "${PYTHON_COMPAT[@]}"; do
+ _python_impl_supported "${impl}" || continue
+
+ for pattern; do
+ if [[ ${impl} == ${pattern} ]]; then
+ matches+=( "python_single_target_${impl}" )
+ break
+ fi
+ done
+ done
+
+ echo "${matches[@]}"
+}
+
+# @FUNCTION: python_gen_cond_dep
+# @USAGE: <dependency> <pattern> [...]
+# @DESCRIPTION:
+# Output a list of <dependency>-ies made conditional to USE flags
+# of Python implementations which are both in PYTHON_COMPAT and match
+# any of the patterns passed as the remaining parameters.
+#
+# In order to enforce USE constraints on the packages, verbatim
+# '${PYTHON_USEDEP}' (quoted!) may be placed in the dependency
+# specification. It will get expanded within the function into a proper
+# USE dependency string.
+#
+# Example:
+# @CODE
+# PYTHON_COMPAT=( python{2_5,2_6,2_7} )
+# RDEPEND="$(python_gen_cond_dep \
+# 'dev-python/unittest2[${PYTHON_USEDEP}]' python{2_5,2_6})"
+# @CODE
+#
+# It will cause the variable to look like:
+# @CODE
+# RDEPEND="python_single_target_python2_5? (
+# dev-python/unittest2[python_targets_python2_5(-)?,...] )
+# python_single_target_python2_6? (
+# dev-python/unittest2[python_targets_python2_6(-)?,...] )"
+# @CODE
+python_gen_cond_dep() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ local impl pattern
+ local matches=()
+
+ local dep=${1}
+ shift
+
+ for impl in "${PYTHON_COMPAT[@]}"; do
+ _python_impl_supported "${impl}" || continue
+
+ for pattern; do
+ if [[ ${impl} == ${pattern} ]]; then
+ # substitute ${PYTHON_USEDEP} if used
+ # (since python_gen_usedep() will not return ${PYTHON_USEDEP}
+ # the code is run at most once)
+ if [[ ${dep} == *'${PYTHON_USEDEP}'* ]]; then
+ local PYTHON_USEDEP=$(python_gen_usedep "${@}")
+ dep=${dep//\$\{PYTHON_USEDEP\}/${PYTHON_USEDEP}}
+ fi
+
+ matches+=( "python_single_target_${impl}? ( ${dep} )" )
+ break
+ fi
+ done
+ done
+
+ echo "${matches[@]}"
+}
+
+# @FUNCTION: python_setup
+# @DESCRIPTION:
+# Determine what the selected Python implementation is and set
+# the Python build environment up for it.
+python_setup() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ unset EPYTHON
+
+ local impl impls=()
+ for impl in "${PYTHON_COMPAT[@]}"; do
+ _python_impl_supported "${impl}" || continue
+ impls+=( "${impl}" )
+ done
+
+ if [[ ${#impls[@]} -eq 1 ]]; then
+ if use "python_targets_${impls[0]}"; then
+ # Only one supported implementation, enable it explicitly
+ python_export "${impls[0]}" EPYTHON PYTHON
+ python_wrapper_setup
+ fi
+ else
+ for impl in "${impls[@]}"; do
+ if use "python_single_target_${impl}"; then
+ if [[ ${EPYTHON} ]]; then
+ eerror "Your PYTHON_SINGLE_TARGET setting lists more than a single Python"
+ eerror "implementation. Please set it to just one value. If you need"
+ eerror "to override the value for a single package, please use package.env"
+ eerror "or an equivalent solution (man 5 portage)."
+ echo
+ die "More than one implementation in PYTHON_SINGLE_TARGET."
+ fi
+
+ if ! use "python_targets_${impl}"; then
+ eerror "The implementation chosen as PYTHON_SINGLE_TARGET must be added"
+ eerror "to PYTHON_TARGETS as well. This is in order to ensure that"
+ eerror "dependencies are satisfied correctly. We're sorry"
+ eerror "for the inconvenience."
+ echo
+ die "Build target (${impl}) not in PYTHON_TARGETS."
+ fi
+
+ python_export "${impl}" EPYTHON PYTHON
+ python_wrapper_setup
+ fi
+ done
+ fi
+
+ if [[ ! ${EPYTHON} ]]; then
+ eerror "No Python implementation selected for the build. Please set"
+ if [[ ${#impls[@]} -eq 1 ]]; then
+ eerror "the PYTHON_TARGETS variable in your make.conf to include one"
+ else
+ eerror "the PYTHON_SINGLE_TARGET variable in your make.conf to one"
+ fi
+ eerror "of the following values:"
+ eerror
+ eerror "${impls[@]}"
+ echo
+ die "No supported Python implementation in PYTHON_SINGLE_TARGET/PYTHON_TARGETS."
+ fi
+}
+
+# @FUNCTION: python-single-r1_pkg_setup
+# @DESCRIPTION:
+# Runs python_setup.
+python-single-r1_pkg_setup() {
+ debug-print-function ${FUNCNAME} "${@}"
+
+ [[ ${MERGE_TYPE} != binary ]] && python_setup
+}
+
+_PYTHON_SINGLE_R1=1
+fi