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