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 |