Gentoo Archives: gentoo-dev

From: Marek Szuba <marecki@g.o>
To: gentoo-dev@l.g.o
Subject: [gentoo-dev] [PATCH 4/4] lua-single.eclass: new eclass for single-implementation Lua ebuilds
Date: Wed, 30 Sep 2020 16:24:59
Message-Id: 20200930162315.253903-5-marecki@gentoo.org
In Reply to: [gentoo-dev] [PATCH 0/4] Eclass for single-impl Lua ebuilds by Marek Szuba
1 With many thanks to Michał Górny and other authors of
2 python-single-r1.eclass.
3
4 Signed-off-by: Marek Szuba <marecki@g.o>
5 ---
6 eclass/lua-single.eclass | 510 +++++++++++++++++++++++++++++++++++++++
7 1 file changed, 510 insertions(+)
8 create mode 100644 eclass/lua-single.eclass
9
10 diff --git a/eclass/lua-single.eclass b/eclass/lua-single.eclass
11 new file mode 100644
12 index 00000000000..2233fdd33b6
13 --- /dev/null
14 +++ b/eclass/lua-single.eclass
15 @@ -0,0 +1,510 @@
16 +# Copyright 1999-2020 Gentoo Authors
17 +# Distributed under the terms of the GNU General Public License v2
18 +
19 +# @ECLASS: lua-single.eclass
20 +# @MAINTAINER:
21 +# William Hubbs <williamh@g.o>
22 +# Marek Szuba <marecki@g.o>
23 +# @AUTHOR:
24 +# Marek Szuba <marecki@g.o>
25 +# Based on python-single-r1.eclass by Michał Górny <mgorny@g.o> et al.
26 +# @SUPPORTED_EAPIS: 7
27 +# @BLURB: An eclass for Lua packages not installed for multiple implementations.
28 +# @DESCRIPTION:
29 +# An extension of lua.eclass suite for packages which don't support being
30 +# installed for multiple Lua implementations. This mostly includes software
31 +# embedding Lua.
32 +#
33 +# This eclass sets correct IUSE. It also provides LUA_DEPS
34 +# and LUA_REQUIRED_USE that need to be added to appropriate ebuild
35 +# metadata variables.
36 +#
37 +# The eclass exports LUA_SINGLE_USEDEP that is suitable for depending
38 +# on other packages using the eclass. Dependencies on packages using
39 +# lua.eclass should be created via lua_gen_cond_dep() function, using
40 +# LUA_USEDEP placeholder.
41 +#
42 +# Please note that packages support multiple Lua implementations
43 +# (using lua.eclass) cannot depend on packages not supporting
44 +# them (using this eclass).
45 +#
46 +# Note that since this eclass always inherits lua-utils as well, in ebuilds
47 +# using the former there is no need to explicitly inherit the latter in order
48 +# to use helper functions such as lua_get_CFLAGS.
49 +
50 +case ${EAPI:-0} in
51 + 0|1|2|3|4|5|6)
52 + die "Unsupported EAPI=${EAPI} (too old) for ${ECLASS}"
53 + ;;
54 + 7)
55 + ;;
56 + *)
57 + die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
58 + ;;
59 +esac
60 +
61 +if [[ ! ${_LUA_SINGLE_R0} ]]; then
62 +
63 +if [[ ${_LUA_R0} ]]; then
64 + die 'lua-single.eclass cannot be used with lua.eclass.'
65 +fi
66 +
67 +inherit lua-utils
68 +
69 +fi
70 +
71 +EXPORT_FUNCTIONS pkg_setup
72 +
73 +# @ECLASS-VARIABLE: LUA_COMPAT
74 +# @REQUIRED
75 +# @PRE_INHERIT
76 +# @DESCRIPTION:
77 +# This variable contains a list of Lua implementations the package
78 +# supports. It must be set before the `inherit' call. It has to be
79 +# an array.
80 +#
81 +# Example:
82 +# @CODE
83 +# LUA_COMPAT=( lua5-1 lua5-2 lua5-3 )
84 +# @CODE
85 +#
86 +# Please note that you can also use bash brace expansion if you like:
87 +# @CODE
88 +# LUA_COMPAT=( lua5-{1..3} )
89 +# @CODE
90 +
91 +# @ECLASS-VARIABLE: LUA_COMPAT_OVERRIDE
92 +# @USER_VARIABLE
93 +# @DEFAULT_UNSET
94 +# @DESCRIPTION:
95 +# This variable can be used when working with ebuilds to override
96 +# the in-ebuild LUA_COMPAT. It is a string listing all
97 +# the implementations which package will be built for. It need be
98 +# specified in the calling environment, and not in ebuilds.
99 +#
100 +# It should be noted that in order to preserve metadata immutability,
101 +# LUA_COMPAT_OVERRIDE does not affect IUSE nor dependencies.
102 +# The state of LUA_TARGETS is ignored, and all the implementations
103 +# in LUA_COMPAT_OVERRIDE are built. Dependencies need to be satisfied
104 +# manually.
105 +#
106 +# Example:
107 +# @CODE
108 +# LUA_COMPAT_OVERRIDE='lua5-2' emerge -1v dev-lua/foo
109 +# @CODE
110 +
111 +# @ECLASS-VARIABLE: LUA_REQ_USE
112 +# @DEFAULT_UNSET
113 +# @PRE_INHERIT
114 +# @DESCRIPTION:
115 +# The list of USE flags required to be enabled on the chosen Lua
116 +# implementations, formed as a USE-dependency string. It should be valid
117 +# for all implementations in LUA_COMPAT, so it may be necessary to
118 +# use USE defaults.
119 +# This must be set before calling `inherit'.
120 +#
121 +# Example:
122 +# @CODE
123 +# LUA_REQ_USE="deprecated"
124 +# @CODE
125 +#
126 +# It will cause the Lua dependencies to look like:
127 +# @CODE
128 +# lua_targets_luaX-Y? ( dev-lang/lua:X.Y[deprecated] )
129 +# @CODE
130 +
131 +# @ECLASS-VARIABLE: LUA_DEPS
132 +# @OUTPUT_VARIABLE
133 +# @DESCRIPTION:
134 +# This is an eclass-generated Lua dependency string for all
135 +# implementations listed in LUA_COMPAT.
136 +#
137 +# Example use:
138 +# @CODE
139 +# RDEPEND="${LUA_DEPS}
140 +# dev-foo/mydep"
141 +# DEPEND="${RDEPEND}"
142 +# @CODE
143 +#
144 +# Example value:
145 +# @CODE
146 +# lua_targets_lua5-1? ( dev-lang/lua:5.1 )
147 +# lua_targets_lua5-2? ( dev-lang/lua:5.2 )
148 +# @CODE
149 +
150 +# @ECLASS-VARIABLE: LUA_REQUIRED_USE
151 +# @OUTPUT_VARIABLE
152 +# @DESCRIPTION:
153 +# This is an eclass-generated required-use expression which ensures at
154 +# least one Lua implementation has been enabled.
155 +#
156 +# This expression should be utilized in an ebuild by including it in
157 +# REQUIRED_USE, optionally behind a use flag.
158 +#
159 +# Example use:
160 +# @CODE
161 +# REQUIRED_USE="lua? ( ${LUA_REQUIRED_USE} )"
162 +# @CODE
163 +#
164 +# Example value:
165 +# @CODE
166 +# || ( lua_targets_lua5-1 lua_targets_lua5-2 )
167 +# @CODE
168 +
169 +# @ECLASS-VARIABLE: LUA_SINGLE_USEDEP
170 +# @OUTPUT_VARIABLE
171 +# @DESCRIPTION:
172 +# This is an eclass-generated USE-dependency string which can be used
173 +# to depend on another lua-single package being built for the same
174 +# Lua implementations.
175 +#
176 +# If you need to depend on a multi-impl (lua.eclass) package, use
177 +# lua_gen_cond_dep with LUA_USEDEP placeholder instead.
178 +#
179 +# Example use:
180 +# @CODE
181 +# RDEPEND="dev-lua/foo[${LUA_SINGLE_USEDEP}]"
182 +# @CODE
183 +#
184 +# Example value:
185 +# @CODE
186 +# lua_single_target_lua5-1(-)?
187 +# @CODE
188 +
189 +# @ECLASS-VARIABLE: LUA_USEDEP
190 +# @OUTPUT_VARIABLE
191 +# @DESCRIPTION:
192 +# This is an eclass-generated USE-dependency string which can be used to
193 +# depend on another Lua package being built for the same Lua
194 +# implementations.
195 +#
196 +# Example use:
197 +# @CODE
198 +# RDEPEND="dev-lua/foo[${LUA_USEDEP}]"
199 +# @CODE
200 +#
201 +# Example value:
202 +# @CODE
203 +# lua_targets_lua5-1(-)?,lua_targets_lua5-2(-)?
204 +# @CODE
205 +
206 +# @FUNCTION: _lua_single_set_globals
207 +# @INTERNAL
208 +# @DESCRIPTION:
209 +# Sets all the global output variables provided by this eclass.
210 +# This function must be called once, in global scope.
211 +_lua_single_set_globals() {
212 + _lua_set_impls
213 +
214 + local flags=( "${_LUA_SUPPORTED_IMPLS[@]/#/lua_single_target_}" )
215 +
216 + if [[ ${#_LUA_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
217 + # if only one implementation is supported, use IUSE defaults
218 + # to avoid requesting the user to enable it
219 + IUSE="+${flags[0]}"
220 + else
221 + IUSE="${flags[*]}"
222 + fi
223 +
224 + local requse="^^ ( ${flags[*]} )"
225 + local single_flags="${flags[@]/%/(-)?}"
226 + local single_usedep=${single_flags// /,}
227 +
228 + local deps= i PYTHON_PKG_DEP
229 + for i in "${_LUA_SUPPORTED_IMPLS[@]}"; do
230 + _lua_export "${i}" LUA_PKG_DEP
231 + deps+="lua_single_target_${i}? ( ${LUA_PKG_DEP} ) "
232 + done
233 +
234 + if [[ ${LUA_DEPS+1} ]]; then
235 + if [[ ${LUA_DEPS} != "${deps}" ]]; then
236 + eerror "LUA_DEPS have changed between inherits (LUA_REQ_USE?)!"
237 + eerror "Before: ${LUA_DEPS}"
238 + eerror "Now : ${deps}"
239 + die "LUA_DEPS integrity check failed"
240 + fi
241 +
242 + # these two are formality -- they depend on LUA_COMPAT only
243 + if [[ ${LUA_REQUIRED_USE} != ${requse} ]]; then
244 + eerror "LUA_REQUIRED_USE have changed between inherits!"
245 + eerror "Before: ${LUA_REQUIRED_USE}"
246 + eerror "Now : ${requse}"
247 + die "LUA_REQUIRED_USE integrity check failed"
248 + fi
249 +
250 + if [[ ${LUA_SINGLE_USEDEP} != "${single_usedep}" ]]; then
251 + eerror "LUA_SINGLE_USEDEP have changed between inherits!"
252 + eerror "Before: ${LUA_SINGLE_USEDEP}"
253 + eerror "Now : ${single_usedep}"
254 + die "LUA_SINGLE_USEDEP integrity check failed"
255 + fi
256 + else
257 + LUA_DEPS=${deps}
258 + LUA_REQUIRED_USE=${requse}
259 + LUA_SINGLE_USEDEP=${single_usedep}
260 + LUA_USEDEP='%LUA_USEDEP-NEEDS-TO-BE-USED-IN-LUA_GEN_COND_DEP%'
261 + readonly LUA_DEPS LUA_REQUIRED_USE LUA_SINGLE_USEDEP LUA_USEDEP
262 + fi
263 +}
264 +
265 +_lua_single_set_globals
266 +unset -f _lua_single_set_globals
267 +
268 +if [[ ! ${_LUA_SINGLE_R0} ]]; then
269 +
270 +# @FUNCTION: _lua_gen_usedep
271 +# @USAGE: [<pattern>...]
272 +# @INTERNAL
273 +# @DESCRIPTION:
274 +# Output a USE dependency string for Lua implementations which
275 +# are both in LUA_COMPAT and match any of the patterns passed
276 +# as parameters to the function.
277 +#
278 +# The patterns can be fnmatch-style patterns (matched via bash == operator
279 +# against LUA_COMPAT values). Remember to escape or quote the fnmatch
280 +# patterns to prevent accidental shell filename expansion.
281 +#
282 +# This is an internal function used to implement lua_gen_cond_dep.
283 +_lua_gen_usedep() {
284 + debug-print-function ${FUNCNAME} "${@}"
285 +
286 + local impl matches=()
287 +
288 + _lua_verify_patterns "${@}"
289 + for impl in "${_LUA_SUPPORTED_IMPLS[@]}"; do
290 + if _lua_impl_matches "${impl}" "${@}"; then
291 + matches+=(
292 + "lua_single_target_${impl}(-)?"
293 + )
294 + fi
295 + done
296 +
297 + [[ ${matches[@]} ]] || die "No supported implementations match lua_gen_usedep patterns: ${@}"
298 +
299 + local out=${matches[@]}
300 + echo "${out// /,}"
301 +}
302 +
303 +# @FUNCTION: _lua_impl_matches
304 +# @USAGE: <impl> [<pattern>...]
305 +# @INTERNAL
306 +# @DESCRIPTION:
307 +# Check whether the specified <impl> matches at least one
308 +# of the patterns following it. Return 0 if it does, 1 otherwise.
309 +# Matches if no patterns are provided.
310 +#
311 +# <impl> can be in LUA_COMPAT or ELUA form. The patterns can be
312 +# fnmatch-style patterns, e.g. 'lua5*', '..
313 +_lua_impl_matches() {
314 + [[ ${#} -ge 1 ]] || die "${FUNCNAME}: takes at least 1 parameter"
315 + [[ ${#} -eq 1 ]] && return 0
316 +
317 + local impl=${1} pattern
318 + shift
319 +
320 + for pattern; do
321 + # unify value style to allow lax matching
322 + if [[ ${impl/./-} == ${pattern/./-} ]]; then
323 + return 0
324 + fi
325 + done
326 +
327 + return 1
328 +}
329 +
330 +# @FUNCTION: _lua_verify_patterns
331 +# @USAGE: <pattern>...
332 +# @INTERNAL
333 +# @DESCRIPTION:
334 +# Verify whether the patterns passed to the eclass function are correct
335 +# (i.e. can match any valid implementation). Dies on wrong pattern.
336 +_lua_verify_patterns() {
337 + debug-print-function ${FUNCNAME} "${@}"
338 +
339 + local impl pattern
340 + for pattern; do
341 + for impl in "${_LUA_ALL_IMPLS[@]}"; do
342 + [[ ${impl} == ${pattern/./-} ]] && continue 2
343 + done
344 +
345 + die "Invalid implementation pattern: ${pattern}"
346 + done
347 +}
348 +
349 +# @FUNCTION: lua_gen_cond_dep
350 +# @USAGE: <dependency> [<pattern>...]
351 +# @DESCRIPTION:
352 +# Output a list of <dependency>-ies made conditional to USE flags
353 +# of Lua implementations which are both in LUA_COMPAT and match
354 +# any of the patterns passed as the remaining parameters.
355 +#
356 +# The patterns can be fnmatch-style patterns (matched via bash == operator
357 +# against LUA_COMPAT values). Remember to escape or quote the fnmatch
358 +# patterns to prevent accidental shell filename expansion.
359 +#
360 +# In order to enforce USE constraints on the packages, verbatim
361 +# '${LUA_SINGLE_USEDEP}' and '${LUA_USEDEP}' (quoted!) may
362 +# be placed in the dependency specification. It will get expanded within
363 +# the function into a proper USE dependency string.
364 +#
365 +# Example:
366 +# @CODE
367 +# LUA_COMPAT=( lua5-{1..3} )
368 +# RDEPEND="$(lua_gen_cond_dep \
369 +# 'dev-lua/backported_core_module[${LUA_USEDEP}]' lua5-1 lua5-2 )"
370 +# @CODE
371 +#
372 +# It will cause the variable to look like:
373 +# @CODE
374 +# RDEPEND="lua_single_target_lua5-1? (
375 +# dev-lua/backported_core_module[lua_targets_lua5-1(-)?,...] )
376 +# lua_single_target_lua5-2? (
377 +# dev-lua/backported_core_module[lua_targets_lua5-2(-)?,...] )"
378 +# @CODE
379 +lua_gen_cond_dep() {
380 + debug-print-function ${FUNCNAME} "${@}"
381 +
382 + local impl matches=()
383 +
384 + local dep=${1}
385 + shift
386 +
387 + _lua_verify_patterns "${@}"
388 + for impl in "${_LUA_SUPPORTED_IMPLS[@]}"; do
389 + if _lua_impl_matches "${impl}" "${@}"; then
390 + # substitute ${LUA_SINGLE_USEDEP} if used
391 + # (since lua_gen_usedep() will not return
392 + # ${LUA_SINGLE_USEDEP}, the code is run at most once)
393 + if [[ ${dep} == *'${LUA_SINGLE_USEDEP}'* ]]; then
394 + local usedep=$(_lua_gen_usedep "${@}")
395 + dep=${dep//\$\{LUA_SINGLE_USEDEP\}/${usedep}}
396 + fi
397 + local multi_usedep="lua_targets_${impl}(-)"
398 +
399 + local subdep=${dep//\$\{LUA_MULTI_USEDEP\}/${multi_usedep}}
400 + matches+=( "lua_single_target_${impl}? (
401 + ${subdep//\$\{LUA_USEDEP\}/${multi_usedep}} )" )
402 + fi
403 + done
404 +
405 + echo "${matches[@]}"
406 +}
407 +
408 +# @FUNCTION: lua_gen_impl_dep
409 +# @USAGE: [<requested-use-flags> [<impl-pattern>...]]
410 +# @DESCRIPTION:
411 +# Output a dependency on Lua implementations with the specified USE
412 +# dependency string appended, or no USE dependency string if called
413 +# without the argument (or with empty argument). If any implementation
414 +# patterns are passed, the output dependencies will be generated only
415 +# for the implementations matching them.
416 +#
417 +# The patterns can be fnmatch-style patterns (matched via bash == operator
418 +# against LUA_COMPAT values). Remember to escape or quote the fnmatch
419 +# patterns to prevent accidental shell filename expansion.
420 +#
421 +# Use this function when you need to request different USE flags
422 +# on the Lua interpreter depending on package's USE flags. If you
423 +# only need a single set of interpreter USE flags, just set
424 +# LUA_REQ_USE and use ${LUA_DEPS} globally.
425 +#
426 +# Example:
427 +# @CODE
428 +# LUA_COMPAT=( lua5-{1..3} )
429 +# RDEPEND="foo? ( $(lua_gen_impl_dep 'deprecated(+)' lua5-3 ) )"
430 +# @CODE
431 +#
432 +# It will cause the variable to look like:
433 +# @CODE
434 +# RDEPEND="foo? (
435 +# lua_single_target_lua5-3? ( dev-lang/lua:5.3[deprecated(+)] )
436 +# )"
437 +# @CODE
438 +lua_gen_impl_dep() {
439 + debug-print-function ${FUNCNAME} "${@}"
440 +
441 + local impl
442 + local matches=()
443 +
444 + local LUA_REQ_USE=${1}
445 + shift
446 +
447 + _lua_verify_patterns "${@}"
448 + for impl in "${_LUA_SUPPORTED_IMPLS[@]}"; do
449 + if _lua_impl_matches "${impl}" "${@}"; then
450 + local LUA_PKG_DEP
451 + _lua_export "${impl}" LUA_PKG_DEP
452 + matches+=( "lua_single_target_${impl}? ( ${LUA_PKG_DEP} )" )
453 + fi
454 + done
455 +
456 + echo "${matches[@]}"
457 +}
458 +
459 +# @FUNCTION: lua_setup
460 +# @DESCRIPTION:
461 +# Determine what the selected Lua implementation is and set
462 +# the Lua build environment up for it.
463 +lua_setup() {
464 + debug-print-function ${FUNCNAME} "${@}"
465 +
466 + unset ELUA
467 +
468 + # support developer override
469 + if [[ ${LUA_COMPAT_OVERRIDE} ]]; then
470 + local impls=( ${LUA_COMPAT_OVERRIDE} )
471 + [[ ${#impls[@]} -eq 1 ]] || die "LUA_COMPAT_OVERRIDE must name exactly one implementation for lua-single"
472 +
473 + ewarn "WARNING: LUA_COMPAT_OVERRIDE in effect. The following Lua"
474 + ewarn "implementation will be used:"
475 + ewarn
476 + ewarn " ${LUA_COMPAT_OVERRIDE}"
477 + ewarn
478 + ewarn "Dependencies won't be satisfied, and LUA_SINGLE_TARGET flags will be ignored."
479 +
480 + _lua_export "${impls[0]}" ELUA LUA
481 + _lua_wrapper_setup
482 + einfo "Using ${ELUA} to build"
483 + return
484 + fi
485 +
486 + local impl
487 + for impl in "${_LUA_SUPPORTED_IMPLS[@]}"; do
488 + if use "lua_single_target_${impl}"; then
489 + if [[ ${ELUA} ]]; then
490 + eerror "Your LUA_SINGLE_TARGET setting lists more than a single Lua"
491 + eerror "implementation. Please set it to just one value. If you need"
492 + eerror "to override the value for a single package, please use package.env"
493 + eerror "or an equivalent solution (man 5 portage)."
494 + echo
495 + die "More than one implementation in LUA_SINGLE_TARGET."
496 + fi
497 +
498 + _lua_export "${impl}" ELUA LUA
499 + _lua_wrapper_setup
500 + einfo "Using ${ELUA} to build"
501 + fi
502 + done
503 +
504 + if [[ ! ${ELUA} ]]; then
505 + eerror "No Lua implementation selected for the build. Please set"
506 + eerror "the LUA_SINGLE_TARGET variable in your make.conf to one"
507 + eerror "of the following values:"
508 + eerror
509 + eerror "${_LUA_SUPPORTED_IMPLS[@]}"
510 + echo
511 + die "No supported Lua implementation in LUA_SINGLE_TARGET."
512 + fi
513 +}
514 +
515 +# @FUNCTION: lua-single_pkg_setup
516 +# @DESCRIPTION:
517 +# Runs lua_setup.
518 +lua-single_pkg_setup() {
519 + debug-print-function ${FUNCNAME} "${@}"
520 +
521 + [[ ${MERGE_TYPE} != binary ]] && lua_setup
522 +}
523 +
524 +_LUA_SINGLE_R0=1
525 +fi
526 --
527 2.26.2