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

Contents of /eclass/python-r1.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.25 - (show annotations) (download)
Sat Dec 1 09:29:24 2012 UTC (19 months, 1 week ago) by mgorny
Branch: MAIN
Changes since 1.24: +3 -1 lines
Introduce python-any-r1, to handle packages satisfied by any Python implementation installed (e.g. strictly build-time dependent).

1 # Copyright 1999-2012 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.24 2012/11/30 11:40:15 mgorny Exp $
4
5 # @ECLASS: python-r1
6 # @MAINTAINER:
7 # Michał Górny <mgorny@gentoo.org>
8 # Python herd <python@gentoo.org>
9 # @AUTHOR:
10 # Author: Michał Górny <mgorny@gentoo.org>
11 # Based on work of: Krzysztof Pawlik <nelchael@gentoo.org>
12 # @BLURB: A common, simple eclass for Python packages.
13 # @DESCRIPTION:
14 # A common eclass providing helper functions to build and install
15 # packages supporting being installed for multiple Python
16 # implementations.
17 #
18 # This eclass sets correct IUSE and REQUIRED_USE. It exports PYTHON_DEPS
19 # and PYTHON_USEDEP so you can create correct dependencies for your
20 # package easily. It also provides methods to easily run a command for
21 # each enabled Python implementation and duplicate the sources for them.
22 #
23 # Please note that python-r1 will always inherit python-utils-r1 as
24 # well. Thus, all the functions defined there can be used
25 # in the packages using python-r1, and there is no need ever to inherit
26 # both.
27 #
28 # For more information, please see the python-r1 Developer's Guide:
29 # http://www.gentoo.org/proj/en/Python/python-r1/dev-guide.xml
30
31 case "${EAPI:-0}" in
32 0|1|2|3)
33 die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
34 ;;
35 4|5)
36 # EAPI=4 needed for REQUIRED_USE
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 IUSE=${flags[*]}
139 REQUIRED_USE="|| ( ${flags[*]} )"
140 PYTHON_USEDEP=${optflags// /,}
141
142 local usestr
143 [[ ${PYTHON_REQ_USE} ]] && usestr="[${PYTHON_REQ_USE}]"
144
145 # 1) well, python-exec would suffice as an RDEP
146 # but no point in making this overcomplex, BDEP doesn't hurt anyone
147 # 2) python-exec should be built with all targets forced anyway
148 # but if new targets were added, we may need to force a rebuild
149 PYTHON_DEPS="dev-python/python-exec[${PYTHON_USEDEP}]"
150 local i
151 for i in "${PYTHON_COMPAT[@]}"; do
152 local d
153 case ${i} in
154 python*)
155 d='dev-lang/python';;
156 jython*)
157 d='dev-java/jython';;
158 pypy*)
159 d='dev-python/pypy';;
160 *)
161 die "Invalid implementation: ${i}"
162 esac
163
164 local v=${i##*[a-z]}
165 PYTHON_DEPS+=" python_targets_${i}? ( ${d}:${v/_/.}${usestr} )"
166 done
167 }
168 _python_set_globals
169
170 # @ECLASS-VARIABLE: BUILD_DIR
171 # @DESCRIPTION:
172 # The current build directory. In global scope, it is supposed to
173 # contain an initial build directory; if unset, it defaults to ${S}.
174 #
175 # In functions run by python_foreach_impl(), the BUILD_DIR is locally
176 # set to an implementation-specific build directory. That path is
177 # created through appending a hyphen and the implementation name
178 # to the final component of the initial BUILD_DIR.
179 #
180 # Example value:
181 # @CODE
182 # ${WORKDIR}/foo-1.3-python2_6
183 # @CODE
184
185 # @FUNCTION: python_copy_sources
186 # @DESCRIPTION:
187 # Create a single copy of the package sources (${S}) for each enabled
188 # Python implementation.
189 #
190 # The sources are always copied from S to implementation-specific build
191 # directories respecting BUILD_DIR.
192 python_copy_sources() {
193 debug-print-function ${FUNCNAME} "${@}"
194
195 local impl
196 local bdir=${BUILD_DIR:-${S}}
197
198 debug-print "${FUNCNAME}: bdir = ${bdir}"
199 einfo "Will copy sources from ${S}"
200 # the order is irrelevant here
201 for impl in "${PYTHON_COMPAT[@]}"; do
202 if use "python_targets_${impl}"
203 then
204 local BUILD_DIR=${bdir%%/}-${impl}
205
206 einfo "${impl}: copying to ${BUILD_DIR}"
207 debug-print "${FUNCNAME}: [${impl}] cp ${S} => ${BUILD_DIR}"
208 cp -pr "${S}" "${BUILD_DIR}" || die
209 fi
210 done
211 }
212
213 # @FUNCTION: _python_check_USE_PYTHON
214 # @INTERNAL
215 # @DESCRIPTION:
216 # Check whether USE_PYTHON and PYTHON_TARGETS are in sync. Output
217 # warnings if they are not.
218 _python_check_USE_PYTHON() {
219 debug-print-function ${FUNCNAME} "${@}"
220
221 if [[ ! ${_PYTHON_USE_PYTHON_CHECKED} ]]; then
222 _PYTHON_USE_PYTHON_CHECKED=1
223
224 # python-exec has profile-forced flags.
225 if [[ ${CATEGORY}/${PN} == dev-python/python-exec ]]; then
226 return
227 fi
228
229 _try_eselect() {
230 # The eselect solution will work only with one py2 & py3.
231
232 local impl py2 py3 dis_py2 dis_py3
233 for impl in "${PYTHON_COMPAT[@]}"; do
234 if use "python_targets_${impl}"; then
235 case "${impl}" in
236 python2_*)
237 if [[ ${py2+1} ]]; then
238 debug-print "${FUNCNAME}: -> more than one py2: ${py2} ${impl}"
239 return 1
240 fi
241 py2=${impl/_/.}
242 ;;
243 python3_*)
244 if [[ ${py3+1} ]]; then
245 debug-print "${FUNCNAME}: -> more than one py3: ${py3} ${impl}"
246 return 1
247 fi
248 py3=${impl/_/.}
249 ;;
250 *)
251 return 1
252 ;;
253 esac
254 else
255 case "${impl}" in
256 python2_*)
257 dis_py2=1
258 ;;
259 python3_*)
260 dis_py3=1
261 ;;
262 esac
263 fi
264 done
265
266 # The eselect solution won't work if the disabled Python version
267 # is installed.
268 if [[ ! ${py2+1} && ${dis_py2} ]]; then
269 debug-print "${FUNCNAME}: -> all py2 versions disabled"
270 if has_version '=dev-lang/python-2*'; then
271 debug-print "${FUNCNAME}: ---> but =python-2* installed!"
272 return 1
273 fi
274 fi
275 if [[ ! ${py3+1} && ${dis_py3} ]]; then
276 debug-print "${FUNCNAME}: -> all py3 versions disabled"
277 if has_version '=dev-lang/python-3*'; then
278 debug-print "${FUNCNAME}: ---> but =python-3* installed!"
279 return 1
280 fi
281 fi
282
283 local warned
284
285 # Now check whether the correct implementations are active.
286 if [[ ${py2+1} ]]; then
287 local sel_py2=$(eselect python show --python2)
288
289 debug-print "${FUNCNAME}: -> py2 built: ${py2}, active: ${sel_py2}"
290 if [[ ${py2} != ${sel_py2} ]]; then
291 ewarn "Building package for ${py2} only while ${sel_py2} is active."
292 ewarn "Please consider switching the active Python 2 interpreter:"
293 ewarn
294 ewarn " eselect python set --python2 ${py2}"
295 warned=1
296 fi
297 fi
298
299 if [[ ${py3+1} ]]; then
300 local sel_py3=$(eselect python show --python3)
301
302 debug-print "${FUNCNAME}: -> py3 built: ${py3}, active: ${sel_py3}"
303 if [[ ${py3} != ${sel_py3} ]]; then
304 [[ ${warned} ]] && ewarn
305 ewarn "Building package for ${py3} only while ${sel_py3} is active."
306 ewarn "Please consider switching the active Python 3 interpreter:"
307 ewarn
308 ewarn " eselect python set --python3 ${py3}"
309 warned=1
310 fi
311 fi
312
313 if [[ ${warned} ]]; then
314 ewarn
315 ewarn "Please note that after switching the active Python interpreter,"
316 ewarn "you may need to run 'python-updater' to rebuild affected packages."
317 ewarn
318 ewarn "For more information on python.eclass compatibility, please see"
319 ewarn "the appropriate python-r1 User's Guide chapter [1]."
320 ewarn
321 ewarn "[1] http://www.gentoo.org/proj/en/Python/python-r1/user-guide.xml#doc_chap2"
322 fi
323 }
324
325 # If user has no USE_PYTHON, try to avoid it.
326 if [[ ! ${USE_PYTHON} ]]; then
327 debug-print "${FUNCNAME}: trying eselect solution ..."
328 _try_eselect && return
329 fi
330
331 debug-print "${FUNCNAME}: trying USE_PYTHON solution ..."
332 debug-print "${FUNCNAME}: -> USE_PYTHON=${USE_PYTHON}"
333
334 local impl old=${USE_PYTHON} new=() removed=()
335
336 for impl in "${PYTHON_COMPAT[@]}"; do
337 local abi
338 case "${impl}" in
339 python*)
340 abi=${impl#python}
341 ;;
342 jython*)
343 abi=${impl#jython}-jython
344 ;;
345 pypy*)
346 abi=2.7-pypy-${impl#pypy}
347 ;;
348 *)
349 die "Unexpected Python implementation: ${impl}"
350 ;;
351 esac
352 abi=${abi/_/.}
353
354 has "${abi}" ${USE_PYTHON}
355 local has_abi=${?}
356 use "python_targets_${impl}"
357 local has_impl=${?}
358
359 # 0 = has, 1 = does not have
360 if [[ ${has_abi} == 0 && ${has_impl} == 1 ]]; then
361 debug-print "${FUNCNAME}: ---> remove ${abi}"
362 # remove from USE_PYTHON
363 old=${old/${abi}/}
364 removed+=( ${abi} )
365 elif [[ ${has_abi} == 1 && ${has_impl} == 0 ]]; then
366 debug-print "${FUNCNAME}: ---> add ${abi}"
367 # add to USE_PYTHON
368 new+=( ${abi} )
369 fi
370 done
371
372 if [[ ${removed[@]} || ${new[@]} ]]; then
373 old=( ${old} )
374
375 debug-print "${FUNCNAME}: -> old: ${old[@]}"
376 debug-print "${FUNCNAME}: -> new: ${new[@]}"
377 debug-print "${FUNCNAME}: -> removed: ${removed[@]}"
378
379 if [[ ${USE_PYTHON} ]]; then
380 ewarn "It seems that your USE_PYTHON setting lists different Python"
381 ewarn "implementations than your PYTHON_TARGETS variable. Please consider"
382 ewarn "using the following value instead:"
383 ewarn
384 ewarn " USE_PYTHON='\033[35m${old[@]}${new[@]+ \033[1m${new[@]}}\033[0m'"
385
386 if [[ ${removed[@]} ]]; then
387 ewarn
388 ewarn "(removed \033[31m${removed[@]}\033[0m)"
389 fi
390 else
391 ewarn "It seems that you need to set USE_PYTHON to make sure that legacy"
392 ewarn "packages will be built with respect to PYTHON_TARGETS correctly:"
393 ewarn
394 ewarn " USE_PYTHON='\033[35;1m${new[@]}\033[0m'"
395 fi
396
397 ewarn
398 ewarn "Please note that after changing the USE_PYTHON variable, you may need"
399 ewarn "to run 'python-updater' to rebuild affected packages."
400 ewarn
401 ewarn "For more information on python.eclass compatibility, please see"
402 ewarn "the appropriate python-r1 User's Guide chapter [1]."
403 ewarn
404 ewarn "[1] http://www.gentoo.org/proj/en/Python/python-r1/user-guide.xml#doc_chap2"
405 fi
406 fi
407 }
408
409 # @FUNCTION: python_foreach_impl
410 # @USAGE: <command> [<args>...]
411 # @DESCRIPTION:
412 # Run the given command for each of the enabled Python implementations.
413 # If additional parameters are passed, they will be passed through
414 # to the command. If the command fails, python_foreach_impl dies.
415 # If necessary, use ':' to force a successful return.
416 #
417 # For each command being run, EPYTHON, PYTHON and BUILD_DIR are set
418 # locally, and the former two are exported to the command environment.
419 python_foreach_impl() {
420 debug-print-function ${FUNCNAME} "${@}"
421
422 _python_check_USE_PYTHON
423
424 local impl
425 local bdir=${BUILD_DIR:-${S}}
426
427 debug-print "${FUNCNAME}: bdir = ${bdir}"
428 for impl in "${_PYTHON_ALL_IMPLS[@]}"; do
429 if has "${impl}" "${PYTHON_COMPAT[@]}" && use "python_targets_${impl}"
430 then
431 local EPYTHON PYTHON
432 python_export "${impl}" EPYTHON PYTHON
433 local BUILD_DIR=${bdir%%/}-${impl}
434 export EPYTHON PYTHON
435
436 einfo "${EPYTHON}: running ${@}"
437 "${@}" || die "${EPYTHON}: ${1} failed"
438 fi
439 done
440 }
441
442 # @FUNCTION: python_export_best
443 # @USAGE: [<variable>...]
444 # @DESCRIPTION:
445 # Find the best (most preferred) Python implementation enabled
446 # and export given variables for it. If no variables are provided,
447 # EPYTHON & PYTHON will be exported.
448 python_export_best() {
449 debug-print-function ${FUNCNAME} "${@}"
450
451 [[ ${#} -gt 0 ]] || set -- EPYTHON PYTHON
452
453 local impl best
454 for impl in "${_PYTHON_ALL_IMPLS[@]}"; do
455 if has "${impl}" "${PYTHON_COMPAT[@]}" && use "python_targets_${impl}"
456 then
457 best=${impl}
458 fi
459 done
460
461 [[ ${best+1} ]] || die "python_export_best(): no implementation found!"
462
463 debug-print "${FUNCNAME}: Best implementation is: ${impl}"
464 python_export "${impl}" "${@}"
465 }
466
467 # @FUNCTION: python_replicate_script
468 # @USAGE: <path>...
469 # @DESCRIPTION:
470 # Copy the given script to variants for all enabled Python
471 # implementations, then replace it with a symlink to the wrapper.
472 #
473 # All specified files must start with a 'python' shebang. A file not
474 # having a matching shebang will be refused.
475 python_replicate_script() {
476 debug-print-function ${FUNCNAME} "${@}"
477
478 if [[ ${_PYTHON_SINGLE_R1} ]]; then
479 die "${FUNCNAME} must not be used with python-single-r1 eclass."
480 fi
481
482 local suffixes=()
483
484 _add_suffix() {
485 suffixes+=( "${EPYTHON}" )
486 }
487 python_foreach_impl _add_suffix
488 debug-print "${FUNCNAME}: suffixes = ( ${suffixes[@]} )"
489
490 local f suffix
491 for suffix in "${suffixes[@]}"; do
492 for f; do
493 local newf=${f}-${suffix}
494
495 debug-print "${FUNCNAME}: ${f} -> ${newf}"
496 cp "${f}" "${newf}" || die
497 done
498
499 _python_rewrite_shebang "${suffix}" "${@/%/-${suffix}}"
500 done
501
502 for f; do
503 _python_ln_rel "${ED}"/usr/bin/python-exec "${f}" || die
504 done
505 }
506
507 _PYTHON_R1=1
508 fi

  ViewVC Help
Powered by ViewVC 1.1.20