Gentoo Archives: gentoo-dev

From: "Michał Górny" <mgorny@g.o>
To: gentoo-dev@l.g.o
Cc: Alfredo Tupone <tupone@g.o>
Subject: Re: [gentoo-dev] [PATCH] ada.eclass: New eclass for dev-ada packages
Date: Fri, 13 Sep 2019 20:15:10
Message-Id: ac6b57e38c0ebb1839cf8dcf22bb5c4bcda0a69f.camel@gentoo.org
In Reply to: [gentoo-dev] [PATCH] ada.eclass: New eclass for dev-ada packages by Tupone Alfredo
1 I'm sorry for not finding time to review this earlier.
2
3 On Thu, 2019-09-05 at 20:25 +0200, Tupone Alfredo wrote:
4 > Signed-off-by: Alfredo Tupone <tupone@g.o>
5 > ---
6 > eclass/ada.eclass | 435 ++++++++++++++++++++++++++++++++++++++++++++++
7 > 1 file changed, 435 insertions(+)
8 > create mode 100644 eclass/ada.eclass
9 >
10 > diff --git a/eclass/ada.eclass b/eclass/ada.eclass
11 > new file mode 100644
12 > index 000000000000..338b73bab86b
13 > --- /dev/null
14 > +++ b/eclass/ada.eclass
15 > @@ -0,0 +1,435 @@
16 > +# Copyright 2019 Gentoo Authors
17 > +# Distributed under the terms of the GNU General Public License v2
18 > +
19 > +# @ECLASS: ada.eclass
20 > +# @MAINTAINER:
21 > +# Ada team <ada@g.o>
22 > +# @AUTHOR:
23 > +# Tupone Alfredo <tupone@g.o>
24 > +# @BLURB: An eclass for Ada packages
25 > +# @DESCRIPTION:
26 > +# This eclass set the IUSE and REQUIRED_USE to request the ADA_TARGET
27 > +# when the inheriting ebuild can be supported by more than one Ada
28 > +# implementation. It also set ADA_USEDEP and ADA_DEPS with a suitable form.
29 > +# A common eclass providing helper functions to build and install
30 > +# packages supporting Ada implementations.
31 > +#
32 > +# This eclass sets correct IUSE. Modification of REQUIRED_USE has to
33 > +# be done by the author of the ebuild (but ADA_REQUIRED_USE is
34 > +# provided for convenience, see below). ada exports ADA_DEPS
35 > +# and ADA_USEDEP so you can create correct dependencies for your
36 > +# package easily.
37 > +#
38 > +# Mostly copied from python-single-r1.eclass
39 > +
40 > +case "${EAPI:-0}" in
41 > + 0|1|2|3|4)
42 > + die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
43 > + ;;
44 > + 5|6|7)
45 > + # EAPI=5 is required for sane USE_EXPAND dependencies
46 > + ;;
47
48 Given that EAPI 5 is deprecated already, you shouldn't be adding any new
49 ebuilds with it. Therefore, adding support for it is a bit pointless.
50
51 > + *)
52 > + die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
53 > + ;;
54 > +esac
55 > +
56 > +EXPORT_FUNCTIONS pkg_setup
57 > +
58 > +# @ECLASS-VARIABLE: ADA_DEPS
59 > +# @DESCRIPTION:
60 > +# This is an eclass-generated Ada dependency string for all
61 > +# implementations listed in ADA_COMPAT.
62 > +#
63 > +# The dependency string is conditional on ADA_TARGET.
64 > +#
65 > +# Example use:
66 > +# @CODE
67 > +# RDEPEND="${ADA_DEPS}
68 > +# dev-foo/mydep"
69 > +# DEPEND="${RDEPEND}"
70 > +# @CODE
71 > +#
72 > +
73 > +# @ECLASS-VARIABLE: _ADA_ALL_IMPLS
74 > +# @INTERNAL
75 > +# @DESCRIPTION:
76 > +# All supported Ada implementations, most preferred last.
77 > +_ADA_ALL_IMPLS=(
78 > + gnat_2016 gnat_2017 gnat_2018 gnat_2019
79 > +)
80 > +readonly _ADA_ALL_IMPLS
81 > +
82 > +
83 > +# @FUNCTION: _ada_impl_supported
84 > +# @USAGE: <impl>
85 > +# @INTERNAL
86 > +# @DESCRIPTION:
87 > +# Check whether the implementation <impl> (ADA_COMPAT-form)
88 > +# is still supported.
89 > +#
90 > +# Returns 0 if the implementation is valid and supported. If it is
91 > +# unsupported, returns 1 -- and the caller should ignore the entry.
92 > +# If it is invalid, dies with an appopriate error messages.
93 > +_ada_impl_supported() {
94 > + debug-print-function ${FUNCNAME} "${@}"
95 > +
96 > + [[ ${#} -eq 1 ]] || die "${FUNCNAME}: takes exactly 1 argument (impl)."
97 > +
98 > + local impl=${1}
99 > +
100 > + # keep in sync with _ADA_ALL_IMPLS!
101 > + # (not using that list because inline patterns shall be faster)
102 > + case "${impl}" in
103 > + gnat_201[6789])
104 > + return 0
105 > + ;;
106 > + *)
107 > + [[ ${ADA_COMPAT_NO_STRICT} ]] && return 1
108 > + die "Invalid implementation in ADA_COMPAT: ${impl}"
109 > + esac
110 > +}
111 > +
112 > +# @FUNCTION: _ada_set_impls
113 > +# @INTERNAL
114 > +# @DESCRIPTION:
115 > +# Check ADA_COMPAT for well-formedness and validity, then set
116 > +# two global variables:
117 > +#
118 > +# - _ADA_SUPPORTED_IMPLS containing valid implementations supported
119 > +# by the ebuild (ADA_COMPAT - dead implementations),
120 > +#
121 > +# - and _ADA_UNSUPPORTED_IMPLS containing valid implementations that
122 > +# are not supported by the ebuild.
123 > +#
124 > +# Implementations in both variables are ordered using the pre-defined
125 > +# eclass implementation ordering.
126 > +#
127 > +# This function must be called once in global scope by an eclass
128 > +# utilizing ADA_COMPAT.
129 > +_ada_set_impls() {
130 > + local i
131 > +
132 > + if ! declare -p ADA_COMPAT &>/dev/null; then
133 > + die 'ADA_COMPAT not declared.'
134 > + fi
135 > + if [[ $(declare -p ADA_COMPAT) != "declare -a"* ]]; then
136 > + die 'ADA_COMPAT must be an array.'
137 > + fi
138 > + for i in "${ADA_COMPAT[@]}"; do
139 > + # trigger validity checks
140 > + _ada_impl_supported "${i}"
141 > + done
142 > +
143 > + local supp=() unsupp=()
144 > +
145 > + for i in "${_ADA_ALL_IMPLS[@]}"; do
146 > + if has "${i}" "${ADA_COMPAT[@]}"; then
147 > + supp+=( "${i}" )
148 > + else
149 > + unsupp+=( "${i}" )
150 > + fi
151 > + done
152 > + if [[ ! ${supp[@]} ]]; then
153 > + die "No supported implementation in ADA_COMPAT."
154 > + fi
155 > +
156 > + if [[ ${_ADA_SUPPORTED_IMPLS[@]} ]]; then
157 > + # set once already, verify integrity
158 > + if [[ ${_ADA_SUPPORTED_IMPLS[@]} != ${supp[@]} ]]; then
159 > + eerror "Supported impls (ADA_COMPAT) changed between inherits!"
160 > + eerror "Before: ${_ADA_SUPPORTED_IMPLS[*]}"
161 > + eerror "Now : ${supp[*]}"
162 > + die "_ADA_SUPPORTED_IMPLS integrity check failed"
163 > + fi
164 > + if [[ ${_ADA_UNSUPPORTED_IMPLS[@]} != ${unsupp[@]} ]]; then
165 > + eerror "Unsupported impls changed between inherits!"
166 > + eerror "Before: ${_ADA_UNSUPPORTED_IMPLS[*]}"
167 > + eerror "Now : ${unsupp[*]}"
168 > + die "_ADA_UNSUPPORTED_IMPLS integrity check failed"
169 > + fi
170 > + else
171 > + _ADA_SUPPORTED_IMPLS=( "${supp[@]}" )
172 > + _ADA_UNSUPPORTED_IMPLS=( "${unsupp[@]}" )
173 > + readonly _ADA_SUPPORTED_IMPLS _ADA_UNSUPPORTED_IMPLS
174 > + fi
175 > +}
176 > +
177 > +# @FUNCTION: ada_export
178
179 For the record, I consider python_export() API a mistake. The wrapper
180 API was added later and with it, there's really no need for _export()
181 API, just wrapper setup and getters.
182
183 > +# @USAGE: [<impl>] <variables>...
184 > +# @DESCRIPTION:
185 > +# Set and export the Ada implementation-relevant variables passed
186 > +# as parameters.
187 > +#
188 > +# The optional first parameter may specify the requested Ada
189 > +# implementation (either as ADA_TARGETS value, e.g. ada2_7,
190 > +# or an EADA one, e.g. ada2.7). If no implementation passed,
191 > +# the current one will be obtained from ${EADA}.
192 > +#
193 > +# The variables which can be exported are: GCC, EADA, GNATMAKE.
194 > +# They are described more completely in the eclass
195 > +# variable documentation.
196 > +ada_export() {
197 > + debug-print-function ${FUNCNAME} "${@}"
198 > +
199 > + local impl var
200 > +
201 > + case "${1}" in
202 > + gnat_201[6789])
203 > + impl=${1}
204 > + shift
205 > + ;;
206 > + *)
207 > + impl=${EADA}
208 > + if [[ -z ${impl} ]]; then
209 > + die "ada_export called without a ada implementation and EADA is unset"
210 > + fi
211 > + ;;
212 > + esac
213 > + debug-print "${FUNCNAME}: implementation: ${impl}"
214 > +
215 > + local gcc_pv
216 > + case "${impl}" in
217 > + gnat_2016)
218 > + gcc_pv=4.9.4
219 > + ;;
220 > + gnat_2017)
221 > + gcc_pv=6.3.0
222 > + ;;
223 > + gnat_2018)
224 > + gcc_pv=7.3.1
225 > + ;;
226 > + gnat_2019)
227 > + gcc_pv=8.3.1
228 > + ;;
229 > + *)
230 > + gcc_pv="9.9.9"
231 > + ;;
232 > + esac
233 > +
234 > + for var; do
235 > + case "${var}" in
236 > + EADA)
237 > + export EADA=${impl}
238 > + debug-print "${FUNCNAME}: EADA = ${EADA}"
239 > + ;;
240 > + GCC)
241 > + export GCC=${EPREFIX}/usr/bin/gcc-${gcc_pv}
242 > + debug-print "${FUNCNAME}: GCC = ${GCC}"
243 > + ;;
244 > + GCC_PV)
245 > + export GCC_PV=${gcc_pv}
246 > + debug-print "${FUNCNAME}: GCC_PV = ${GCC_PV}"
247 > + ;;
248 > + GNATBIND)
249 > + export GNATBIND=${EPREFIX}/usr/bin/gnatbind-${gcc_pv}
250 > + debug-print "${FUNCNAME}: GNATBIND = ${GNATBIND}"
251 > + ;;
252 > + GNATMAKE)
253 > + export GNATMAKE=${EPREFIX}/usr/bin/gnatmake-${gcc_pv}
254 > + debug-print "${FUNCNAME}: GNATMAKE = ${GNATMAKE}"
255 > + ;;
256 > + GNATLS)
257 > + export GNATLS=${EPREFIX}/usr/bin/gnatls-${gcc_pv}
258 > + debug-print "${FUNCNAME}: GNATLS = ${GNATLS}"
259 > + ;;
260 > + ADA_PKG_DEP)
261 > + ADA_PKG_DEP="dev-lang/gnat-gpl:${gcc_pv}"
262 > +
263 > + # use-dep
264 > + if [[ ${ADA_REQ_USE} ]]; then
265 > + ADA_PKG_DEP+=[${ADA_REQ_USE}]
266 > + fi
267 > +
268 > + export ADA_PKG_DEP
269 > + debug-print "${FUNCNAME}: ADA_PKG_DEP = ${ADA_PKG_DEP}"
270 > + ;;
271 > + *)
272 > + die "ada_export: unknown variable ${var}"
273 > + esac
274 > + done
275 > +}
276 > +
277 > +_ada_single_set_globals() {
278 > + _ada_set_impls
279 > + local i ADA_PKG_DEP
280 > +
281 > + local flags=( "${_ADA_SUPPORTED_IMPLS[@]/#/ada_target_}" )
282 > + local unflags=( "${_ADA_UNSUPPORTED_IMPLS[@]/#/-ada_target_}" )
283 > + local allflags=( ${flags[@]} ${unflags[@]} )
284 > +
285 > + local optflags=${flags[@]/%/(-)?}
286 > +
287 > + IUSE="${allflags[*]}"
288 > +
289 > + if [[ ${#_ADA_UNSUPPORTED_IMPLS[@]} -gt 0 ]]; then
290 > + optflags+=,${unflags[@]/%/(-)}
291 > + fi
292 > +
293 > + local deps requse usedep
294 > + if [[ ${#_ADA_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
295 > + # There is only one supported implementation; set IUSE and other
296 > + # variables without ADA_SINGLE_TARGET.
297 > + requse=${flags[*]}
298 > + ada_export "${_ADA_SUPPORTED_IMPLS[0]}" ADA_PKG_DEP
299 > + deps="${flags[*]}? ( ${ADA_PKG_DEP} ) "
300 > + else
301 > + # Multiple supported implementations; honor ADA_TARGET.
302 > + requse="^^ ( ${flags[*]} )"
303 > +
304 > + for i in "${_ADA_SUPPORTED_IMPLS[@]}"; do
305 > + ada_export "${i}" ADA_PKG_DEP
306 > + deps+="ada_target_${i}? ( ${ADA_PKG_DEP} ) "
307 > + done
308 > + fi
309 > + usedep=${optflags// /,}
310 > + if [[ ${ADA_DEPS+1} ]]; then
311 > + if [[ ${ADA_DEPS} != "${deps}" ]]; then
312 > + eerror "ADA_DEPS have changed between inherits (ADA_REQ_USE?)!"
313 > + eerror "Before: ${ADA_DEPS}"
314 > + eerror "Now : ${deps}"
315 > + die "ADA_DEPS integrity check failed"
316 > + fi
317 > +
318 > + # these two are formality -- they depend on ADA_COMPAT only
319 > + if [[ ${ADA_REQUIRED_USE} != ${requse} ]]; then
320 > + eerror "ADA_REQUIRED_USE have changed between inherits!"
321 > + eerror "Before: ${ADA_REQUIRED_USE}"
322 > + eerror "Now : ${requse}"
323 > + die "ADA_REQUIRED_USE integrity check failed"
324 > + fi
325 > +
326 > + if [[ ${ADA_USEDEP} != "${usedep}" ]]; then
327 > + eerror "ADA_USEDEP have changed between inherits!"
328 > + eerror "Before: ${ADA_USEDEP}"
329 > + eerror "Now : ${usedep}"
330 > + die "ADA_USEDEP integrity check failed"
331 > + fi
332 > + else
333 > + ADA_DEPS=${deps}
334 > + ADA_REQUIRED_USE=${requse}
335 > + ADA_USEDEP=${usedep}
336 > + readonly ADA_DEPS ADA_REQUIRED_USE ADA_USEDEP
337 > + fi
338 > +}
339 > +_ada_single_set_globals
340 > +unset -f _ada_single_set_globals
341 > +
342 > +# @FUNCTION: ada_wrapper_setup
343 > +# @USAGE: [<path> [<impl>]]
344 > +# @DESCRIPTION:
345 > +# Create proper 'ada' executable wrappers
346 > +# in the directory named by <path>. Set up PATH
347 > +# appropriately. <path> defaults to ${T}/${EADA}.
348 > +#
349 > +# The wrappers will be created for implementation named by <impl>,
350 > +# or for one named by ${EADA} if no <impl> passed.
351 > +#
352 > +# If the named directory contains a ada symlink already, it will
353 > +# be assumed to contain proper wrappers already and only environment
354 > +# setup will be done. If wrapper update is requested, the directory
355 > +# shall be removed first.
356 > +ada_wrapper_setup() {
357 > + debug-print-function ${FUNCNAME} "${@}"
358 > +
359 > + local workdir=${1:-${T}/${EADA}}
360 > + local impl=${2:-${EADA}}
361 > +
362 > + [[ ${workdir} ]] || die "${FUNCNAME}: no workdir specified."
363 > + [[ ${impl} ]] || die "${FUNCNAME}: no impl nor EADA specified."
364 > +
365 > + if [[ ! -x ${workdir}/bin/gnatmake ]]; then
366 > + mkdir -p "${workdir}"/bin || die
367 > +
368 > + local GCC GNATMAKE GNATLS GNATBIND
369 > + ada_export "${impl}" GCC GNATMAKE GNATLS GNATBIND
370
371 This seems like basically a lot of indirection for unclear purpose.
372 The export/getter logic in Python is there because we sometimes need
373 those values in ebuilds. Do you expect to need them outside
374 the wrapper? If not, it would probably be more readable to just inline
375 proper paths here.
376
377 > +
378 > + # Ada compiler
379 > + cat > "${workdir}/bin/gcc" <<-_EOF_ || die
380 > + #!/bin/sh
381 > + exec "${GCC}" "\${@}"
382 > + _EOF_
383 > + chmod a+x "${workdir}/bin/gcc"
384
385 || die.
386
387 > + cat > "${workdir}/bin/gnatmake" <<-_EOF_ || die
388 > + #!/bin/sh
389 > + exec "${GNATMAKE}" "\${@}"
390 > + _EOF_
391 > + chmod a+x "${workdir}/bin/gnatmake"
392 > + cat > "${workdir}/bin/gnatls" <<-_EOF_ || die
393 > + #!/bin/sh
394 > + exec "${GNATLS}" "\${@}"
395 > + _EOF_
396 > + chmod a+x "${workdir}/bin/gnatls"
397 > + cat > "${workdir}/bin/gnatbind" <<-_EOF_ || die
398 > + #!/bin/sh
399 > + exec "${GNATBIND}" "\${@}"
400 > + _EOF_
401 > + chmod a+x "${workdir}/bin/gnatbind"
402 > + fi
403 > +
404 > + # Now, set the environment.
405 > + # But note that ${workdir} may be shared with something else,
406 > + # and thus already on top of PATH.
407 > + if [[ ${PATH##:*} != ${workdir}/bin ]]; then
408 > + PATH=${workdir}/bin${PATH:+:${PATH}}
409 > + fi
410 > + export PATH
411 > +}
412 > +
413 > +# @FUNCTION: ada_setup
414 > +# @DESCRIPTION:
415 > +# Determine what the selected Ada implementation is and set
416 > +# the Ada build environment up for it.
417 > +ada_setup() {
418 > + debug-print-function ${FUNCNAME} "${@}"
419 > +
420 > + unset EADA
421 > +
422 > + if [[ ${#_ADA_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
423 > + if use "ada_targets_${_ADA_SUPPORTED_IMPLS[0]}"; then
424 > + # Only one supported implementation, enable it explicitly
425 > + ada_export "${_ADA_SUPPORTED_IMPLS[0]}" EADA GCC GCC_PV GNATMAKE
426
427 Why do you export it first, then again in the wrapper setup function?
428
429 > + ada_wrapper_setup
430 > + fi
431 > + else
432 > + local impl
433 > + for impl in "${_ADA_SUPPORTED_IMPLS[@]}"; do
434 > + if use "ada_target_${impl}"; then
435 > + if [[ ${EADA} ]]; then
436 > + eerror "Your ADA_TARGET setting lists more than a single Ada"
437 > + eerror "implementation. Please set it to just one value. If you need"
438 > + eerror "to override the value for a single package, please use package.env"
439 > + eerror "or an equivalent solution (man 5 portage)."
440 > + echo
441 > + die "More than one implementation in ADA_TARGET."
442 > + fi
443 > +
444 > + ada_export "${impl}" EADA GCC GCC_PV GNATMAKE
445 > + ada_wrapper_setup
446 > + fi
447 > + done
448 > + fi
449 > +
450 > + if [[ ! ${EADA} ]]; then
451 > + eerror "No Ada implementation selected for the build. Please set"
452 > + if [[ ${#_ADA_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
453 > + eerror "the ADA_TARGETS variable in your make.conf to include one"
454 > + else
455 > + eerror "the ADA_SINGLE_TARGET variable in your make.conf to one"
456 > + fi
457 > + eerror "of the following values:"
458 > + eerror
459 > + eerror "${_ADA_SUPPORTED_IMPLS[@]}"
460 > + echo
461 > + die "No supported Ada implementation in ADA_SINGLE_TARGET/ADA_TARGETS."
462 > + fi
463 > +}
464 > +
465 > +# @FUNCTION: ada_pkg_setup
466 > +# @DESCRIPTION:
467 > +# Runs ada_setup.
468 > +ada_pkg_setup() {
469 > + debug-print-function ${FUNCNAME} "${@}"
470 > +
471 > + [[ ${MERGE_TYPE} != binary ]] && ada_setup
472 > +}
473
474 --
475 Best regards,
476 Michał Górny

Attachments

File name MIME type
signature.asc application/pgp-signature