Merge remote-tracking branch 'remotes/joe-konno-gitlab/topic/gentoo-565434-v2'
[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         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 }
257 _python_single_set_globals
258
259 # @FUNCTION: python_gen_usedep
260 # @USAGE: <pattern> [...]
261 # @DESCRIPTION:
262 # Output a USE dependency string for Python implementations which
263 # are both in PYTHON_COMPAT and match any of the patterns passed
264 # as parameters to the function.
265 #
266 # Remember to escape or quote the patterns to prevent shell filename
267 # expansion.
268 #
269 # When all implementations are requested, please use ${PYTHON_USEDEP}
270 # instead. Please also remember to set an appropriate REQUIRED_USE
271 # to avoid ineffective USE flags.
272 #
273 # Example:
274 # @CODE
275 # PYTHON_COMPAT=( python{2_7,3_4} )
276 # DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep 'python2*')] )"
277 # @CODE
278 #
279 # It will cause the dependency to look like:
280 # @CODE
281 # DEPEND="doc? ( dev-python/epydoc[python_targets_python2_7(-)?,...] )"
282 # @CODE
283 python_gen_usedep() {
284         debug-print-function ${FUNCNAME} "${@}"
285
286         local impl pattern
287         local matches=()
288
289         for impl in "${PYTHON_COMPAT[@]}"; do
290                 _python_impl_supported "${impl}" || continue
291
292                 for pattern; do
293                         if [[ ${impl} == ${pattern} ]]; then
294                                 matches+=(
295                                         "python_targets_${impl}(-)?"
296                                         "python_single_target_${impl}(+)?"
297                                 )
298                                 break
299                         fi
300                 done
301         done
302
303         [[ ${matches[@]} ]] || die "No supported implementations match python_gen_usedep patterns: ${@}"
304
305         local out=${matches[@]}
306         echo "${out// /,}"
307 }
308
309 # @FUNCTION: python_gen_useflags
310 # @USAGE: <pattern> [...]
311 # @DESCRIPTION:
312 # Output a list of USE flags for Python implementations which
313 # are both in PYTHON_COMPAT and match any of the patterns passed
314 # as parameters to the function.
315 #
316 # Example:
317 # @CODE
318 # PYTHON_COMPAT=( python{2_7,3_4} )
319 # REQUIRED_USE="doc? ( ^^ ( $(python_gen_useflags 'python2*') ) )"
320 # @CODE
321 #
322 # It will cause the variable to look like:
323 # @CODE
324 # REQUIRED_USE="doc? ( ^^ ( python_single_target_python2_7 ) )"
325 # @CODE
326 python_gen_useflags() {
327         debug-print-function ${FUNCNAME} "${@}"
328
329         local impl pattern
330         local matches=()
331
332         for impl in "${PYTHON_COMPAT[@]}"; do
333                 _python_impl_supported "${impl}" || continue
334
335                 for pattern; do
336                         if [[ ${impl} == ${pattern} ]]; then
337                                 matches+=( "python_single_target_${impl}" )
338                                 break
339                         fi
340                 done
341         done
342
343         echo "${matches[@]}"
344 }
345
346 # @FUNCTION: python_gen_cond_dep
347 # @USAGE: <dependency> <pattern> [...]
348 # @DESCRIPTION:
349 # Output a list of <dependency>-ies made conditional to USE flags
350 # of Python implementations which are both in PYTHON_COMPAT and match
351 # any of the patterns passed as the remaining parameters.
352 #
353 # In order to enforce USE constraints on the packages, verbatim
354 # '${PYTHON_USEDEP}' (quoted!) may be placed in the dependency
355 # specification. It will get expanded within the function into a proper
356 # USE dependency string.
357 #
358 # Example:
359 # @CODE
360 # PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy )
361 # RDEPEND="$(python_gen_cond_dep \
362 #   'dev-python/unittest2[${PYTHON_USEDEP}]' python2_7 pypy )"
363 # @CODE
364 #
365 # It will cause the variable to look like:
366 # @CODE
367 # RDEPEND="python_single_target_python2_7? (
368 #     dev-python/unittest2[python_targets_python2_7(-)?,...] )
369 #       python_single_target_pypy? (
370 #     dev-python/unittest2[python_targets_pypy(-)?,...] )"
371 # @CODE
372 python_gen_cond_dep() {
373         debug-print-function ${FUNCNAME} "${@}"
374
375         local impl pattern
376         local matches=()
377
378         local dep=${1}
379         shift
380
381         for impl in "${PYTHON_COMPAT[@]}"; do
382                 _python_impl_supported "${impl}" || continue
383
384                 for pattern; do
385                         if [[ ${impl} == ${pattern} ]]; then
386                                 # substitute ${PYTHON_USEDEP} if used
387                                 # (since python_gen_usedep() will not return ${PYTHON_USEDEP}
388                                 #  the code is run at most once)
389                                 if [[ ${dep} == *'${PYTHON_USEDEP}'* ]]; then
390                                         local PYTHON_USEDEP=$(python_gen_usedep "${@}")
391                                         dep=${dep//\$\{PYTHON_USEDEP\}/${PYTHON_USEDEP}}
392                                 fi
393
394                                 matches+=( "python_single_target_${impl}? ( ${dep} )" )
395                                 break
396                         fi
397                 done
398         done
399
400         echo "${matches[@]}"
401 }
402
403 # @FUNCTION: python_setup
404 # @DESCRIPTION:
405 # Determine what the selected Python implementation is and set
406 # the Python build environment up for it.
407 python_setup() {
408         debug-print-function ${FUNCNAME} "${@}"
409
410         unset EPYTHON
411
412         local impl impls=()
413         for impl in "${PYTHON_COMPAT[@]}"; do
414                 _python_impl_supported "${impl}" || continue
415                 impls+=( "${impl}" )
416         done
417
418         if [[ ${#impls[@]} -eq 1 ]]; then
419                 if use "python_targets_${impls[0]}"; then
420                         # Only one supported implementation, enable it explicitly
421                         python_export "${impls[0]}" EPYTHON PYTHON
422                         python_wrapper_setup
423                 fi
424         else
425                 for impl in "${impls[@]}"; do
426                         if use "python_single_target_${impl}"; then
427                                 if [[ ${EPYTHON} ]]; then
428                                         eerror "Your PYTHON_SINGLE_TARGET setting lists more than a single Python"
429                                         eerror "implementation. Please set it to just one value. If you need"
430                                         eerror "to override the value for a single package, please use package.env"
431                                         eerror "or an equivalent solution (man 5 portage)."
432                                         echo
433                                         die "More than one implementation in PYTHON_SINGLE_TARGET."
434                                 fi
435
436                                 if ! use "python_targets_${impl}"; then
437                                         eerror "The implementation chosen as PYTHON_SINGLE_TARGET must be added"
438                                         eerror "to PYTHON_TARGETS as well. This is in order to ensure that"
439                                         eerror "dependencies are satisfied correctly. We're sorry"
440                                         eerror "for the inconvenience."
441                                         echo
442                                         die "Build target (${impl}) not in PYTHON_TARGETS."
443                                 fi
444
445                                 python_export "${impl}" EPYTHON PYTHON
446                                 python_wrapper_setup
447                         fi
448                 done
449         fi
450
451         if [[ ! ${EPYTHON} ]]; then
452                 eerror "No Python implementation selected for the build. Please set"
453                 if [[ ${#impls[@]} -eq 1 ]]; then
454                         eerror "the PYTHON_TARGETS variable in your make.conf to include one"
455                 else
456                         eerror "the PYTHON_SINGLE_TARGET variable in your make.conf to one"
457                 fi
458                 eerror "of the following values:"
459                 eerror
460                 eerror "${impls[@]}"
461                 echo
462                 die "No supported Python implementation in PYTHON_SINGLE_TARGET/PYTHON_TARGETS."
463         fi
464 }
465
466 # @FUNCTION: python-single-r1_pkg_setup
467 # @DESCRIPTION:
468 # Runs python_setup.
469 python-single-r1_pkg_setup() {
470         debug-print-function ${FUNCNAME} "${@}"
471
472         [[ ${MERGE_TYPE} != binary ]] && python_setup
473 }
474
475 _PYTHON_SINGLE_R1=1
476 fi