Merge remote-tracking branch 'github/pr/431'.
[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 if ! declare -p PYTHON_COMPAT &>/dev/null; then
99         die 'PYTHON_COMPAT not declared.'
100 fi
101 if [[ $(declare -p PYTHON_COMPAT) != "declare -a"* ]]; then
102         die 'PYTHON_COMPAT must be an array.'
103 fi
104
105 # @ECLASS-VARIABLE: PYTHON_REQ_USE
106 # @DEFAULT_UNSET
107 # @DESCRIPTION:
108 # The list of USEflags required to be enabled on the chosen Python
109 # implementations, formed as a USE-dependency string. It should be valid
110 # for all implementations in PYTHON_COMPAT, so it may be necessary to
111 # use USE defaults.
112 #
113 # This should be set before calling `inherit'.
114 #
115 # Example:
116 # @CODE
117 # PYTHON_REQ_USE="gdbm,ncurses(-)?"
118 # @CODE
119 #
120 # It will cause the Python dependencies to look like:
121 # @CODE
122 # python_single_target_pythonX_Y? ( dev-lang/python:X.Y[gdbm,ncurses(-)?] )
123 # @CODE
124
125 # @ECLASS-VARIABLE: PYTHON_DEPS
126 # @DESCRIPTION:
127 # This is an eclass-generated Python dependency string for all
128 # implementations listed in PYTHON_COMPAT.
129 #
130 # The dependency string is conditional on PYTHON_SINGLE_TARGET.
131 #
132 # Example use:
133 # @CODE
134 # RDEPEND="${PYTHON_DEPS}
135 #       dev-foo/mydep"
136 # DEPEND="${RDEPEND}"
137 # @CODE
138 #
139 # Example value:
140 # @CODE
141 # dev-lang/python-exec:=
142 # python_single_target_python2_7? ( dev-lang/python:2.7[gdbm] )
143 # python_single_target_pypy? ( virtual/pypy[gdbm] )
144 # @CODE
145
146 # @ECLASS-VARIABLE: PYTHON_USEDEP
147 # @DESCRIPTION:
148 # This is an eclass-generated USE-dependency string which can be used to
149 # depend on another Python package being built for the same Python
150 # implementations.
151 #
152 # The generate USE-flag list is compatible with packages using python-r1,
153 # python-single-r1 and python-distutils-ng eclasses. It must not be used
154 # on packages using python.eclass.
155 #
156 # Example use:
157 # @CODE
158 # RDEPEND="dev-python/foo[${PYTHON_USEDEP}]"
159 # @CODE
160 #
161 # Example value:
162 # @CODE
163 # python_targets_python2_7(-)?,python_single_target_python3_4(+)?
164 # @CODE
165
166 # @ECLASS-VARIABLE: PYTHON_REQUIRED_USE
167 # @DESCRIPTION:
168 # This is an eclass-generated required-use expression which ensures the following
169 # when more than one python implementation is possible:
170 # 1. Exactly one PYTHON_SINGLE_TARGET value has been enabled.
171 # 2. The selected PYTHON_SINGLE_TARGET value is enabled in PYTHON_TARGETS.
172 #
173 # This expression should be utilized in an ebuild by including it in
174 # REQUIRED_USE, optionally behind a use flag.
175 #
176 # Example use:
177 # @CODE
178 # REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )"
179 # @CODE
180 #
181 # Example value:
182 # @CODE
183 # python_single_target_python2_7? ( python_targets_python2_7 )
184 # python_single_target_python3_3? ( python_targets_python3_3 )
185 # ^^ ( python_single_target_python2_7 python_single_target_python3_3 )
186 # @CODE
187
188 _python_single_set_globals() {
189         local impls=()
190         local unimpls=()
191
192         PYTHON_DEPS=
193         local i PYTHON_PKG_DEP
194         for i in "${_PYTHON_ALL_IMPLS[@]}"; do
195                 has "${i}" "${PYTHON_COMPAT[@]}" \
196                         && impls+=( "${i}" ) \
197                         || unimpls+=( "${i}" )
198         done
199
200         if [[ ${#impls[@]} -eq 0 ]]; then
201                 die "No supported implementation in PYTHON_COMPAT."
202         fi
203
204         local flags_mt=( "${impls[@]/#/python_targets_}" )
205         local flags=( "${impls[@]/#/python_single_target_}" )
206         local unflags=( "${unimpls[@]/#/-python_single_target_}" )
207
208         local optflags=${flags_mt[@]/%/(-)?},${unflags[@]/%/(-)}
209
210         IUSE="${flags_mt[*]}"
211
212         if [[ ${#impls[@]} -eq 1 ]]; then
213                 # There is only one supported implementation; set IUSE and other
214                 # variables without PYTHON_SINGLE_TARGET.
215                 PYTHON_REQUIRED_USE="${flags_mt[*]}"
216                 python_export "${impls[0]}" PYTHON_PKG_DEP
217                 PYTHON_DEPS="${PYTHON_PKG_DEP} "
218                 # Force on the python_single_target_* flag for this impl, so
219                 # that any dependencies that inherit python-single-r1 and
220                 # happen to have multiple implementations will still need
221                 # to bound by the implementation used by this package.
222                 optflags+=,${flags[0]/%/(+)}
223         else
224                 # Multiple supported implementations; honor PYTHON_SINGLE_TARGET.
225                 IUSE+=" ${flags[*]}"
226                 PYTHON_REQUIRED_USE="^^ ( ${flags[*]} )"
227                 # Ensure deps honor the same python_single_target_* flag as is set
228                 # on this package.
229                 optflags+=,${flags[@]/%/(+)?}
230
231                 for i in "${impls[@]}"; do
232                         # The chosen targets need to be in PYTHON_TARGETS as well.
233                         # This is in order to enforce correct dependencies on packages
234                         # supporting multiple implementations.
235                         PYTHON_REQUIRED_USE+=" python_single_target_${i}? ( python_targets_${i} )"
236
237                         python_export "${i}" PYTHON_PKG_DEP
238                         PYTHON_DEPS+="python_single_target_${i}? ( ${PYTHON_PKG_DEP} ) "
239                 done
240         fi
241         declare -g -r PYTHON_USEDEP=${optflags// /,}
242
243         # 1) well, python-exec would suffice as an RDEP
244         # but no point in making this overcomplex, BDEP doesn't hurt anyone
245         # 2) python-exec should be built with all targets forced anyway
246         # but if new targets were added, we may need to force a rebuild
247         # 3) use whichever python-exec slot installed in EAPI 5. For EAPI 4,
248         # just fix :2 since := deps are not supported.
249         if [[ ${_PYTHON_WANT_PYTHON_EXEC2} == 0 ]]; then
250                 die "python-exec:0 is no longer supported, please fix your ebuild to work with python-exec:2"
251         elif [[ ${EAPI} != 4 ]]; then
252                 PYTHON_DEPS+=">=dev-lang/python-exec-2:=[${PYTHON_USEDEP}]"
253         else
254                 PYTHON_DEPS+="dev-lang/python-exec:2[${PYTHON_USEDEP}]"
255         fi
256         readonly PYTHON_DEPS PYTHON_REQUIRED_USE
257 }
258 _python_single_set_globals
259 unset -f _python_single_set_globals
260
261 # @FUNCTION: python_gen_usedep
262 # @USAGE: <pattern> [...]
263 # @DESCRIPTION:
264 # Output a USE dependency string for Python implementations which
265 # are both in PYTHON_COMPAT and match any of the patterns passed
266 # as parameters to the function.
267 #
268 # Remember to escape or quote the patterns to prevent shell filename
269 # expansion.
270 #
271 # When all implementations are requested, please use ${PYTHON_USEDEP}
272 # instead. Please also remember to set an appropriate REQUIRED_USE
273 # to avoid ineffective USE flags.
274 #
275 # Example:
276 # @CODE
277 # PYTHON_COMPAT=( python{2_7,3_4} )
278 # DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep 'python2*')] )"
279 # @CODE
280 #
281 # It will cause the dependency to look like:
282 # @CODE
283 # DEPEND="doc? ( dev-python/epydoc[python_targets_python2_7(-)?,...] )"
284 # @CODE
285 python_gen_usedep() {
286         debug-print-function ${FUNCNAME} "${@}"
287
288         local impl pattern
289         local matches=()
290
291         for impl in "${PYTHON_COMPAT[@]}"; do
292                 _python_impl_supported "${impl}" || continue
293
294                 for pattern; do
295                         if [[ ${impl} == ${pattern} ]]; then
296                                 matches+=(
297                                         "python_targets_${impl}(-)?"
298                                         "python_single_target_${impl}(+)?"
299                                 )
300                                 break
301                         fi
302                 done
303         done
304
305         [[ ${matches[@]} ]] || die "No supported implementations match python_gen_usedep patterns: ${@}"
306
307         local out=${matches[@]}
308         echo "${out// /,}"
309 }
310
311 # @FUNCTION: python_gen_useflags
312 # @USAGE: <pattern> [...]
313 # @DESCRIPTION:
314 # Output a list of USE flags for Python implementations which
315 # are both in PYTHON_COMPAT and match any of the patterns passed
316 # as parameters to the function.
317 #
318 # Example:
319 # @CODE
320 # PYTHON_COMPAT=( python{2_7,3_4} )
321 # REQUIRED_USE="doc? ( ^^ ( $(python_gen_useflags 'python2*') ) )"
322 # @CODE
323 #
324 # It will cause the variable to look like:
325 # @CODE
326 # REQUIRED_USE="doc? ( ^^ ( python_single_target_python2_7 ) )"
327 # @CODE
328 python_gen_useflags() {
329         debug-print-function ${FUNCNAME} "${@}"
330
331         local impl pattern
332         local matches=()
333
334         for impl in "${PYTHON_COMPAT[@]}"; do
335                 _python_impl_supported "${impl}" || continue
336
337                 for pattern; do
338                         if [[ ${impl} == ${pattern} ]]; then
339                                 matches+=( "python_single_target_${impl}" )
340                                 break
341                         fi
342                 done
343         done
344
345         echo "${matches[@]}"
346 }
347
348 # @FUNCTION: python_gen_cond_dep
349 # @USAGE: <dependency> <pattern> [...]
350 # @DESCRIPTION:
351 # Output a list of <dependency>-ies made conditional to USE flags
352 # of Python implementations which are both in PYTHON_COMPAT and match
353 # any of the patterns passed as the remaining parameters.
354 #
355 # In order to enforce USE constraints on the packages, verbatim
356 # '${PYTHON_USEDEP}' (quoted!) may be placed in the dependency
357 # specification. It will get expanded within the function into a proper
358 # USE dependency string.
359 #
360 # Example:
361 # @CODE
362 # PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
363 # RDEPEND="$(python_gen_cond_dep \
364 #   'dev-python/unittest2[${PYTHON_USEDEP}]' python2_7 pypy )"
365 # @CODE
366 #
367 # It will cause the variable to look like:
368 # @CODE
369 # RDEPEND="python_single_target_python2_7? (
370 #     dev-python/unittest2[python_targets_python2_7(-)?,...] )
371 #       python_single_target_pypy? (
372 #     dev-python/unittest2[python_targets_pypy(-)?,...] )"
373 # @CODE
374 python_gen_cond_dep() {
375         debug-print-function ${FUNCNAME} "${@}"
376
377         local impl pattern
378         local matches=()
379
380         local dep=${1}
381         shift
382
383         for impl in "${PYTHON_COMPAT[@]}"; do
384                 _python_impl_supported "${impl}" || continue
385
386                 for pattern; do
387                         if [[ ${impl} == ${pattern} ]]; then
388                                 # substitute ${PYTHON_USEDEP} if used
389                                 # (since python_gen_usedep() will not return ${PYTHON_USEDEP}
390                                 #  the code is run at most once)
391                                 if [[ ${dep} == *'${PYTHON_USEDEP}'* ]]; then
392                                         local usedep=$(python_gen_usedep "${@}")
393                                         dep=${dep//\$\{PYTHON_USEDEP\}/${usedep}}
394                                 fi
395
396                                 matches+=( "python_single_target_${impl}? ( ${dep} )" )
397                                 break
398                         fi
399                 done
400         done
401
402         echo "${matches[@]}"
403 }
404
405 # @FUNCTION: python_setup
406 # @DESCRIPTION:
407 # Determine what the selected Python implementation is and set
408 # the Python build environment up for it.
409 python_setup() {
410         debug-print-function ${FUNCNAME} "${@}"
411
412         unset EPYTHON
413
414         local impl impls=()
415         for impl in "${PYTHON_COMPAT[@]}"; do
416                 _python_impl_supported "${impl}" || continue
417                 impls+=( "${impl}" )
418         done
419
420         if [[ ${#impls[@]} -eq 1 ]]; then
421                 if use "python_targets_${impls[0]}"; then
422                         # Only one supported implementation, enable it explicitly
423                         python_export "${impls[0]}" EPYTHON PYTHON
424                         python_wrapper_setup
425                 fi
426         else
427                 for impl in "${impls[@]}"; do
428                         if use "python_single_target_${impl}"; then
429                                 if [[ ${EPYTHON} ]]; then
430                                         eerror "Your PYTHON_SINGLE_TARGET setting lists more than a single Python"
431                                         eerror "implementation. Please set it to just one value. If you need"
432                                         eerror "to override the value for a single package, please use package.env"
433                                         eerror "or an equivalent solution (man 5 portage)."
434                                         echo
435                                         die "More than one implementation in PYTHON_SINGLE_TARGET."
436                                 fi
437
438                                 if ! use "python_targets_${impl}"; then
439                                         eerror "The implementation chosen as PYTHON_SINGLE_TARGET must be added"
440                                         eerror "to PYTHON_TARGETS as well. This is in order to ensure that"
441                                         eerror "dependencies are satisfied correctly. We're sorry"
442                                         eerror "for the inconvenience."
443                                         echo
444                                         die "Build target (${impl}) not in PYTHON_TARGETS."
445                                 fi
446
447                                 python_export "${impl}" EPYTHON PYTHON
448                                 python_wrapper_setup
449                         fi
450                 done
451         fi
452
453         if [[ ! ${EPYTHON} ]]; then
454                 eerror "No Python implementation selected for the build. Please set"
455                 if [[ ${#impls[@]} -eq 1 ]]; then
456                         eerror "the PYTHON_TARGETS variable in your make.conf to include one"
457                 else
458                         eerror "the PYTHON_SINGLE_TARGET variable in your make.conf to one"
459                 fi
460                 eerror "of the following values:"
461                 eerror
462                 eerror "${impls[@]}"
463                 echo
464                 die "No supported Python implementation in PYTHON_SINGLE_TARGET/PYTHON_TARGETS."
465         fi
466 }
467
468 # @FUNCTION: python-single-r1_pkg_setup
469 # @DESCRIPTION:
470 # Runs python_setup.
471 python-single-r1_pkg_setup() {
472         debug-print-function ${FUNCNAME} "${@}"
473
474         [[ ${MERGE_TYPE} != binary ]] && python_setup
475 }
476
477 _PYTHON_SINGLE_R1=1
478 fi