python-single-r1.eclass (13652B)
1 # Copyright 1999-2022 Gentoo Authors 2 # Distributed under the terms of the GNU General Public License v2 3 4 # @ECLASS: python-single-r1.eclass 5 # @MAINTAINER: 6 # Python team <python@gentoo.org> 7 # @AUTHOR: 8 # Author: Michał Górny <mgorny@gentoo.org> 9 # Based on work of: Krzysztof Pawlik <nelchael@gentoo.org> 10 # @SUPPORTED_EAPIS: 6 7 8 11 # @PROVIDES: python-utils-r1 12 # @BLURB: An eclass for Python packages not installed for multiple implementations. 13 # @DESCRIPTION: 14 # An extension of the python-r1 eclass suite for packages which 15 # don't support being installed for multiple Python implementations. 16 # This mostly includes tools embedding Python and packages using foreign 17 # build systems. 18 # 19 # This eclass sets correct IUSE. It also provides PYTHON_DEPS 20 # and PYTHON_REQUIRED_USE that need to be added to appropriate ebuild 21 # metadata variables. 22 # 23 # The eclass exports PYTHON_SINGLE_USEDEP that is suitable for depending 24 # on other packages using the eclass. Dependencies on packages using 25 # python-r1 should be created via python_gen_cond_dep() function, 26 # using PYTHON_USEDEP placeholder. 27 # 28 # Please note that packages support multiple Python implementations 29 # (using python-r1 eclass) can not depend on packages not supporting 30 # them (using this eclass). 31 # 32 # Please note that python-single-r1 will always inherit python-utils-r1 33 # as well. Thus, all the functions defined there can be used 34 # in the packages using python-single-r1, and there is no need ever 35 # to inherit both. 36 # 37 # For more information, please see the Python Guide: 38 # https://projects.gentoo.org/python/guide/ 39 40 case "${EAPI:-0}" in 41 [0-5]) 42 die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}" 43 ;; 44 [6-8]) 45 ;; 46 *) 47 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" 48 ;; 49 esac 50 51 if [[ ! ${_PYTHON_SINGLE_R1} ]]; then 52 53 if [[ ${_PYTHON_R1_ECLASS} ]]; then 54 die 'python-single-r1.eclass can not be used with python-r1.eclass.' 55 elif [[ ${_PYTHON_ANY_R1_ECLASS} ]]; then 56 die 'python-single-r1.eclass can not be used with python-any-r1.eclass.' 57 fi 58 59 inherit python-utils-r1 60 61 fi 62 63 EXPORT_FUNCTIONS pkg_setup 64 65 # @ECLASS_VARIABLE: PYTHON_COMPAT 66 # @REQUIRED 67 # @DESCRIPTION: 68 # This variable contains a list of Python implementations the package 69 # supports. It must be set before the `inherit' call. It has to be 70 # an array. 71 # 72 # Example: 73 # @CODE 74 # PYTHON_COMPAT=( python2_7 python3_3 python3_4 ) 75 # @CODE 76 # 77 # Please note that you can also use bash brace expansion if you like: 78 # @CODE 79 # PYTHON_COMPAT=( python2_7 python3_{3,4} ) 80 # @CODE 81 82 # @ECLASS_VARIABLE: PYTHON_COMPAT_OVERRIDE 83 # @USER_VARIABLE 84 # @DEFAULT_UNSET 85 # @DESCRIPTION: 86 # This variable can be used when working with ebuilds to override 87 # the in-ebuild PYTHON_COMPAT. It is a string naming the implementation 88 # which package will be built for. It needs to be specified 89 # in the calling environment, and not in ebuilds. 90 # 91 # It should be noted that in order to preserve metadata immutability, 92 # PYTHON_COMPAT_OVERRIDE does not affect IUSE nor dependencies. 93 # The state of PYTHON_SINGLE_TARGET is ignored, and the implementation 94 # in PYTHON_COMPAT_OVERRIDE is built instead. Dependencies need to be 95 # satisfied manually. 96 # 97 # Example: 98 # @CODE 99 # PYTHON_COMPAT_OVERRIDE='pypy' emerge -1v dev-python/bar 100 # @CODE 101 102 # @ECLASS_VARIABLE: PYTHON_REQ_USE 103 # @DEFAULT_UNSET 104 # @DESCRIPTION: 105 # The list of USEflags required to be enabled on the chosen Python 106 # implementations, formed as a USE-dependency string. It should be valid 107 # for all implementations in PYTHON_COMPAT, so it may be necessary to 108 # use USE defaults. 109 # 110 # This should be set before calling `inherit'. 111 # 112 # Example: 113 # @CODE 114 # PYTHON_REQ_USE="gdbm,ncurses(-)?" 115 # @CODE 116 # 117 # It will cause the Python dependencies to look like: 118 # @CODE 119 # python_single_target_pythonX_Y? ( dev-lang/python:X.Y[gdbm,ncurses(-)?] ) 120 # @CODE 121 122 # @ECLASS_VARIABLE: PYTHON_DEPS 123 # @OUTPUT_VARIABLE 124 # @DESCRIPTION: 125 # This is an eclass-generated Python dependency string for all 126 # implementations listed in PYTHON_COMPAT. 127 # 128 # The dependency string is conditional on PYTHON_SINGLE_TARGET. 129 # 130 # Example use: 131 # @CODE 132 # RDEPEND="${PYTHON_DEPS} 133 # dev-foo/mydep" 134 # BDEPEND="${PYTHON_DEPS}" 135 # @CODE 136 # 137 # Example value: 138 # @CODE 139 # python_single_target_python2_7? ( dev-lang/python:2.7[gdbm] ) 140 # python_single_target_pypy? ( dev-python/pypy[gdbm] ) 141 # @CODE 142 143 # @ECLASS_VARIABLE: PYTHON_SINGLE_USEDEP 144 # @OUTPUT_VARIABLE 145 # @DESCRIPTION: 146 # This is an eclass-generated USE-dependency string which can be used to 147 # depend on another python-single-r1 package being built for the same 148 # Python implementations. 149 # 150 # If you need to depend on a multi-impl (python-r1) package, use 151 # python_gen_cond_dep with PYTHON_USEDEP placeholder instead. 152 # 153 # Example use: 154 # @CODE 155 # RDEPEND="dev-python/foo[${PYTHON_SINGLE_USEDEP}]" 156 # @CODE 157 # 158 # Example value: 159 # @CODE 160 # python_single_target_python3_4(-)? 161 # @CODE 162 163 # @ECLASS_VARIABLE: PYTHON_USEDEP 164 # @OUTPUT_VARIABLE 165 # @DESCRIPTION: 166 # This is a placeholder variable supported by python_gen_cond_dep, 167 # in order to depend on python-r1 packages built for the same Python 168 # implementations. 169 # 170 # Example use: 171 # @CODE 172 # RDEPEND="$(python_gen_cond_dep ' 173 # dev-python/foo[${PYTHON_USEDEP}] 174 # ')" 175 # @CODE 176 # 177 # Example value: 178 # @CODE 179 # python_targets_python3_4(-) 180 # @CODE 181 182 # @ECLASS_VARIABLE: PYTHON_REQUIRED_USE 183 # @OUTPUT_VARIABLE 184 # @DESCRIPTION: 185 # This is an eclass-generated required-use expression which ensures 186 # that exactly one PYTHON_SINGLE_TARGET value has been enabled. 187 # 188 # This expression should be utilized in an ebuild by including it in 189 # REQUIRED_USE, optionally behind a use flag. 190 # 191 # Example use: 192 # @CODE 193 # REQUIRED_USE="python? ( ${PYTHON_REQUIRED_USE} )" 194 # @CODE 195 # 196 # Example value: 197 # @CODE 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 local flags=( "${_PYTHON_SUPPORTED_IMPLS[@]/#/python_single_target_}" ) 205 206 if [[ ${#_PYTHON_SUPPORTED_IMPLS[@]} -eq 1 ]]; then 207 # if only one implementation is supported, use IUSE defaults 208 # to avoid requesting the user to enable it 209 IUSE="+${flags[0]}" 210 else 211 IUSE="${flags[*]}" 212 fi 213 214 local requse="^^ ( ${flags[*]} )" 215 local single_flags="${flags[@]/%/(-)?}" 216 local single_usedep=${single_flags// /,} 217 218 local deps= i PYTHON_PKG_DEP 219 for i in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do 220 _python_export "${i}" PYTHON_PKG_DEP 221 deps+="python_single_target_${i}? ( 222 ${PYTHON_PKG_DEP} 223 ) " 224 done 225 226 if [[ ${PYTHON_DEPS+1} ]]; then 227 if [[ ${PYTHON_DEPS} != "${deps}" ]]; then 228 eerror "PYTHON_DEPS have changed between inherits (PYTHON_REQ_USE?)!" 229 eerror "Before: ${PYTHON_DEPS}" 230 eerror "Now : ${deps}" 231 die "PYTHON_DEPS integrity check failed" 232 fi 233 234 # these two are formality -- they depend on PYTHON_COMPAT only 235 if [[ ${PYTHON_REQUIRED_USE} != ${requse} ]]; then 236 eerror "PYTHON_REQUIRED_USE have changed between inherits!" 237 eerror "Before: ${PYTHON_REQUIRED_USE}" 238 eerror "Now : ${requse}" 239 die "PYTHON_REQUIRED_USE integrity check failed" 240 fi 241 242 if [[ ${PYTHON_SINGLE_USEDEP} != "${single_usedep}" ]]; then 243 eerror "PYTHON_SINGLE_USEDEP have changed between inherits!" 244 eerror "Before: ${PYTHON_SINGLE_USEDEP}" 245 eerror "Now : ${single_usedep}" 246 die "PYTHON_SINGLE_USEDEP integrity check failed" 247 fi 248 else 249 PYTHON_DEPS=${deps} 250 PYTHON_REQUIRED_USE=${requse} 251 PYTHON_USEDEP='%PYTHON_USEDEP-NEEDS-TO-BE-USED-IN-PYTHON_GEN_COND_DEP%' 252 PYTHON_SINGLE_USEDEP=${single_usedep} 253 readonly PYTHON_DEPS PYTHON_REQUIRED_USE PYTHON_SINGLE_USEDEP \ 254 PYTHON_USEDEP 255 fi 256 } 257 _python_single_set_globals 258 unset -f _python_single_set_globals 259 260 if [[ ! ${_PYTHON_SINGLE_R1} ]]; then 261 262 # @FUNCTION: python_gen_useflags 263 # @USAGE: [<pattern>...] 264 # @DESCRIPTION: 265 # Output a list of USE flags for Python implementations which 266 # are both in PYTHON_COMPAT and match any of the patterns passed 267 # as parameters to the function. 268 # 269 # For the pattern syntax, please see _python_impl_matches 270 # in python-utils-r1.eclass. 271 # 272 # Example: 273 # @CODE 274 # PYTHON_COMPAT=( python{2_7,3_4} ) 275 # REQUIRED_USE="doc? ( ^^ ( $(python_gen_useflags 'python2*') ) )" 276 # @CODE 277 # 278 # It will cause the variable to look like: 279 # @CODE 280 # REQUIRED_USE="doc? ( ^^ ( python_single_target_python2_7 ) )" 281 # @CODE 282 python_gen_useflags() { 283 debug-print-function ${FUNCNAME} "${@}" 284 285 local impl matches=() 286 287 _python_verify_patterns "${@}" 288 for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do 289 if _python_impl_matches "${impl}" "${@}"; then 290 matches+=( "python_single_target_${impl}" ) 291 fi 292 done 293 294 echo "${matches[@]}" 295 } 296 297 # @FUNCTION: python_gen_cond_dep 298 # @USAGE: <dependency> [<pattern>...] 299 # @DESCRIPTION: 300 # Output a list of <dependency>-ies made conditional to USE flags 301 # of Python implementations which are both in PYTHON_COMPAT and match 302 # any of the patterns passed as the remaining parameters. 303 # 304 # For the pattern syntax, please see _python_impl_matches 305 # in python-utils-r1.eclass. 306 # 307 # In order to enforce USE constraints on the packages, verbatim 308 # '${PYTHON_SINGLE_USEDEP}' and '${PYTHON_USEDEP}' (quoted!) may 309 # be placed in the dependency specification. It will get expanded within 310 # the function into a proper USE dependency string. 311 # 312 # Example: 313 # @CODE 314 # PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy ) 315 # RDEPEND="$(python_gen_cond_dep \ 316 # 'dev-python/unittest2[${PYTHON_USEDEP}]' python2_7 pypy )" 317 # @CODE 318 # 319 # It will cause the variable to look like: 320 # @CODE 321 # RDEPEND="python_single_target_python2_7? ( 322 # dev-python/unittest2[python_targets_python2_7(-)?,...] ) 323 # python_single_target_pypy? ( 324 # dev-python/unittest2[python_targets_pypy(-)?,...] )" 325 # @CODE 326 python_gen_cond_dep() { 327 debug-print-function ${FUNCNAME} "${@}" 328 329 local impl matches=() 330 331 local dep=${1} 332 shift 333 334 _python_verify_patterns "${@}" 335 for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do 336 if _python_impl_matches "${impl}" "${@}"; then 337 local single_usedep="python_single_target_${impl}(-)" 338 local multi_usedep="python_targets_${impl}(-)" 339 340 local subdep=${dep//\$\{PYTHON_SINGLE_USEDEP\}/${single_usedep}} 341 matches+=( "python_single_target_${impl}? ( 342 ${subdep//\$\{PYTHON_USEDEP\}/${multi_usedep}} )" ) 343 fi 344 done 345 346 echo "${matches[@]}" 347 } 348 349 # @FUNCTION: python_gen_impl_dep 350 # @USAGE: [<requested-use-flags> [<impl-pattern>...]] 351 # @DESCRIPTION: 352 # Output a dependency on Python implementations with the specified USE 353 # dependency string appended, or no USE dependency string if called 354 # without the argument (or with empty argument). If any implementation 355 # patterns are passed, the output dependencies will be generated only 356 # for the implementations matching them. 357 # 358 # For the pattern syntax, please see _python_impl_matches 359 # in python-utils-r1.eclass. 360 # 361 # Use this function when you need to request different USE flags 362 # on the Python interpreter depending on package's USE flags. If you 363 # only need a single set of interpreter USE flags, just set 364 # PYTHON_REQ_USE and use ${PYTHON_DEPS} globally. 365 # 366 # Example: 367 # @CODE 368 # PYTHON_COMPAT=( python{2_7,3_{3,4}} pypy ) 369 # RDEPEND="foo? ( $(python_gen_impl_dep 'xml(+)') )" 370 # @CODE 371 # 372 # It will cause the variable to look like: 373 # @CODE 374 # RDEPEND="foo? ( 375 # python_single_target_python2_7? ( 376 # dev-lang/python:2.7[xml(+)] ) 377 # python_single_target_pypy? ( 378 # dev-python/pypy[xml(+)] ) )" 379 # @CODE 380 python_gen_impl_dep() { 381 debug-print-function ${FUNCNAME} "${@}" 382 383 local impl 384 local matches=() 385 386 local PYTHON_REQ_USE=${1} 387 shift 388 389 _python_verify_patterns "${@}" 390 for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do 391 if _python_impl_matches "${impl}" "${@}"; then 392 local PYTHON_PKG_DEP 393 _python_export "${impl}" PYTHON_PKG_DEP 394 matches+=( "python_single_target_${impl}? ( ${PYTHON_PKG_DEP} )" ) 395 fi 396 done 397 398 echo "${matches[@]}" 399 } 400 401 # @FUNCTION: python_setup 402 # @DESCRIPTION: 403 # Determine what the selected Python implementation is and set 404 # the Python build environment up for it. 405 python_setup() { 406 debug-print-function ${FUNCNAME} "${@}" 407 408 unset EPYTHON 409 410 # support developer override 411 if [[ ${PYTHON_COMPAT_OVERRIDE} ]]; then 412 local impls=( ${PYTHON_COMPAT_OVERRIDE} ) 413 [[ ${#impls[@]} -eq 1 ]] || die "PYTHON_COMPAT_OVERRIDE must name exactly one implementation for python-single-r1" 414 415 ewarn "WARNING: PYTHON_COMPAT_OVERRIDE in effect. The following Python" 416 ewarn "implementation will be used:" 417 ewarn 418 ewarn " ${PYTHON_COMPAT_OVERRIDE}" 419 ewarn 420 ewarn "Dependencies won't be satisfied, and PYTHON_SINGLE_TARGET flags will be ignored." 421 422 _python_export "${impls[0]}" EPYTHON PYTHON 423 _python_wrapper_setup 424 einfo "Using ${EPYTHON} to build" 425 return 426 fi 427 428 local impl 429 for impl in "${_PYTHON_SUPPORTED_IMPLS[@]}"; do 430 if use "python_single_target_${impl}"; then 431 if [[ ${EPYTHON} ]]; then 432 eerror "Your PYTHON_SINGLE_TARGET setting lists more than a single Python" 433 eerror "implementation. Please set it to just one value. If you need" 434 eerror "to override the value for a single package, please use package.env" 435 eerror "or an equivalent solution (man 5 portage)." 436 echo 437 die "More than one implementation in PYTHON_SINGLE_TARGET." 438 fi 439 440 _python_export "${impl}" EPYTHON PYTHON 441 _python_wrapper_setup 442 einfo "Using ${EPYTHON} to build" 443 fi 444 done 445 446 if [[ ! ${EPYTHON} ]]; then 447 eerror "No Python implementation selected for the build. Please set" 448 eerror "the PYTHON_SINGLE_TARGET variable in your make.conf to one" 449 eerror "of the following values:" 450 eerror 451 eerror "${_PYTHON_SUPPORTED_IMPLS[@]}" 452 echo 453 die "No supported Python implementation in PYTHON_SINGLE_TARGET." 454 fi 455 } 456 457 # @FUNCTION: python-single-r1_pkg_setup 458 # @DESCRIPTION: 459 # Runs python_setup. 460 python-single-r1_pkg_setup() { 461 debug-print-function ${FUNCNAME} "${@}" 462 463 [[ ${MERGE_TYPE} != binary ]] && python_setup 464 } 465 466 _PYTHON_SINGLE_R1=1 467 fi