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