Hello, Instead of the floating patches and p-d-ng modifications I sent earlier, here are the two complete (so far, well, initial :P) eclasses for review.
They are designed as 'mostly' drop-in python-distutils-ng replacement. -- Best regards, Michał Górny
# Copyright 1999-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ # @ECLASS: python-r1 # @MAINTAINER: # Python herd <pyt...@gentoo.org> # @AUTHOR: # Author: MichaŠGórny <mgo...@gentoo.org> # Based on work of: Krzysztof Pawlik <nelch...@gentoo.org> # @BLURB: A common, simple eclass for Python packages. # @DESCRIPTION: # A common eclass providing helper functions to build and install # packages supporting being installed for multiple Python # implementations. # # This eclass sets correct IUSE and REQUIRED_USE. It exports PYTHON_DEPS # and PYTHON_USEDEP so you can create correct dependencies for your # package easily. It also provides methods to easily run a command for # each enabled Python implementation and duplicate the sources for them. case "${EAPI}" in 0|1|2|3) die "Unsupported EAPI=${EAPI} (too old) for ${ECLASS}" ;; 4) # EAPI=4 needed for REQUIRED_USE ;; *) die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;; esac # @ECLASS-VARIABLE: _PYTHON_ALL_IMPLS # @INTERNAL # @DESCRIPTION: # All supported Python implementations, most preferred last. _PYTHON_ALL_IMPLS=( jython2_5 pypy1_8 pypy1_9 python3_1 python3_2 python2_5 python2_6 python2_7 ) # @ECLASS-VARIABLE: PYTHON_COMPAT # @DESCRIPTION: # This variable contains a space separated list of Python # implementations a package supports. It must be set before # the `inherit' call. The default is to enable all implementations. # # PYTHON_COMPAT can be either a scalar or an array. If it's a scalar, # the eclass will implicitly convert it to an array. : ${PYTHON_COMPAT:=${_PYTHON_ALL_IMPLS[@]}} # @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. # # Example: # @CODE # PYTHON_REQ_USE="gdbm,ncurses(-)?" # @CODE # # Will cause the Python dependencies to look like: # @CODE # python_targets_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. It should be used # in RDEPEND and/or DEPEND like: # # @CODE # RDEPEND="${PYTHON_DEPS} # dev-foo/mydep" # DEPEND="${RDEPEND}" # @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. It should be used like: # # @CODE # RDEPEND="dev-python/foo[${PYTHON_USEDEP}]" # @CODE PYTHON_COMPAT=( ${PYTHON_COMPAT[@]} ) _python_set_globals() { local flags=( "${PYTHON_COMPAT[@]/#/python_targets_}" ) local optflags=${flags[@]/%/?} IUSE=${flags[*]} REQUIRED_USE="|| ( ${flags[*]} )" PYTHON_USEDEP=${optflags// /,} PYTHON_DEPS= local i for i in ${PYTHON_COMPAT[@]}; do local d case ${i} in python*) d='dev-lang/python';; jython*) d='dev-java/jython';; pypy*) d='dev-python/pypy';; *) die "Invalid implementation: ${i}" esac local v=${i##*[a-z]} local usestr [[ ${PYTHON_REQ_USE} ]] && usestr="[${PYTHON_REQ_USE}]" PYTHON_DEPS+=" python_targets_${i}? ( ${d}:${v/_/.}${usestr} )" done } _python_set_globals # @FUNCTION: python_get_PYTHON # @USAGE: <impl> # @DESCRIPTION: # Get the Python executable name for the given implementation. Please # note that this this function returns the 'basename' only. # If using it for a hashbang, please use #!/usr/bin/env. python_get_PYTHON() { local impl=${1/_/.} case "${impl}" in python*|jython*) echo ${impl} ;; pypy*) echo pypy-c${impl#pypy} ;; *) die "Invalid argument to python_get_PYTHON: ${1}" ;; esac } # @FUNCTION: python_copy_sources # @DESCRIPTION: # Create a single copy of the package sources (${S}) for each enabled # Python implementation. python_copy_sources() { local impl local bdir=${BUILD_DIR:-${S}} einfo "Will copy sources from ${S}" # the order is irrelevant here for impl in ${PYTHON_COMPAT[@]}; do if use python_targets_${impl} then local BUILD_DIR=${bdir%%/}-${impl} einfo "${impl}: copying to ${BUILD_DIR}" cp -pr "${S}" "${BUILD_DIR}" || die fi done } # @FUNCTION: python_foreach_impl # @USAGE: <command> [<args>...] # @DESCRIPTION: # Run the given command for each of the enabled Python implementations. # If additional parameters are passed, they will be passed through # to the command. If the command fails, python_foreach_impl dies. # If necessary, use ':' to force a successful return. # # Before the command is run, EPYTHON is set to the name of the current # Python implementation, PYTHON is set to the correct Python executable # name and exported, and BUILD_DIR is set to a 'default' build directory # for given implementation (e.g. ${BUILD_DIR:-${S}}-python2_7). # # The command is run inside the build directory. If it doesn't exist # yet, it is created (as an empty directory!). If your build system does # not support out-of-source builds, you will likely want to use # python_copy_sources first. python_foreach_impl() { local impl local bdir=${BUILD_DIR:-${S}} for impl in ${_PYTHON_ALL_IMPLS[@]}; do if has ${impl} ${PYTHON_COMPAT[@]} && use python_targets_${impl} then local PYTHON=$(python_get_PYTHON "${impl}") local EPYTHON=${impl} local BUILD_DIR=${bdir%%/}-${impl} export PYTHON mkdir -p "${BUILD_DIR}" || die pushd "${BUILD_DIR}" &>/dev/null || die einfo "${EPYTHON}: running ${@}" "${@}" || die "${EPYTHON}: ${1} failed" popd || die fi done }
# Copyright 1999-2012 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 # $Header: $ # @ECLASS: distutils-r1 # @MAINTAINER: # Python herd <pyt...@gentoo.org> # @AUTHOR: # Author: MichaŠGórny <mgo...@gentoo.org> # Based on the work of: Krzysztof Pawlik <nelch...@gentoo.org> # @BLURB: A simple eclass to build Python packages using distutils. # @DESCRIPTION: # A simple eclass providing functions to build Python packages using # the distutils build system. It exports phase functions for all # the src_* phases. Each of the phases runs two pseudo-phases: # python_..._all() (e.g. python_prepare_all()) once in ${S}, then # python_...() (e.g. python_prepare()) for each implementation # (see: python_foreach_impl() in python-r1). # # In distutils-r1_src_prepare(), the 'all' function is run before # per-implementation ones (because it creates the implementations), # per-implementation functions are run in a random order. # # In remaining phase functions, the per-implementation functions are run # before the 'all' one, and they are ordered from the least to the most # preferred implementation (so that 'better' files overwrite 'worse' # ones). # # If the ebuild doesn't specify a particular pseudo-phase function, # the default one will be used (distutils-r1_...). Defaults are provided # for all per-implementation pseudo-phases, python_prepare_all() # and python_install_all(); whenever writing your own pseudo-phase # functions, you should consider calling the defaults (and especially # distutils-r1_python_prepare_all). # # Please note that distutils-r1 sets RDEPEND and DEPEND for you. case "${EAPI}" in 0|1|2|3) die "Unsupported EAPI=${EAPI} (too old) for ${ECLASS}" ;; 4) ;; *) die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;; esac inherit eutils python-r1 EXPORT_FUNCTIONS src_prepare src_configure src_compile src_test src_install RDEPEND=${PYTHON_DEPS} DEPEND=${PYTHON_DEPS} # @FUNCTION: distutils-r1_python_prepare_all # @DESCRIPTION: # The default python_prepare_all(). It applies the patches from PATCHES # array, then user patches and finally calls python_copy_sources to # create copies of resulting sources for each Python implementation. distutils-r1_python_prepare_all() { [[ ${PATCHES} ]] && epatch "${PATCHES[@]}" epatch_user # create source copies for each implementation python_copy_sources } # @FUNCTION: distutils-r1_python_prepare # @DESCRIPTION: # The default python_prepare(). Currently it is a no-op # but in the future it may apply implementation-specific quirks # to the build system. distutils-r1_python_prepare() { : } # @FUNCTION: distutils-r1_python_configure # @DESCRIPTION: # The default python_configure(). Currently a no-op. distutils-r1_python_configure() { : } # @FUNCTION: distutils-r1_python_compile # @DESCRIPTION: # The default python_compile(). Runs 'setup.py build' using the correct # Python implementation. distutils-r1_python_compile() { cd "${BUILD_DIR}" || die "${PYTHON}" setup.py build || die } # @FUNCTION: distutils-r1_python_test # @DESCRIPTION: # The default python_test(). Currently a no-op. distutils-r1_python_test() { : } # @FUNCTION: distutils-r1_rename_scripts # @DESCRIPTION: # Renames installed Python scripts to be implementation-suffixed. # ${PYTHON} has to be set to the expected Python executable (which # hashbang will be grepped for), and ${EPYTHON} to the implementation # name (for new name). distutils-r1_rename_scripts() { local dir f local wrapdir=${T}/distutils_wrappers # XXX: change this if we ever allow directories in bin/sbin for dir in bin sbin usr/bin usr/sbin; do for f in "${D}"/${dir}/*; do if [[ -x ${f} ]]; then if [[ "$(head -n 1 "${f}")" == '#!'*${PYTHON}* ]] then local newf=${f}-${EPYTHON} mv "${f}" "${newf}" || die mkdir -p "${wrapdir}"/${dir} ln -fs "${newf##*/}" \ "${wrapdir}"/${dir}/"${f##*/}" || die fi fi done done } # @FUNCTION: distutils-r1_python_install # @DESCRIPTION: # The default python_install(). Runs 'setup.py install' using # the correct Python implementation, and appending the optimization # flags. Then calls distutils-r1_rename_scripts. distutils-r1_python_install() { local flags case "${EPYTHON}" in jython*) flags='--compile';; *) flags='--compile -O2';; esac # XXX: where does it come from?! unset PYTHONDONTWRITEBYTECODE cd "${BUILD_DIR}" || die "${PYTHON}" setup.py install ${flags} --root="${D}" || die distutils-r1_rename_scripts } # @FUNCTION: distutils-r1_python_install_all # @DESCRIPTION: # The default python_install_all(). It creates wrappers # for the implementation-suffixed executables. distutils-r1_python_install_all() { local wrapdir=${T}/distutils_wrappers if [[ -d ${wrapdir} ]]; then cp -r "${wrapdir}/." "${D}" || die fi } distutils-r1_src_prepare() { # common preparations if declare -f python_prepare_all >/dev/null; then python_prepare_all else distutils-r1_python_prepare_all fi if declare -f python_prepare >/dev/null; then python_foreach_impl python_prepare else distutils-r1_python_prepare fi } distutils-r1_src_configure() { if declare -f python_configure >/dev/null; then python_foreach_impl python_configure else distutils-r1_python_configure fi if declare -f python_configure_all >/dev/null; then python_configure_all fi } distutils-r1_src_compile() { if declare -f python_compile >/dev/null; then python_foreach_impl python_compile else python_foreach_impl distutils-r1_python_compile fi if declare -f python_compile_all >/dev/null; then python_compile_all fi } distutils-r1_src_test() { if declare -f python_test >/dev/null; then python_foreach_impl python_test else distutils-r1_python_test fi if declare -f python_test_all >/dev/null; then python_test_all fi } distutils-r1_src_install() { if declare -f python_install >/dev/null; then python_foreach_impl python_install else python_foreach_impl distutils-r1_python_install fi if declare -f python_install_all >/dev/null; then python_install_all else distutils-r1_python_install_all fi }
signature.asc
Description: PGP signature