/[gentoo-x86]/eclass/python-r1.eclass
Gentoo

Contents of /eclass/python-r1.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.36 - (show annotations) (download)
Tue Jan 8 16:36:16 2013 UTC (22 months, 1 week ago) by mgorny
Branch: MAIN
Changes since 1.35: +30 -2 lines
Manually check PYTHON_TARGETS and PYTHON_SINGLE_TARGET for validity rather than using REQUIRED_USE. Fixes bug #447808.

1 # Copyright 1999-2013 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Header: /var/cvsroot/gentoo-x86/eclass/python-r1.eclass,v 1.35 2013/01/04 01:26:22 floppym Exp $
4
5 # @ECLASS: python-r1
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: A common, simple eclass for Python packages.
12 # @DESCRIPTION:
13 # A common eclass providing helper functions to build and install
14 # packages supporting being installed for multiple Python
15 # implementations.
16 #
17 # This eclass sets correct IUSE and REQUIRED_USE. It exports PYTHON_DEPS
18 # and PYTHON_USEDEP so you can create correct dependencies for your
19 # package easily. It also provides methods to easily run a command for
20 # each enabled Python implementation and duplicate the sources for them.
21 #
22 # Please note that python-r1 will always inherit python-utils-r1 as
23 # well. Thus, all the functions defined there can be used
24 # in the packages using python-r1, and there is no need ever to inherit
25 # both.
26 #
27 # For more information, please see the python-r1 Developer's Guide:
28 # http://www.gentoo.org/proj/en/Python/python-r1/dev-guide.xml
29
30 case "${EAPI:-0}" in
31 0|1|2|3|4)
32 die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
33 ;;
34 5)
35 # EAPI=5 is required for meaningful USE default deps
36 # on USE_EXPAND flags
37 ;;
38 *)
39 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
40 ;;
41 esac
42
43 if [[ ! ${_PYTHON_R1} ]]; then
44
45 if [[ ${_PYTHON_SINGLE_R1} ]]; then
46 die 'python-r1.eclass can not be used with python-single-r1.eclass.'
47 elif [[ ${_PYTHON_ANY_R1} ]]; then
48 die 'python-r1.eclass can not be used with python-any-r1.eclass.'
49 fi
50
51 inherit python-utils-r1
52
53 # @ECLASS-VARIABLE: PYTHON_COMPAT
54 # @REQUIRED
55 # @DESCRIPTION:
56 # This variable contains a list of Python implementations the package
57 # supports. It must be set before the `inherit' call. It has to be
58 # an array.
59 #
60 # Example:
61 # @CODE
62 # PYTHON_COMPAT=( python2_5 python2_6 python2_7 )
63 # @CODE
64 #
65 # Please note that you can also use bash brace expansion if you like:
66 # @CODE
67 # PYTHON_COMPAT=( python{2_5,2_6,2_7} )
68 # @CODE
69 if ! declare -p PYTHON_COMPAT &>/dev/null; then
70 if [[ ${CATEGORY}/${PN} == dev-python/python-exec ]]; then
71 PYTHON_COMPAT=( "${_PYTHON_ALL_IMPLS[@]}" )
72 else
73 die 'PYTHON_COMPAT not declared.'
74 fi
75 fi
76
77 # @ECLASS-VARIABLE: PYTHON_REQ_USE
78 # @DEFAULT_UNSET
79 # @DESCRIPTION:
80 # The list of USEflags required to be enabled on the chosen Python
81 # implementations, formed as a USE-dependency string. It should be valid
82 # for all implementations in PYTHON_COMPAT, so it may be necessary to
83 # use USE defaults.
84 #
85 # Example:
86 # @CODE
87 # PYTHON_REQ_USE="gdbm,ncurses(-)?"
88 # @CODE
89 #
90 # It will cause the Python dependencies to look like:
91 # @CODE
92 # python_targets_pythonX_Y? ( dev-lang/python:X.Y[gdbm,ncurses(-)?] )
93 # @CODE
94
95 # @ECLASS-VARIABLE: PYTHON_DEPS
96 # @DESCRIPTION:
97 # This is an eclass-generated Python dependency string for all
98 # implementations listed in PYTHON_COMPAT.
99 #
100 # Example use:
101 # @CODE
102 # RDEPEND="${PYTHON_DEPS}
103 # dev-foo/mydep"
104 # DEPEND="${RDEPEND}"
105 # @CODE
106 #
107 # Example value:
108 # @CODE
109 # dev-python/python-exec
110 # python_targets_python2_6? ( dev-lang/python:2.6[gdbm] )
111 # python_targets_python2_7? ( dev-lang/python:2.7[gdbm] )
112 # @CODE
113
114 # @ECLASS-VARIABLE: PYTHON_USEDEP
115 # @DESCRIPTION:
116 # This is an eclass-generated USE-dependency string which can be used to
117 # depend on another Python package being built for the same Python
118 # implementations.
119 #
120 # The generate USE-flag list is compatible with packages using python-r1
121 # and python-distutils-ng eclasses. It must not be used on packages
122 # using python.eclass.
123 #
124 # Example use:
125 # @CODE
126 # RDEPEND="dev-python/foo[${PYTHON_USEDEP}]"
127 # @CODE
128 #
129 # Example value:
130 # @CODE
131 # python_targets_python2_6?,python_targets_python2_7?
132 # @CODE
133
134 _python_set_globals() {
135 local flags=( "${PYTHON_COMPAT[@]/#/python_targets_}" )
136 local optflags=${flags[@]/%/?}
137
138 # A nice QA trick here. Since a python-single-r1 package has to have
139 # at least one PYTHON_SINGLE_TARGET enabled (REQUIRED_USE),
140 # the following check will always fail on those packages. Therefore,
141 # it should prevent developers from mistakenly depending on packages
142 # not supporting multiple Python implementations.
143
144 local flags_st=( "${PYTHON_COMPAT[@]/#/-python_single_target_}" )
145 optflags+=,${flags_st[@]/%/(-)}
146
147 IUSE=${flags[*]}
148 #REQUIRED_USE="|| ( ${flags[*]} )"
149 PYTHON_USEDEP=${optflags// /,}
150
151 # 1) well, python-exec would suffice as an RDEP
152 # but no point in making this overcomplex, BDEP doesn't hurt anyone
153 # 2) python-exec should be built with all targets forced anyway
154 # but if new targets were added, we may need to force a rebuild
155 PYTHON_DEPS="dev-python/python-exec[${PYTHON_USEDEP}]"
156 local i PYTHON_PKG_DEP
157 for i in "${PYTHON_COMPAT[@]}"; do
158 python_export "${i}" PYTHON_PKG_DEP
159 PYTHON_DEPS+=" python_targets_${i}? ( ${PYTHON_PKG_DEP} )"
160 done
161 }
162 _python_set_globals
163
164 # @FUNCTION: _python_validate_useflags
165 # @INTERNAL
166 # @DESCRIPTION:
167 # Enforce the proper setting of PYTHON_TARGETS.
168 _python_validate_useflags() {
169 debug-print-function ${FUNCNAME} "${@}"
170
171 local i
172
173 for i in "${PYTHON_COMPAT[@]}"; do
174 use "python_targets_${i}" && return 0
175 done
176
177 eerror "No Python implementation selected for the build. Please add one"
178 eerror "of the following values to your PYTHON_TARGETS (in make.conf):"
179 eerror
180 eerror "${PYTHON_COMPAT[@]}"
181 echo
182 die "No supported Python implementation in PYTHON_TARGETS."
183 }
184
185 # @FUNCTION: python_gen_usedep
186 # @USAGE: <pattern> [...]
187 # @DESCRIPTION:
188 # Output a USE dependency string for Python implementations which
189 # are both in PYTHON_COMPAT and match any of the patterns passed
190 # as parameters to the function.
191 #
192 # When all implementations are requested, please use ${PYTHON_USEDEP}
193 # instead. Please also remember to set an appropriate REQUIRED_USE
194 # to avoid ineffective USE flags.
195 #
196 # Example:
197 # @CODE
198 # PYTHON_COMPAT=( python{2_7,3_2} )
199 # DEPEND="doc? ( dev-python/epydoc[$(python_gen_usedep python2*)] )"
200 # @CODE
201 #
202 # It will cause the dependency to look like:
203 # @CODE
204 # DEPEND="doc? ( dev-python/epydoc[python_targets_python2_7?] )"
205 # @CODE
206 python_gen_usedep() {
207 debug-print-function ${FUNCNAME} "${@}"
208
209 local impl pattern
210 local matches=()
211
212 for impl in "${PYTHON_COMPAT[@]}"; do
213 for pattern; do
214 if [[ ${impl} == ${pattern} ]]; then
215 matches+=(
216 "python_targets_${impl}?"
217 "-python_single_target_${impl}(-)"
218 )
219 break
220 fi
221 done
222 done
223
224 local out=${matches[@]}
225 echo ${out// /,}
226 }
227
228 # @FUNCTION: python_gen_useflags
229 # @USAGE: <pattern> [...]
230 # @DESCRIPTION:
231 # Output a list of USE flags for Python implementations which
232 # are both in PYTHON_COMPAT and match any of the patterns passed
233 # as parameters to the function.
234 #
235 # Example:
236 # @CODE
237 # PYTHON_COMPAT=( python{2_7,3_2} )
238 # REQUIRED_USE="doc? ( || ( $(python_gen_useflags python2*) ) )"
239 # @CODE
240 #
241 # It will cause the variable to look like:
242 # @CODE
243 # REQUIRED_USE="doc? ( || ( python_targets_python2_7 ) )"
244 # @CODE
245 python_gen_useflags() {
246 debug-print-function ${FUNCNAME} "${@}"
247
248 local impl pattern
249 local matches=()
250
251 for impl in "${PYTHON_COMPAT[@]}"; do
252 for pattern; do
253 if [[ ${impl} == ${pattern} ]]; then
254 matches+=( "python_targets_${impl}" )
255 break
256 fi
257 done
258 done
259
260 echo ${matches[@]}
261 }
262
263 # @FUNCTION: python_gen_cond_dep
264 # @USAGE: <dependency> <pattern> [...]
265 # @DESCRIPTION:
266 # Output a list of <dependency>-ies made conditional to USE flags
267 # of Python implementations which are both in PYTHON_COMPAT and match
268 # any of the patterns passed as the remaining parameters.
269 #
270 # Please note that USE constraints on the package need to be enforced
271 # separately. Therefore, the dependency usually needs to use
272 # python_gen_usedep as well.
273 #
274 # Example:
275 # @CODE
276 # PYTHON_COMPAT=( python{2_5,2_6,2_7} )
277 # RDEPEND="$(python_gen_cond_dep dev-python/unittest2 python{2_5,2_6})"
278 # @CODE
279 #
280 # It will cause the variable to look like:
281 # @CODE
282 # RDEPEND="python_targets_python2_5? ( dev-python/unittest2 )
283 # python_targets_python2_6? ( dev-python/unittest2 )"
284 # @CODE
285 python_gen_cond_dep() {
286 debug-print-function ${FUNCNAME} "${@}"
287
288 local impl pattern
289 local matches=()
290
291 local dep=${1}
292 shift
293
294 for impl in "${PYTHON_COMPAT[@]}"; do
295 for pattern; do
296 if [[ ${impl} == ${pattern} ]]; then
297 matches+=( "python_targets_${impl}? ( ${dep} )" )
298 break
299 fi
300 done
301 done
302
303 echo ${matches[@]}
304 }
305
306 # @ECLASS-VARIABLE: BUILD_DIR
307 # @DESCRIPTION:
308 # The current build directory. In global scope, it is supposed to
309 # contain an initial build directory; if unset, it defaults to ${S}.
310 #
311 # In functions run by python_foreach_impl(), the BUILD_DIR is locally
312 # set to an implementation-specific build directory. That path is
313 # created through appending a hyphen and the implementation name
314 # to the final component of the initial BUILD_DIR.
315 #
316 # Example value:
317 # @CODE
318 # ${WORKDIR}/foo-1.3-python2_6
319 # @CODE
320
321 # @FUNCTION: python_copy_sources
322 # @DESCRIPTION:
323 # Create a single copy of the package sources (${S}) for each enabled
324 # Python implementation.
325 #
326 # The sources are always copied from S to implementation-specific build
327 # directories respecting BUILD_DIR.
328 python_copy_sources() {
329 debug-print-function ${FUNCNAME} "${@}"
330
331 _python_validate_useflags
332
333 local impl
334 local bdir=${BUILD_DIR:-${S}}
335
336 debug-print "${FUNCNAME}: bdir = ${bdir}"
337 einfo "Will copy sources from ${S}"
338 # the order is irrelevant here
339 for impl in "${PYTHON_COMPAT[@]}"; do
340 if use "python_targets_${impl}"
341 then
342 local BUILD_DIR=${bdir%%/}-${impl}
343
344 einfo "${impl}: copying to ${BUILD_DIR}"
345 debug-print "${FUNCNAME}: [${impl}] cp ${S} => ${BUILD_DIR}"
346 cp -pr "${S}" "${BUILD_DIR}" || die
347 fi
348 done
349 }
350
351 # @FUNCTION: _python_check_USE_PYTHON
352 # @INTERNAL
353 # @DESCRIPTION:
354 # Check whether USE_PYTHON and PYTHON_TARGETS are in sync. Output
355 # warnings if they are not.
356 _python_check_USE_PYTHON() {
357 debug-print-function ${FUNCNAME} "${@}"
358
359 if [[ ! ${_PYTHON_USE_PYTHON_CHECKED} ]]; then
360 _PYTHON_USE_PYTHON_CHECKED=1
361
362 # python-exec has profile-forced flags.
363 if [[ ${CATEGORY}/${PN} == dev-python/python-exec ]]; then
364 return
365 fi
366
367 _try_eselect() {
368 # The eselect solution will work only with one py2 & py3.
369
370 local impl py2 py3 dis_py2 dis_py3
371 for impl in "${PYTHON_COMPAT[@]}"; do
372 if use "python_targets_${impl}"; then
373 case "${impl}" in
374 python2_*)
375 if [[ ${py2+1} ]]; then
376 debug-print "${FUNCNAME}: -> more than one py2: ${py2} ${impl}"
377 return 1
378 fi
379 py2=${impl/_/.}
380 ;;
381 python3_*)
382 if [[ ${py3+1} ]]; then
383 debug-print "${FUNCNAME}: -> more than one py3: ${py3} ${impl}"
384 return 1
385 fi
386 py3=${impl/_/.}
387 ;;
388 *)
389 return 1
390 ;;
391 esac
392 else
393 case "${impl}" in
394 python2_*)
395 dis_py2=1
396 ;;
397 python3_*)
398 dis_py3=1
399 ;;
400 esac
401 fi
402 done
403
404 # The eselect solution won't work if the disabled Python version
405 # is installed.
406 if [[ ! ${py2+1} && ${dis_py2} ]]; then
407 debug-print "${FUNCNAME}: -> all py2 versions disabled"
408 if ! has python2_7 "${PYTHON_COMPAT[@]}"; then
409 debug-print "${FUNCNAME}: ---> package does not support 2.7"
410 return 0
411 fi
412 if has_version '=dev-lang/python-2*'; then
413 debug-print "${FUNCNAME}: ---> but =python-2* installed!"
414 return 1
415 fi
416 fi
417 if [[ ! ${py3+1} && ${dis_py3} ]]; then
418 debug-print "${FUNCNAME}: -> all py3 versions disabled"
419 if ! has python3_2 "${PYTHON_COMPAT[@]}"; then
420 debug-print "${FUNCNAME}: ---> package does not support 3.2"
421 return 0
422 fi
423 if has_version '=dev-lang/python-3*'; then
424 debug-print "${FUNCNAME}: ---> but =python-3* installed!"
425 return 1
426 fi
427 fi
428
429 local warned
430
431 # Now check whether the correct implementations are active.
432 if [[ ${py2+1} ]]; then
433 local sel_py2=$(eselect python show --python2)
434
435 debug-print "${FUNCNAME}: -> py2 built: ${py2}, active: ${sel_py2}"
436 if [[ ${py2} != ${sel_py2} ]]; then
437 ewarn "Building package for ${py2} only while ${sel_py2} is active."
438 ewarn "Please consider switching the active Python 2 interpreter:"
439 ewarn
440 ewarn " eselect python set --python2 ${py2}"
441 warned=1
442 fi
443 fi
444
445 if [[ ${py3+1} ]]; then
446 local sel_py3=$(eselect python show --python3)
447
448 debug-print "${FUNCNAME}: -> py3 built: ${py3}, active: ${sel_py3}"
449 if [[ ${py3} != ${sel_py3} ]]; then
450 [[ ${warned} ]] && ewarn
451 ewarn "Building package for ${py3} only while ${sel_py3} is active."
452 ewarn "Please consider switching the active Python 3 interpreter:"
453 ewarn
454 ewarn " eselect python set --python3 ${py3}"
455 warned=1
456 fi
457 fi
458
459 if [[ ${warned} ]]; then
460 ewarn
461 ewarn "Please note that after switching the active Python interpreter,"
462 ewarn "you may need to run 'python-updater' to rebuild affected packages."
463 ewarn
464 ewarn "For more information on python.eclass compatibility, please see"
465 ewarn "the appropriate python-r1 User's Guide chapter [1]."
466 ewarn
467 ewarn "[1] http://www.gentoo.org/proj/en/Python/python-r1/user-guide.xml#doc_chap2"
468 fi
469 }
470
471 # If user has no USE_PYTHON, try to avoid it.
472 if [[ ! ${USE_PYTHON} ]]; then
473 debug-print "${FUNCNAME}: trying eselect solution ..."
474 _try_eselect && return
475 fi
476
477 debug-print "${FUNCNAME}: trying USE_PYTHON solution ..."
478 debug-print "${FUNCNAME}: -> USE_PYTHON=${USE_PYTHON}"
479
480 local impl old=${USE_PYTHON} new=() removed=()
481
482 for impl in "${PYTHON_COMPAT[@]}"; do
483 local abi
484 case "${impl}" in
485 python*)
486 abi=${impl#python}
487 ;;
488 jython*)
489 abi=${impl#jython}-jython
490 ;;
491 pypy*)
492 abi=2.7-pypy-${impl#pypy}
493 ;;
494 *)
495 die "Unexpected Python implementation: ${impl}"
496 ;;
497 esac
498 abi=${abi/_/.}
499
500 has "${abi}" ${USE_PYTHON}
501 local has_abi=${?}
502 use "python_targets_${impl}"
503 local has_impl=${?}
504
505 # 0 = has, 1 = does not have
506 if [[ ${has_abi} == 0 && ${has_impl} == 1 ]]; then
507 debug-print "${FUNCNAME}: ---> remove ${abi}"
508 # remove from USE_PYTHON
509 old=${old/${abi}/}
510 removed+=( ${abi} )
511 elif [[ ${has_abi} == 1 && ${has_impl} == 0 ]]; then
512 debug-print "${FUNCNAME}: ---> add ${abi}"
513 # add to USE_PYTHON
514 new+=( ${abi} )
515 fi
516 done
517
518 if [[ ${removed[@]} || ${new[@]} ]]; then
519 old=( ${old} )
520
521 debug-print "${FUNCNAME}: -> old: ${old[@]}"
522 debug-print "${FUNCNAME}: -> new: ${new[@]}"
523 debug-print "${FUNCNAME}: -> removed: ${removed[@]}"
524
525 if [[ ${USE_PYTHON} ]]; then
526 ewarn "It seems that your USE_PYTHON setting lists different Python"
527 ewarn "implementations than your PYTHON_TARGETS variable. Please consider"
528 ewarn "using the following value instead:"
529 ewarn
530 ewarn " USE_PYTHON='\033[35m${old[@]}${new[@]+ \033[1m${new[@]}}\033[0m'"
531
532 if [[ ${removed[@]} ]]; then
533 ewarn
534 ewarn "(removed \033[31m${removed[@]}\033[0m)"
535 fi
536 else
537 ewarn "It seems that you need to set USE_PYTHON to make sure that legacy"
538 ewarn "packages will be built with respect to PYTHON_TARGETS correctly:"
539 ewarn
540 ewarn " USE_PYTHON='\033[35;1m${new[@]}\033[0m'"
541 fi
542
543 ewarn
544 ewarn "Please note that after changing the USE_PYTHON variable, you may need"
545 ewarn "to run 'python-updater' to rebuild affected packages."
546 ewarn
547 ewarn "For more information on python.eclass compatibility, please see"
548 ewarn "the appropriate python-r1 User's Guide chapter [1]."
549 ewarn
550 ewarn "[1] http://www.gentoo.org/proj/en/Python/python-r1/user-guide.xml#doc_chap2"
551 fi
552 fi
553 }
554
555 # @FUNCTION: python_foreach_impl
556 # @USAGE: <command> [<args>...]
557 # @DESCRIPTION:
558 # Run the given command for each of the enabled Python implementations.
559 # If additional parameters are passed, they will be passed through
560 # to the command. If the command fails, python_foreach_impl dies.
561 # If necessary, use ':' to force a successful return.
562 #
563 # For each command being run, EPYTHON, PYTHON and BUILD_DIR are set
564 # locally, and the former two are exported to the command environment.
565 python_foreach_impl() {
566 debug-print-function ${FUNCNAME} "${@}"
567
568 _python_validate_useflags
569 _python_check_USE_PYTHON
570
571 local impl
572 local bdir=${BUILD_DIR:-${S}}
573
574 debug-print "${FUNCNAME}: bdir = ${bdir}"
575 for impl in "${_PYTHON_ALL_IMPLS[@]}"; do
576 if has "${impl}" "${PYTHON_COMPAT[@]}" && use "python_targets_${impl}"
577 then
578 local EPYTHON PYTHON
579 python_export "${impl}" EPYTHON PYTHON
580 local BUILD_DIR=${bdir%%/}-${impl}
581 export EPYTHON PYTHON
582
583 einfo "${EPYTHON}: running ${@}"
584 "${@}" || die "${EPYTHON}: ${1} failed"
585 fi
586 done
587 }
588
589 # @FUNCTION: python_export_best
590 # @USAGE: [<variable>...]
591 # @DESCRIPTION:
592 # Find the best (most preferred) Python implementation enabled
593 # and export given variables for it. If no variables are provided,
594 # EPYTHON & PYTHON will be exported.
595 python_export_best() {
596 debug-print-function ${FUNCNAME} "${@}"
597
598 _python_validate_useflags
599
600 [[ ${#} -gt 0 ]] || set -- EPYTHON PYTHON
601
602 local impl best
603 for impl in "${_PYTHON_ALL_IMPLS[@]}"; do
604 if has "${impl}" "${PYTHON_COMPAT[@]}" && use "python_targets_${impl}"
605 then
606 best=${impl}
607 fi
608 done
609
610 [[ ${best+1} ]] || die "python_export_best(): no implementation found!"
611
612 debug-print "${FUNCNAME}: Best implementation is: ${impl}"
613 python_export "${impl}" "${@}"
614 }
615
616 # @FUNCTION: python_replicate_script
617 # @USAGE: <path>...
618 # @DESCRIPTION:
619 # Copy the given script to variants for all enabled Python
620 # implementations, then replace it with a symlink to the wrapper.
621 #
622 # All specified files must start with a 'python' shebang. A file not
623 # having a matching shebang will be refused.
624 python_replicate_script() {
625 debug-print-function ${FUNCNAME} "${@}"
626
627 _python_validate_useflags
628
629 local suffixes=()
630
631 _add_suffix() {
632 suffixes+=( "${EPYTHON}" )
633 }
634 python_foreach_impl _add_suffix
635 debug-print "${FUNCNAME}: suffixes = ( ${suffixes[@]} )"
636
637 local f suffix
638 for suffix in "${suffixes[@]}"; do
639 for f; do
640 local newf=${f}-${suffix}
641
642 debug-print "${FUNCNAME}: ${f} -> ${newf}"
643 cp "${f}" "${newf}" || die
644 done
645
646 _python_rewrite_shebang "${suffix}" "${@/%/-${suffix}}"
647 done
648
649 for f; do
650 _python_ln_rel "${ED}"/usr/bin/python-exec "${f}" || die
651 done
652 }
653
654 _PYTHON_R1=1
655 fi

  ViewVC Help
Powered by ViewVC 1.1.20