python-single-r1.eclass: add @SUPPORTED_EAPIS
[gentoo.git] / eclass / python-single-r1.eclass
1 # Copyright 1999-2018 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3
4 # @ECLASS: python-single-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 Python packages not installed for multiple implementations.
12 # @DESCRIPTION:
13 # An extension of the python-r1 eclass suite for packages which
14 # don't support being installed for multiple Python implementations.
15 # This mostly includes tools embedding Python.
16 #
17 # This eclass extends the IUSE and REQUIRED_USE set by python-r1
18 # to request the PYTHON_SINGLE_TARGET when the inheriting ebuild
19 # can be supported by more than one Python implementation. It also
20 # replaces PYTHON_USEDEP and PYTHON_DEPS with a more suitable form.
21 #
22 # Please note that packages support multiple Python implementations
23 # (using python-r1 eclass) can not depend on packages not supporting
24 # them (using this eclass).
25 #
26 # Please note that python-single-r1 will always inherit python-utils-r1
27 # as well. Thus, all the functions defined there can be used
28 # in the packages using python-single-r1, and there is no need ever
29 # to inherit both.
30 #
31 # For more information, please see the wiki:
32 # https://wiki.gentoo.org/wiki/Project:Python/python-single-r1
33
34 case "${EAPI:-0}" in
35         0|1|2|3|4)
36                 die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
37                 ;;
38         5|6|7)
39                 # EAPI=5 is required for sane USE_EXPAND dependencies
40                 ;;
41         *)
42                 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
43                 ;;
44 esac
45
46 if [[ ! ${_PYTHON_SINGLE_R1} ]]; then
47
48 if [[ ${_PYTHON_R1} ]]; then
49         die 'python-single-r1.eclass can not be used with python-r1.eclass.'
50 elif [[ ${_PYTHON_ANY_R1} ]]; then
51         die 'python-single-r1.eclass can not be used with python-any-r1.eclass.'
52 fi
53
54 inherit python-utils-r1
55
56 fi
57
58 EXPORT_FUNCTIONS pkg_setup
59
60 # @ECLASS-VARIABLE: PYTHON_COMPAT
61 # @REQUIRED
62 # @DESCRIPTION:
63 # This variable contains a list of Python implementations the package
64 # supports. It must be set before the `inherit' call. It has to be
65 # an array.
66 #
67 # Example:
68 # @CODE
69 # PYTHON_COMPAT=( python2_7 python3_3 python3_4 )
70 # @CODE
71 #
72 # Please note that you can also use bash brace expansion if you like:
73 # @CODE
74 # PYTHON_COMPAT=( python2_7 python3_{3,4} )
75 # @CODE
76
77 # @ECLASS-VARIABLE: PYTHON_COMPAT_OVERRIDE
78 # @INTERNAL
79 # @DESCRIPTION:
80 # This variable can be used when working with ebuilds to override
81 # the in-ebuild PYTHON_COMPAT. It is a string naming the implementation
82 # which package will be built for. It needs to be specified
83 # in the calling environment, and not in ebuilds.
84 #
85 # It should be noted that in order to preserve metadata immutability,
86 # PYTHON_COMPAT_OVERRIDE does not affect IUSE nor dependencies.
87 # The state of PYTHON_TARGETS and PYTHON_SINGLE_TARGET is ignored,
88 # and the implementation in PYTHON_COMPAT_OVERRIDE is built instead.
89 # Dependencies need to be satisfied manually.
90 #
91 # Example:
92 # @CODE
93 # PYTHON_COMPAT_OVERRIDE='pypy' emerge -1v dev-python/bar
94 # @CODE
95
96 # @ECLASS-VARIABLE: PYTHON_REQ_USE
97 # @DEFAULT_UNSET
98 # @DESCRIPTION:
99 # The list of USEflags required to be enabled on the chosen Python
100 # implementations, formed as a USE-dependency string. It should be valid
101 # for all implementations in PYTHON_COMPAT, so it may be necessary to
102 # use USE defaults.
103 #
104 # This should be set before calling `inherit'.
105 #
106 # Example:
107 # @CODE
108 # PYTHON_REQ_USE="gdbm,ncurses(-)?"
109 # @CODE
110 #
111 # It will cause the Python dependencies to look like:
112 # @CODE
113 # python_single_target_pythonX_Y? ( dev-lang/python:X.Y[gdbm,ncurses(-)?] )
114 # @CODE
115
116 # @ECLASS-VARIABLE: PYTHON_DEPS
117 # @DESCRIPTION:
118 # This is an eclass-generated Python dependency string for all
119 # implementations listed in PYTHON_COMPAT.
120 #
121 # The dependency string is conditional on PYTHON_SINGLE_TARGET.
122 #
123 # Example use:
124 # @CODE
125 # RDEPEND="${PYTHON_DEPS}
126 #       dev-foo/mydep"
127 # DEPEND="${RDEPEND}"
128 # @CODE
129 #
130 # Example value:
131 # @CODE
132 # dev-lang/python-exec:=
133 # python_single_target_python2_7? ( dev-lang/python:2.7[gdbm] )
134 # python_single_target_pypy? ( virtual/pypy[gdbm] )
135 # @CODE
136
137 # @ECLASS-VARIABLE: PYTHON_USEDEP
138 # @DESCRIPTION:
139 # This is an eclass-generated USE-dependency string which can be used to
140 # depend on another Python package being built for the same Python
141 # implementations.
142 #
143 # The generate USE-flag list is compatible with packages using python-r1,
144 # python-single-r1 and python-distutils-ng eclasses. It must not be used
145 # on packages using python.eclass.
146 #
147 # Example use:
148 # @CODE
149 # RDEPEND="dev-python/foo[${PYTHON_USEDEP}]"
150 # @CODE
151 #
152 # Example value:
153 # @CODE
154 # python_targets_python2_7(-)?,python_single_target_python3_4(+)?
155 # @CODE
156
157 # @ECLASS-VARIABLE: PYTHON_REQUIRED_USE
158 # @DESCRIPTION:
159 # This is an eclass-generated required-use expression which ensures the following
160 # when more than one python implementation is possible:
161 # 1. Exactly one PYTHON_SINGLE_TARGET value has been enabled.
162 # 2. The selected PYTHON_SINGLE_TARGET value is enabled in PYTHON_TARGETS.
163 #
164 # This expression should be utilized in an ebuild by including it in
165 # REQUIRED_USE, optionally behind a use flag.
166 #
167 # Example use:
168 # @CODE
169 # REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
170 # @CODE
171 #
172 # Example value:
173 # @CODE
174 # python_single_target_python2_7? ( python_targets_python2_7 )
175 # python_single_target_python3_3? ( python_targets_python3_3 )
176 # ^^ ( python_single_target_python2_7 python_single_target_python3_3 )
177 # @CODE
178
179 _python_single_set_globals() {
180         _python_set_impls
181
182         local i PYTHON_PKG_DEP
183
184         local flags_mt=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_targets_}" )
185         local flags=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_single_target_}" )
186         local unflags=( "${_PYTHON_UNSUPPORTED_IMPLS[@]/#/-python_single_target_}" )
187
188         local optflags=${flags_mt[@]/%/(-)?},${unflags[@]/%/(-)}
189
190         IUSE="${flags_mt[*]}"
191
192         local deps requse usedep
193         if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
194                 # There is only one supported implementation; set IUSE and other
195                 # variables without PYTHON_SINGLE_TARGET.
196                 requse=${flags_mt[*]}
197                 python_export "${_PYTHON_SUPPORTED_IMPLS[0]}" PYTHON_PKG_DEP
198                 deps="${flags_mt[*]}? ( ${PYTHON_PKG_DEP} ) "
199                 # Force on the python_single_target_* flag for this impl, so
200                 # that any dependencies that inherit python-single-r1 and
201                 # happen to have multiple implementations will still need
202                 # to bound by the implementation used by this package.
203                 optflags+=,${flags[0]/%/(+)}
204         else
205                 # Multiple supported implementations; honor PYTHON_SINGLE_TARGET.
206                 IUSE+=" ${flags[*]}"
207                 requse="^^ ( ${flags[*]} )"
208                 # Ensure deps honor the same python_single_target_* flag as is set
209                 # on this package.
210                 optflags+=,${flags[@]/%/(+)?}
211
212                 for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
213                         # The chosen targets need to be in PYTHON_TARGETS as well.
214                         # This is in order to enforce correct dependencies on packages
215                         # supporting multiple implementations.
216                         requse+=" python_single_target_${i}? ( python_targets_${i} )"
217
218                         python_export "${i}" PYTHON_PKG_DEP
219                         deps+="python_single_target_${i}? ( ${PYTHON_PKG_DEP} ) "
220                 done
221         fi
222         usedep=${optflags// /,}
223
224         # 1) well, python-exec would suffice as an RDEP
225         # but no point in making this overcomplex, BDEP doesn't hurt anyone
226         # 2) python-exec should be built with all targets forced anyway
227         # but if new targets were added, we may need to force a rebuild
228         if [[ ${_PYTHON_WANT_PYTHON_EXEC2} == 0 ]]; then
229                 die "python-exec:0 is no longer supported, please fix your ebuild to work with python-exec:2"
230         else
231                 deps+=">=dev-lang/python-exec-2:=[${usedep}]"
232         fi
233
234         if [[ ${PYTHON_DEPS+1} ]]; then
235                 if [[ ${PYTHON_DEPS} != "${deps}" ]]; then
236                         eerror "PYTHON_DEPS have changed between inherits (PYTHON_REQ_USE?)!"
237                         eerror "Before: ${PYTHON_DEPS}"
238                         eerror "Now   : ${deps}"
239                         die "PYTHON_DEPS integrity check failed"
240                 fi
241
242                 # these two are formality -- they depend on PYTHON_COMPAT only
243                 if [[ ${PYTHON_REQUIRED_USE} != ${requse} ]]; then
244                         eerror "PYTHON_REQUIRED_USE have changed between inherits!"
245                         eerror "Before: ${PYTHON_REQUIRED_USE}"
246                         eerror "Now   : ${requse}"
247                         die "PYTHON_REQUIRED_USE integrity check failed"
248                 fi
249
250                 if [[ ${PYTHON_USEDEP} != "${usedep}" ]]; then
251                         eerror "PYTHON_USEDEP have changed between inherits!"
252                         eerror "Before: ${PYTHON_USEDEP}"
253                         eerror "Now   : ${usedep}"
254                         die "PYTHON_USEDEP integrity check failed"
255                 fi
256         else
257                 PYTHON_DEPS=${deps}
258                 PYTHON_REQUIRED_USE=${requse}
259                 PYTHON_USEDEP=${usedep}
260                 readonly PYTHON_DEPS PYTHON_REQUIRED_USE PYTHON_USEDEP
261         fi
262 }
263 _python_single_set_globals
264 unset -f _python_single_set_globals
265
266 if [[ ! ${_PYTHON_SINGLE_R1} ]]; then
267
268 # @FUNCTION: python_gen_usedep
269 # @USAGE: <pattern> [...]
270 # @DESCRIPTION:
271 # Output a USE dependency string for Python implementations which
272 # are both in PYTHON_COMPAT and match any of the patterns passed
273 # as parameters to the function.
274 #
275 # The patterns can be either fnmatch-style patterns (matched via bash
276 # == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
277 # appropriately all enabled Python 2/3 implementations (alike
278 # python_is_python3). Remember to escape or quote the fnmatch patterns
279 # to prevent accidental shell filename expansion.
280 #
281 # When all implementations are requested, please use ${PYTHON_USEDEP}
282 # instead. Please also remember to set an appropriate REQUIRED_USE
283 # to avoid ineffective USE flags.
284 #
285 # Example:
286 # @CODE
287 # PYTHON_COMPAT=( python{2_7,3_4} )
288 # DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep 'python2*')] )"
289 # @CODE
290 #
291 # It will cause the dependency to look like:
292 # @CODE
293 # DEPEND="doc? ( dev-python/epydoc[python_targets_python2_7(-)?,...] )"
294 # @CODE
295 python_gen_usedep() {
296         debug-print-function ${FUNCNAME} "${@}"
297
298         local impl matches=()
299
300         for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
301                 if _python_impl_matches "${impl}" "${@}"; then
302                         matches+=(
303                                 "python_targets_${impl}(-)?"
304                                 "python_single_target_${impl}(+)?"
305                         )
306                 fi
307         done
308
309         [[ ${matches[@]} ]] || die "No supported implementations match python_gen_usedep patterns: ${@}"
310
311         local out=${matches[@]}
312         echo "${out// /,}"
313 }
314
315 # @FUNCTION: python_gen_useflags
316 # @USAGE: <pattern> [...]
317 # @DESCRIPTION:
318 # Output a list of USE flags for Python implementations which
319 # are both in PYTHON_COMPAT and match any of the patterns passed
320 # as parameters to the function.
321 #
322 # The patterns can be either fnmatch-style patterns (matched via bash
323 # == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
324 # appropriately all enabled Python 2/3 implementations (alike
325 # python_is_python3). Remember to escape or quote the fnmatch patterns
326 # to prevent accidental shell filename expansion.
327 #
328 # Example:
329 # @CODE
330 # PYTHON_COMPAT=( python{2_7,3_4} )
331 # REQUIRED_USE="doc? ( ^^ ( $(python_gen_useflags 'python2*') ) )"
332 # @CODE
333 #
334 # It will cause the variable to look like:
335 # @CODE
336 # REQUIRED_USE="doc? ( ^^ ( python_single_target_python2_7 ) )"
337 # @CODE
338 python_gen_useflags() {
339         debug-print-function ${FUNCNAME} "${@}"
340
341         local flag_prefix impl matches=()
342
343         if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
344                 flag_prefix=python_targets
345         else
346                 flag_prefix=python_single_target
347         fi
348
349         for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
350                 if _python_impl_matches "${impl}" "${@}"; then
351                         matches+=( "${flag_prefix}_${impl}" )
352                 fi
353         done
354
355         echo "${matches[@]}"
356 }
357
358 # @FUNCTION: python_gen_cond_dep
359 # @USAGE: <dependency> <pattern> [...]
360 # @DESCRIPTION:
361 # Output a list of <dependency>-ies made conditional to USE flags
362 # of Python implementations which are both in PYTHON_COMPAT and match
363 # any of the patterns passed as the remaining parameters.
364 #
365 # The patterns can be either fnmatch-style patterns (matched via bash
366 # == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
367 # appropriately all enabled Python 2/3 implementations (alike
368 # python_is_python3). Remember to escape or quote the fnmatch patterns
369 # to prevent accidental shell filename expansion.
370 #
371 # In order to enforce USE constraints on the packages, verbatim
372 # '${PYTHON_USEDEP}' (quoted!) may be placed in the dependency
373 # specification. It will get expanded within the function into a proper
374 # USE dependency string.
375 #
376 # Example:
377 # @CODE
378 # PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
379 # RDEPEND="$(python_gen_cond_dep \
380 #   'dev-python/unittest2[${PYTHON_USEDEP}]' python2_7 pypy )"
381 # @CODE
382 #
383 # It will cause the variable to look like:
384 # @CODE
385 # RDEPEND="python_single_target_python2_7? (
386 #     dev-python/unittest2[python_targets_python2_7(-)?,...] )
387 #       python_single_target_pypy? (
388 #     dev-python/unittest2[python_targets_pypy(-)?,...] )"
389 # @CODE
390 python_gen_cond_dep() {
391         debug-print-function ${FUNCNAME} "${@}"
392
393         local flag_prefix impl matches=()
394
395         if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
396                 flag_prefix=python_targets
397         else
398                 flag_prefix=python_single_target
399         fi
400
401         local dep=${1}
402         shift
403
404         for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
405                 if _python_impl_matches "${impl}" "${@}"; then
406                         # substitute ${PYTHON_USEDEP} if used
407                         # (since python_gen_usedep() will not return ${PYTHON_USEDEP}
408                         #  the code is run at most once)
409                         if [[ ${dep} == *'${PYTHON_USEDEP}'* ]]; then
410                                 local usedep=$(python_gen_usedep "${@}")
411                                 dep=${dep//\$\{PYTHON_USEDEP\}/${usedep}}
412                         fi
413
414                         matches+=( "${flag_prefix}_${impl}? ( ${dep} )" )
415                 fi
416         done
417
418         echo "${matches[@]}"
419 }
420
421 # @FUNCTION: python_gen_impl_dep
422 # @USAGE: [<requested-use-flags> [<impl-pattern>...]]
423 # @DESCRIPTION:
424 # Output a dependency on Python implementations with the specified USE
425 # dependency string appended, or no USE dependency string if called
426 # without the argument (or with empty argument). If any implementation
427 # patterns are passed, the output dependencies will be generated only
428 # for the implementations matching them.
429 #
430 # The patterns can be either fnmatch-style patterns (matched via bash
431 # == operator against PYTHON_COMPAT values) or '-2' / '-3' to indicate
432 # appropriately all enabled Python 2/3 implementations (alike
433 # python_is_python3). Remember to escape or quote the fnmatch patterns
434 # to prevent accidental shell filename expansion.
435 #
436 # Use this function when you need to request different USE flags
437 # on the Python interpreter depending on package's USE flags. If you
438 # only need a single set of interpreter USE flags, just set
439 # PYTHON_REQ_USE and use ${PYTHON_DEPS} globally.
440 #
441 # Example:
442 # @CODE
443 # PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
444 # RDEPEND="foo? ( $(python_gen_impl_dep 'xml(+)') )"
445 # @CODE
446 #
447 # It will cause the variable to look like:
448 # @CODE
449 # RDEPEND="foo? (
450 #   python_single_target_python2_7? (
451 #     dev-lang/python:2.7[xml(+)] )
452 #       python_single_target_pypy? (
453 #     dev-python/pypy[xml(+)] ) )"
454 # @CODE
455 python_gen_impl_dep() {
456         debug-print-function ${FUNCNAME} "${@}"
457
458         local impl pattern
459         local matches=()
460
461         if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
462                 flag_prefix=python_targets
463         else
464                 flag_prefix=python_single_target
465         fi
466
467         local PYTHON_REQ_USE=${1}
468         shift
469
470         local patterns=( "${@-*}" )
471         for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
472                 if _python_impl_matches "${impl}" "${patterns[@]}"; then
473                         local PYTHON_PKG_DEP
474                         python_export "${impl}" PYTHON_PKG_DEP
475                         matches+=( "${flag_prefix}_${impl}? ( ${PYTHON_PKG_DEP} )" )
476                 fi
477         done
478
479         echo "${matches[@]}"
480 }
481
482 # @FUNCTION: python_setup
483 # @DESCRIPTION:
484 # Determine what the selected Python implementation is and set
485 # the Python build environment up for it.
486 python_setup() {
487         debug-print-function ${FUNCNAME} "${@}"
488
489         unset EPYTHON
490
491         # support developer override
492         if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then
493                 local impls=( ${PYTHON_COMPAT_OVERRIDE} )
494                 [[ ${#impls[@]} -eq 1 ]] || die "PYTHON_COMPAT_OVERRIDE must name exactly one implementation for python-single-r1"
495
496                 ewarn "WARNING: PYTHON_COMPAT_OVERRIDE in effect. The following Python"
497                 ewarn "implementation will be used:"
498                 ewarn
499                 ewarn " ${PYTHON_COMPAT_OVERRIDE}"
500                 ewarn
501                 ewarn "Dependencies won't be satisfied, and PYTHON_SINGLE_TARGET flags will be ignored."
502
503                 python_export "${impls[0]}" EPYTHON PYTHON
504                 python_wrapper_setup
505                 return
506         fi
507
508         if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
509                 if use "python_targets_${_PYTHON_SUPPORTED_IMPLS[0]}"; then
510                         # Only one supported implementation, enable it explicitly
511                         python_export "${_PYTHON_SUPPORTED_IMPLS[0]}" EPYTHON PYTHON
512                         python_wrapper_setup
513                 fi
514         else
515                 local impl
516                 for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do
517                         if use "python_single_target_${impl}"; then
518                                 if [[ ${EPYTHON} ]]; then
519                                         eerror "Your PYTHON_SINGLE_TARGET setting lists more than a single Python"
520                                         eerror "implementation. Please set it to just one value. If you need"
521                                         eerror "to override the value for a single package, please use package.env"
522                                         eerror "or an equivalent solution (man 5 portage)."
523                                         echo
524                                         die "More than one implementation in PYTHON_SINGLE_TARGET."
525                                 fi
526
527                                 if ! use "python_targets_${impl}"; then
528                                         eerror "The implementation chosen as PYTHON_SINGLE_TARGET must be added"
529                                         eerror "to PYTHON_TARGETS as well. This is in order to ensure that"
530                                         eerror "dependencies are satisfied correctly. We're sorry"
531                                         eerror "for the inconvenience."
532                                         echo
533                                         die "Build target (${impl}) not in PYTHON_TARGETS."
534                                 fi
535
536                                 python_export "${impl}" EPYTHON PYTHON
537                                 python_wrapper_setup
538                         fi
539                 done
540         fi
541
542         if [[ ! ${EPYTHON} ]]; then
543                 eerror "No Python implementation selected for the build. Please set"
544                 if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
545                         eerror "the PYTHON_TARGETS variable in your make.conf to include one"
546                 else
547                         eerror "the PYTHON_SINGLE_TARGET variable in your make.conf to one"
548                 fi
549                 eerror "of the following values:"
550                 eerror
551                 eerror "${_PYTHON_SUPPORTED_IMPLS[@]}"
552                 echo
553                 die "No supported Python implementation in PYTHON_SINGLE_TARGET/PYTHON_TARGETS."
554         fi
555 }
556
557 # @FUNCTION: python-single-r1_pkg_setup
558 # @DESCRIPTION:
559 # Runs python_setup.
560 python-single-r1_pkg_setup() {
561         debug-print-function ${FUNCNAME} "${@}"
562
563         [[ ${MERGE_TYPE} != binary ]] && python_setup
564 }
565
566 _PYTHON_SINGLE_R1=1
567 fi