dev-qt/qttest: stable 5.14.2 for ppc, bug #719732
[gentoo.git] / eclass / python-any-r1.eclass
1 # Copyright 1999-2020 Gentoo Authors
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: python-any-r1.eclass
5 # @MAINTAINER:
6 # Python team <python@gentoo.org>
7 # @AUTHOR:
8 # Author: Michał Górny <mgorny@gentoo.org>
9 # Based on work of: Krzysztof Pawlik <nelchael@gentoo.org>
10 # @SUPPORTED_EAPIS: 5 6 7
11 # @BLURB: An eclass for packages having build-time dependency on Python.
12 # @DESCRIPTION:
13 # A minimal eclass for packages which need any Python interpreter
14 # installed without a need for explicit choice and invariability.
15 # This usually involves packages requiring Python at build-time
16 # but having no other relevance to it.
17 #
18 # This eclass provides a minimal PYTHON_DEPS variable with a dependency
19 # string on any of the supported Python implementations. It also exports
20 # pkg_setup() which finds the best supported implementation and sets it
21 # as the active one.
22 #
23 # Optionally, you can define a python_check_deps() function. It will
24 # be called by the eclass with EPYTHON set to each matching Python
25 # implementation and it is expected to check whether the implementation
26 # fulfills the package requirements. You can use the locally exported
27 # PYTHON_USEDEP to check USE-dependencies of relevant packages. It
28 # should return a true value (0) if the Python implementation fulfills
29 # the requirements, a false value (non-zero) otherwise.
30 #
31 # Please note that python-any-r1 will always inherit python-utils-r1
32 # as well. Thus, all the functions defined there can be used in the
33 # packages using python-any-r1, and there is no need ever to inherit
34 # both.
35 #
36 # For more information, please see the Python Guide:
37 # https://dev.gentoo.org/~mgorny/python-guide/
38
39 case "${EAPI:-0}" in
40         [0-4]) die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" ;;
41         [5-7]) ;;
42         *)     die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" ;;
43 esac
44
45 if [[ ! ${_PYTHON_ANY_R1} ]]; then
46
47 if [[ ${_PYTHON_R1} ]]; then
48         die 'python-any-r1.eclass can not be used with python-r1.eclass.'
49 elif [[ ${_PYTHON_SINGLE_R1} ]]; then
50         die 'python-any-r1.eclass can not be used with python-single-r1.eclass.'
51 fi
52
53 inherit python-utils-r1
54
55 fi
56
57 EXPORT_FUNCTIONS pkg_setup
58
59 # @ECLASS-VARIABLE: PYTHON_COMPAT
60 # @REQUIRED
61 # @DESCRIPTION:
62 # This variable contains a list of Python implementations the package
63 # supports. It must be set before the `inherit' call. It has to be
64 # an array.
65 #
66 # Example:
67 # @CODE
68 # PYTHON_COMPAT=( python{2_5,2_6,2_7} )
69 # @CODE
70
71 # @ECLASS-VARIABLE: PYTHON_COMPAT_OVERRIDE
72 # @INTERNAL
73 # @DESCRIPTION:
74 # This variable can be used when working with ebuilds to override
75 # the in-ebuild PYTHON_COMPAT. It is a string naming the implementation
76 # which will be used to build the package. It needs to be specified
77 # in the calling environment, and not in ebuilds.
78 #
79 # It should be noted that in order to preserve metadata immutability,
80 # PYTHON_COMPAT_OVERRIDE does not affect dependencies. The value of
81 # EPYTHON and eselect-python preferences are ignored. Dependencies need
82 # to be satisfied manually.
83 #
84 # Example:
85 # @CODE
86 # PYTHON_COMPAT_OVERRIDE='pypy' emerge -1v dev-python/bar
87 # @CODE
88
89 # @ECLASS-VARIABLE: PYTHON_REQ_USE
90 # @DEFAULT_UNSET
91 # @DESCRIPTION:
92 # The list of USEflags required to be enabled on the Python
93 # implementations, formed as a USE-dependency string. It should be valid
94 # for all implementations in PYTHON_COMPAT, so it may be necessary to
95 # use USE defaults.
96 #
97 # Example:
98 # @CODE
99 # PYTHON_REQ_USE="gdbm,ncurses(-)?"
100 # @CODE
101 #
102 # It will cause the Python dependencies to look like:
103 # @CODE
104 # || ( dev-lang/python:X.Y[gdbm,ncurses(-)?] ... )
105 # @CODE
106
107 # @ECLASS-VARIABLE: PYTHON_DEPS
108 # @DESCRIPTION:
109 # This is an eclass-generated Python dependency string for all
110 # implementations listed in PYTHON_COMPAT.
111 #
112 # Any of the supported interpreters will satisfy the dependency.
113 #
114 # Example use:
115 # @CODE
116 # DEPEND="${RDEPEND}
117 #       ${PYTHON_DEPS}"
118 # @CODE
119 #
120 # Example value:
121 # @CODE
122 # || ( dev-lang/python:2.7[gdbm]
123 #       dev-lang/python:2.6[gdbm] )
124 # @CODE
125
126 # @ECLASS-VARIABLE: PYTHON_USEDEP
127 # @DESCRIPTION:
128 # An eclass-generated USE-dependency string for the currently tested
129 # implementation. It is set locally for python_check_deps() call.
130 #
131 # The generate USE-flag list is compatible with packages using python-r1,
132 # python-single-r1 and python-distutils-ng eclasses. It must not be used
133 # on packages using python.eclass.
134 #
135 # Example use:
136 # @CODE
137 # python_check_deps() {
138 #       has_version "dev-python/foo[${PYTHON_USEDEP}]"
139 # }
140 # @CODE
141 #
142 # Example value:
143 # @CODE
144 # python_targets_python2_7(-)?,python_single_target_python2_7(+)?
145 # @CODE
146
147 _python_any_set_globals() {
148         local usestr deps i PYTHON_PKG_DEP
149         [[ ${PYTHON_REQ_USE} ]] && usestr="[${PYTHON_REQ_USE}]"
150
151         _python_set_impls
152
153         for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
154                 _python_export "${i}" PYTHON_PKG_DEP
155
156                 # note: need to strip '=' slot operator for || deps
157                 deps="${PYTHON_PKG_DEP/:0=/:0} ${deps}"
158         done
159         deps="|| ( ${deps})"
160
161         if [[ ${PYTHON_DEPS+1} ]]; then
162                 if [[ ${PYTHON_DEPS} != "${deps}" ]]; then
163                         eerror "PYTHON_DEPS have changed between inherits (PYTHON_REQ_USE?)!"
164                         eerror "Before: ${PYTHON_DEPS}"
165                         eerror "Now   : ${deps}"
166                         die "PYTHON_DEPS integrity check failed"
167                 fi
168         else
169                 PYTHON_DEPS=${deps}
170                 readonly PYTHON_DEPS
171         fi
172
173         if [[ ! ${PYTHON_REQUIRED_USE+1} ]]; then
174                 # fake var to catch mistaken usage
175                 PYTHON_REQUIRED_USE='I-DO-NOT-EXIST-IN-PYTHON-ANY-R1'
176                 readonly PYTHON_REQUIRED_USE
177         fi
178 }
179 _python_any_set_globals
180 unset -f _python_any_set_globals
181
182 if [[ ! ${_PYTHON_ANY_R1} ]]; then
183
184 # @FUNCTION: python_gen_any_dep
185 # @USAGE: <dependency-block>
186 # @DESCRIPTION:
187 # Generate an any-of dependency that enforces a version match between
188 # the Python interpreter and Python packages. <dependency-block> needs
189 # to list one or more dependencies with verbatim '${PYTHON_USEDEP}'
190 # references (quoted!) that will get expanded inside the function.
191 #
192 # This should be used along with an appropriate python_check_deps()
193 # that checks which of the any-of blocks were matched.
194 #
195 # Example use:
196 # @CODE
197 # DEPEND="$(python_gen_any_dep '
198 #       dev-python/foo[${PYTHON_USEDEP}]
199 #       || ( dev-python/bar[${PYTHON_USEDEP}]
200 #               dev-python/baz[${PYTHON_USEDEP}] )')"
201 #
202 # python_check_deps() {
203 #       has_version "dev-python/foo[${PYTHON_USEDEP}]" \
204 #               && { has_version "dev-python/bar[${PYTHON_USEDEP}]" \
205 #                       || has_version "dev-python/baz[${PYTHON_USEDEP}]"; }
206 # }
207 # @CODE
208 #
209 # Example value:
210 # @CODE
211 # || (
212 #       (
213 #               dev-lang/python:2.7
214 #               dev-python/foo[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
215 #               || ( dev-python/bar[python_targets_python2_7(-)?,python_single_target_python2_7(+)?]
216 #                       dev-python/baz[python_targets_python2_7(-)?,python_single_target_python2_7(+)?] )
217 #       )
218 #       (
219 #               dev-lang/python:3.3
220 #               dev-python/foo[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
221 #               || ( dev-python/bar[python_targets_python3_3(-)?,python_single_target_python3_3(+)?]
222 #                       dev-python/baz[python_targets_python3_3(-)?,python_single_target_python3_3(+)?] )
223 #       )
224 # )
225 # @CODE
226 python_gen_any_dep() {
227         debug-print-function ${FUNCNAME} "${@}"
228
229         local depstr=${1}
230         [[ ${depstr} ]] || die "No dependency string provided"
231
232         local i PYTHON_PKG_DEP out=
233         for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
234                 local PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
235                 _python_export "${i}" PYTHON_PKG_DEP
236
237                 local i_depstr=${depstr//\$\{PYTHON_USEDEP\}/${PYTHON_USEDEP}}
238                 # note: need to strip '=' slot operator for || deps
239                 out="( ${PYTHON_PKG_DEP%=} ${i_depstr} ) ${out}"
240         done
241         echo "|| ( ${out})"
242 }
243
244 # @FUNCTION: _python_EPYTHON_supported
245 # @USAGE: <epython>
246 # @INTERNAL
247 # @DESCRIPTION:
248 # Check whether the specified implementation is supported by package
249 # (specified in PYTHON_COMPAT). Calls python_check_deps() if declared.
250 _python_EPYTHON_supported() {
251         debug-print-function ${FUNCNAME} "${@}"
252
253         local EPYTHON=${1}
254         local i=${EPYTHON/./_}
255
256         case "${i}" in
257                 python*|jython*|pypy*)
258                         ;;
259                 *)
260                         ewarn "Invalid EPYTHON: ${EPYTHON}"
261                         return 1
262                         ;;
263         esac
264
265         if has "${i}" "${_PYTHON_SUPPORTED_IMPLS[@]}"; then
266                 if python_is_installed "${i}"; then
267                         if declare -f python_check_deps >/dev/null; then
268                                 local PYTHON_USEDEP="python_targets_${i}(-),python_single_target_${i}(+)"
269                                 python_check_deps
270                                 return ${?}
271                         fi
272
273                         return 0
274                 fi
275         elif ! has "${i}" "${_PYTHON_ALL_IMPLS[@]}"; then
276                 ewarn "Invalid EPYTHON: ${EPYTHON}"
277         fi
278         return 1
279 }
280
281 # @FUNCTION: python_setup
282 # @DESCRIPTION:
283 # Determine what the best installed (and supported) Python
284 # implementation is, and set the Python build environment up for it.
285 #
286 # This function will call python_check_deps() if defined.
287 python_setup() {
288         debug-print-function ${FUNCNAME} "${@}"
289
290         # support developer override
291         if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
292                 local impls=( ${PYTHON_COMPAT_OVERRIDE} )
293                 [[ ${#impls[@]} -eq 1 ]] || die "PYTHON_COMPAT_OVERRIDE must name exactly one implementation for python-any-r1"
294
295                 ewarn "WARNING: PYTHON_COMPAT_OVERRIDE in effect. The following Python"
296                 ewarn "implementation will be used:"
297                 ewarn
298                 ewarn " ${PYTHON_COMPAT_OVERRIDE}"
299                 ewarn
300                 ewarn "Dependencies won't be satisfied, and EPYTHON/eselect-python will be ignored."
301
302                 _python_export "${impls[0]}" EPYTHON PYTHON
303                 _python_wrapper_setup
304                 einfo "Using ${EPYTHON} to build"
305                 return
306         fi
307
308         # first, try ${EPYTHON}... maybe it's good enough for us.
309         if [[ ${EPYTHON} ]]; then
310                 if _python_EPYTHON_supported "${EPYTHON}"; then
311                         _python_export EPYTHON PYTHON
312                         _python_wrapper_setup
313                         einfo "Using ${EPYTHON} to build"
314                         return
315                 fi
316         fi
317
318         # then, try eselect-python
319         local variant i
320         for variant in '' '--python2' '--python3'; do
321                 i=$(eselect python --show ${variant} 2>/dev/null)
322
323                 if [[ ! ${i} ]]; then
324                         # no eselect-python?
325                         break
326                 elif _python_EPYTHON_supported "${i}"; then
327                         _python_export "${i}" EPYTHON PYTHON
328                         _python_wrapper_setup
329                         einfo "Using ${EPYTHON} to build"
330                         return
331                 fi
332         done
333
334         # fallback to best installed impl.
335         # (reverse iteration over _PYTHON_SUPPORTED_IMPLS)
336         for (( i = ${#_PYTHON_SUPPORTED_IMPLS[@]} - 1; i >= 0; i-- )); do
337                 _python_export "${_PYTHON_SUPPORTED_IMPLS[i]}" EPYTHON PYTHON
338                 if _python_EPYTHON_supported "${EPYTHON}"; then
339                         _python_wrapper_setup
340                         einfo "Using ${EPYTHON} to build"
341                         return
342                 fi
343         done
344
345         eerror "No Python implementation found for the build. This is usually"
346         eerror "a bug in the ebuild. Please report it to bugs.gentoo.org"
347         eerror "along with the build log."
348         echo
349         die "No supported Python implementation installed."
350 }
351
352 # @FUNCTION: python-any-r1_pkg_setup
353 # @DESCRIPTION:
354 # Runs python_setup during from-source installs.
355 #
356 # In a binary package installs is a no-op. If you need Python in pkg_*
357 # phases of a binary package, call python_setup directly.
358 python-any-r1_pkg_setup() {
359         debug-print-function ${FUNCNAME} "${@}"
360
361         [[ ${MERGE_TYPE} != binary ]] && python_setup
362 }
363
364 _PYTHON_ANY_R1=1
365 fi