public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Michał Górny" <mgorny@gentoo.org>
To: gentoo-dev@lists.gentoo.org
Cc: Alfredo Tupone <tupone@gentoo.org>
Subject: Re: [gentoo-dev] [PATCH] ada.eclass: New eclass for dev-ada packages
Date: Fri, 13 Sep 2019 22:14:56 +0200	[thread overview]
Message-ID: <ac6b57e38c0ebb1839cf8dcf22bb5c4bcda0a69f.camel@gentoo.org> (raw)
In-Reply-To: <20190905182554.17582-1-tupone@gentoo.org>

[-- Attachment #1: Type: text/plain, Size: 14808 bytes --]

I'm sorry for not finding time to review this earlier.

On Thu, 2019-09-05 at 20:25 +0200, Tupone Alfredo wrote:
> Signed-off-by: Alfredo Tupone <tupone@gentoo.org>
> ---
>  eclass/ada.eclass | 435 ++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 435 insertions(+)
>  create mode 100644 eclass/ada.eclass
> 
> diff --git a/eclass/ada.eclass b/eclass/ada.eclass
> new file mode 100644
> index 000000000000..338b73bab86b
> --- /dev/null
> +++ b/eclass/ada.eclass
> @@ -0,0 +1,435 @@
> +# Copyright 2019 Gentoo Authors
> +# Distributed under the terms of the GNU General Public License v2
> +
> +# @ECLASS: ada.eclass
> +# @MAINTAINER:
> +# Ada team <ada@gentoo.org>
> +# @AUTHOR:
> +# Tupone Alfredo <tupone@gentoo.org>
> +# @BLURB: An eclass for Ada packages
> +# @DESCRIPTION:
> +# This eclass set the IUSE and REQUIRED_USE to request the ADA_TARGET
> +# when the inheriting ebuild can be supported by more than one Ada
> +# implementation. It also set ADA_USEDEP and ADA_DEPS with a suitable form.
> +# A common eclass providing helper functions to build and install
> +# packages supporting Ada implementations.
> +#
> +# This eclass sets correct IUSE. Modification of REQUIRED_USE has to
> +# be done by the author of the ebuild (but ADA_REQUIRED_USE is
> +# provided for convenience, see below). ada exports ADA_DEPS
> +# and ADA_USEDEP so you can create correct dependencies for your
> +# package easily.
> +#
> +# Mostly copied from python-single-r1.eclass
> +
> +case "${EAPI:-0}" in
> +	0|1|2|3|4)
> +		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
> +		;;
> +	5|6|7)
> +		# EAPI=5 is required for sane USE_EXPAND dependencies
> +		;;

Given that EAPI 5 is deprecated already, you shouldn't be adding any new
ebuilds with it.  Therefore, adding support for it is a bit pointless.

> +	*)
> +		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
> +		;;
> +esac
> +
> +EXPORT_FUNCTIONS pkg_setup
> +
> +# @ECLASS-VARIABLE: ADA_DEPS
> +# @DESCRIPTION:
> +# This is an eclass-generated Ada dependency string for all
> +# implementations listed in ADA_COMPAT.
> +#
> +# The dependency string is conditional on ADA_TARGET.
> +#
> +# Example use:
> +# @CODE
> +# RDEPEND="${ADA_DEPS}
> +#   dev-foo/mydep"
> +# DEPEND="${RDEPEND}"
> +# @CODE
> +#
> +
> +# @ECLASS-VARIABLE: _ADA_ALL_IMPLS
> +# @INTERNAL
> +# @DESCRIPTION:
> +# All supported Ada implementations, most preferred last.
> +_ADA_ALL_IMPLS=(
> +	gnat_2016 gnat_2017 gnat_2018 gnat_2019
> +)
> +readonly _ADA_ALL_IMPLS
> +
> +
> +# @FUNCTION: _ada_impl_supported
> +# @USAGE: <impl>
> +# @INTERNAL
> +# @DESCRIPTION:
> +# Check whether the implementation <impl> (ADA_COMPAT-form)
> +# is still supported.
> +#
> +# Returns 0 if the implementation is valid and supported. If it is
> +# unsupported, returns 1 -- and the caller should ignore the entry.
> +# If it is invalid, dies with an appopriate error messages.
> +_ada_impl_supported() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	[[ ${#} -eq 1 ]] || die "${FUNCNAME}: takes exactly 1 argument (impl)."
> +
> +	local impl=${1}
> +
> +	# keep in sync with _ADA_ALL_IMPLS!
> +	# (not using that list because inline patterns shall be faster)
> +	case "${impl}" in
> +		gnat_201[6789])
> +			return 0
> +			;;
> +		*)
> +			[[ ${ADA_COMPAT_NO_STRICT} ]] && return 1
> +			die "Invalid implementation in ADA_COMPAT: ${impl}"
> +	esac
> +}
> +
> +# @FUNCTION: _ada_set_impls
> +# @INTERNAL
> +# @DESCRIPTION:
> +# Check ADA_COMPAT for well-formedness and validity, then set
> +# two global variables:
> +#
> +# - _ADA_SUPPORTED_IMPLS containing valid implementations supported
> +#   by the ebuild (ADA_COMPAT - dead implementations),
> +#
> +# - and _ADA_UNSUPPORTED_IMPLS containing valid implementations that
> +#   are not supported by the ebuild.
> +#
> +# Implementations in both variables are ordered using the pre-defined
> +# eclass implementation ordering.
> +#
> +# This function must be called once in global scope by an eclass
> +# utilizing ADA_COMPAT.
> +_ada_set_impls() {
> +	local i
> +
> +	if ! declare -p ADA_COMPAT &>/dev/null; then
> +		die 'ADA_COMPAT not declared.'
> +	fi
> +	if [[ $(declare -p ADA_COMPAT) != "declare -a"* ]]; then
> +		die 'ADA_COMPAT must be an array.'
> +	fi
> +	for i in "${ADA_COMPAT[@]}"; do
> +		# trigger validity checks
> +		_ada_impl_supported "${i}"
> +	done
> +
> +	local supp=() unsupp=()
> +
> +	for i in "${_ADA_ALL_IMPLS[@]}"; do
> +		if has "${i}" "${ADA_COMPAT[@]}"; then
> +			supp+=( "${i}" )
> +		else
> +			unsupp+=( "${i}" )
> +		fi
> +	done
> +	if [[ ! ${supp[@]} ]]; then
> +		die "No supported implementation in ADA_COMPAT."
> +	fi
> +
> +	if [[ ${_ADA_SUPPORTED_IMPLS[@]} ]]; then
> +		# set once already, verify integrity
> +		if [[ ${_ADA_SUPPORTED_IMPLS[@]} != ${supp[@]} ]]; then
> +			eerror "Supported impls (ADA_COMPAT) changed between inherits!"
> +			eerror "Before: ${_ADA_SUPPORTED_IMPLS[*]}"
> +			eerror "Now   : ${supp[*]}"
> +			die "_ADA_SUPPORTED_IMPLS integrity check failed"
> +		fi
> +		if [[ ${_ADA_UNSUPPORTED_IMPLS[@]} != ${unsupp[@]} ]]; then
> +			eerror "Unsupported impls changed between inherits!"
> +			eerror "Before: ${_ADA_UNSUPPORTED_IMPLS[*]}"
> +			eerror "Now   : ${unsupp[*]}"
> +			die "_ADA_UNSUPPORTED_IMPLS integrity check failed"
> +		fi
> +	else
> +		_ADA_SUPPORTED_IMPLS=( "${supp[@]}" )
> +		_ADA_UNSUPPORTED_IMPLS=( "${unsupp[@]}" )
> +		readonly _ADA_SUPPORTED_IMPLS _ADA_UNSUPPORTED_IMPLS
> +	fi
> +}
> +
> +# @FUNCTION: ada_export

For the record, I consider python_export() API a mistake.  The wrapper
API was added later and with it, there's really no need for _export()
API, just wrapper setup and getters.

> +# @USAGE: [<impl>] <variables>...
> +# @DESCRIPTION:
> +# Set and export the Ada implementation-relevant variables passed
> +# as parameters.
> +#
> +# The optional first parameter may specify the requested Ada
> +# implementation (either as ADA_TARGETS value, e.g. ada2_7,
> +# or an EADA one, e.g. ada2.7). If no implementation passed,
> +# the current one will be obtained from ${EADA}.
> +#
> +# The variables which can be exported are: GCC, EADA, GNATMAKE.
> +# They are described more completely in the eclass
> +# variable documentation.
> +ada_export() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	local impl var
> +
> +	case "${1}" in
> +		gnat_201[6789])
> +			impl=${1}
> +			shift
> +			;;
> +		*)
> +			impl=${EADA}
> +			if [[ -z ${impl} ]]; then
> +				die "ada_export called without a ada implementation and EADA is unset"
> +			fi
> +			;;
> +	esac
> +	debug-print "${FUNCNAME}: implementation: ${impl}"
> +
> +	local gcc_pv
> +	case "${impl}" in
> +		gnat_2016)
> +			gcc_pv=4.9.4
> +			;;
> +		gnat_2017)
> +			gcc_pv=6.3.0
> +			;;
> +		gnat_2018)
> +			gcc_pv=7.3.1
> +			;;
> +		gnat_2019)
> +			gcc_pv=8.3.1
> +			;;
> +		*)
> +			gcc_pv="9.9.9"
> +			;;
> +	esac
> +
> +	for var; do
> +		case "${var}" in
> +			EADA)
> +				export EADA=${impl}
> +				debug-print "${FUNCNAME}: EADA = ${EADA}"
> +				;;
> +			GCC)
> +				export GCC=${EPREFIX}/usr/bin/gcc-${gcc_pv}
> +				debug-print "${FUNCNAME}: GCC = ${GCC}"
> +				;;
> +			GCC_PV)
> +				export GCC_PV=${gcc_pv}
> +				debug-print "${FUNCNAME}: GCC_PV = ${GCC_PV}"
> +				;;
> +			GNATBIND)
> +				export GNATBIND=${EPREFIX}/usr/bin/gnatbind-${gcc_pv}
> +				debug-print "${FUNCNAME}: GNATBIND = ${GNATBIND}"
> +				;;
> +			GNATMAKE)
> +				export GNATMAKE=${EPREFIX}/usr/bin/gnatmake-${gcc_pv}
> +				debug-print "${FUNCNAME}: GNATMAKE = ${GNATMAKE}"
> +				;;
> +			GNATLS)
> +				export GNATLS=${EPREFIX}/usr/bin/gnatls-${gcc_pv}
> +				debug-print "${FUNCNAME}: GNATLS = ${GNATLS}"
> +				;;
> +			ADA_PKG_DEP)
> +				ADA_PKG_DEP="dev-lang/gnat-gpl:${gcc_pv}"
> +
> +				# use-dep
> +				if [[ ${ADA_REQ_USE} ]]; then
> +					ADA_PKG_DEP+=[${ADA_REQ_USE}]
> +				fi
> +
> +				export ADA_PKG_DEP
> +				debug-print "${FUNCNAME}: ADA_PKG_DEP = ${ADA_PKG_DEP}"
> +				;;
> +			*)
> +				die "ada_export: unknown variable ${var}"
> +		esac
> +	done
> +}
> +
> +_ada_single_set_globals() {
> +	_ada_set_impls
> +	local i ADA_PKG_DEP
> +
> +	local flags=( "${_ADA_SUPPORTED_IMPLS[@]/#/ada_target_}" )
> +	local unflags=( "${_ADA_UNSUPPORTED_IMPLS[@]/#/-ada_target_}" )
> +	local allflags=( ${flags[@]} ${unflags[@]} )
> +
> +	local optflags=${flags[@]/%/(-)?}
> +
> +	IUSE="${allflags[*]}"
> +
> +	if [[ ${#_ADA_UNSUPPORTED_IMPLS[@]} -gt 0 ]]; then
> +		optflags+=,${unflags[@]/%/(-)}
> +	fi
> +
> +	local deps requse usedep
> +	if [[ ${#_ADA_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
> +		# There is only one supported implementation; set IUSE and other
> +		# variables without ADA_SINGLE_TARGET.
> +		requse=${flags[*]}
> +		ada_export "${_ADA_SUPPORTED_IMPLS[0]}" ADA_PKG_DEP
> +		deps="${flags[*]}? ( ${ADA_PKG_DEP} ) "
> +	else
> +		# Multiple supported implementations; honor ADA_TARGET.
> +		requse="^^ ( ${flags[*]} )"
> +
> +		for i in "${_ADA_SUPPORTED_IMPLS[@]}"; do
> +			ada_export "${i}" ADA_PKG_DEP
> +			deps+="ada_target_${i}? ( ${ADA_PKG_DEP} ) "
> +		done
> +	fi
> +	usedep=${optflags// /,}
> +	if [[ ${ADA_DEPS+1} ]]; then
> +		if [[ ${ADA_DEPS} != "${deps}" ]]; then
> +			eerror "ADA_DEPS have changed between inherits (ADA_REQ_USE?)!"
> +			eerror "Before: ${ADA_DEPS}"
> +			eerror "Now   : ${deps}"
> +			die "ADA_DEPS integrity check failed"
> +		fi
> +
> +		# these two are formality -- they depend on ADA_COMPAT only
> +		if [[ ${ADA_REQUIRED_USE} != ${requse} ]]; then
> +			eerror "ADA_REQUIRED_USE have changed between inherits!"
> +			eerror "Before: ${ADA_REQUIRED_USE}"
> +			eerror "Now   : ${requse}"
> +			die "ADA_REQUIRED_USE integrity check failed"
> +		fi
> +
> +		if [[ ${ADA_USEDEP} != "${usedep}" ]]; then
> +			eerror "ADA_USEDEP have changed between inherits!"
> +			eerror "Before: ${ADA_USEDEP}"
> +			eerror "Now   : ${usedep}"
> +			die "ADA_USEDEP integrity check failed"
> +		fi
> +	else
> +		ADA_DEPS=${deps}
> +		ADA_REQUIRED_USE=${requse}
> +		ADA_USEDEP=${usedep}
> +		readonly ADA_DEPS ADA_REQUIRED_USE ADA_USEDEP
> +	fi
> +}
> +_ada_single_set_globals
> +unset -f _ada_single_set_globals
> +
> +# @FUNCTION: ada_wrapper_setup
> +# @USAGE: [<path> [<impl>]]
> +# @DESCRIPTION:
> +# Create proper 'ada' executable wrappers
> +# in the directory named by <path>. Set up PATH
> +# appropriately. <path> defaults to ${T}/${EADA}.
> +#
> +# The wrappers will be created for implementation named by <impl>,
> +# or for one named by ${EADA} if no <impl> passed.
> +#
> +# If the named directory contains a ada symlink already, it will
> +# be assumed to contain proper wrappers already and only environment
> +# setup will be done. If wrapper update is requested, the directory
> +# shall be removed first.
> +ada_wrapper_setup() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	local workdir=${1:-${T}/${EADA}}
> +	local impl=${2:-${EADA}}
> +
> +	[[ ${workdir} ]] || die "${FUNCNAME}: no workdir specified."
> +	[[ ${impl} ]] || die "${FUNCNAME}: no impl nor EADA specified."
> +
> +	if [[ ! -x ${workdir}/bin/gnatmake ]]; then
> +		mkdir -p "${workdir}"/bin || die
> +
> +		local GCC GNATMAKE GNATLS GNATBIND
> +		ada_export "${impl}" GCC GNATMAKE GNATLS GNATBIND

This seems like basically a lot of indirection for unclear purpose.
The export/getter logic in Python is there because we sometimes need
those values in ebuilds.  Do you expect to need them outside
the wrapper?  If not, it would probably be more readable to just inline
proper paths here.

> +
> +		# Ada compiler
> +		cat > "${workdir}/bin/gcc" <<-_EOF_ || die
> +			#!/bin/sh
> +			exec "${GCC}" "\${@}"
> +		_EOF_
> +		chmod a+x "${workdir}/bin/gcc"

|| die.

> +		cat > "${workdir}/bin/gnatmake" <<-_EOF_ || die
> +			#!/bin/sh
> +			exec "${GNATMAKE}" "\${@}"
> +		_EOF_
> +		chmod a+x "${workdir}/bin/gnatmake"
> +		cat > "${workdir}/bin/gnatls" <<-_EOF_ || die
> +			#!/bin/sh
> +			exec "${GNATLS}" "\${@}"
> +		_EOF_
> +		chmod a+x "${workdir}/bin/gnatls"
> +		cat > "${workdir}/bin/gnatbind" <<-_EOF_ || die
> +			#!/bin/sh
> +			exec "${GNATBIND}" "\${@}"
> +		_EOF_
> +		chmod a+x "${workdir}/bin/gnatbind"
> +	fi
> +
> +	# Now, set the environment.
> +	# But note that ${workdir} may be shared with something else,
> +	# and thus already on top of PATH.
> +	if [[ ${PATH##:*} != ${workdir}/bin ]]; then
> +		PATH=${workdir}/bin${PATH:+:${PATH}}
> +	fi
> +	export PATH
> +}
> +
> +# @FUNCTION: ada_setup
> +# @DESCRIPTION:
> +# Determine what the selected Ada implementation is and set
> +# the Ada build environment up for it.
> +ada_setup() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	unset EADA
> +
> +	if [[ ${#_ADA_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
> +		if use "ada_targets_${_ADA_SUPPORTED_IMPLS[0]}"; then
> +			# Only one supported implementation, enable it explicitly
> +			ada_export "${_ADA_SUPPORTED_IMPLS[0]}" EADA GCC GCC_PV GNATMAKE

Why do you export it first, then again in the wrapper setup function?

> +			ada_wrapper_setup
> +		fi
> +	else
> +		local impl
> +		for impl in "${_ADA_SUPPORTED_IMPLS[@]}"; do
> +			if use "ada_target_${impl}"; then
> +				if [[ ${EADA} ]]; then
> +					eerror "Your ADA_TARGET setting lists more than a single Ada"
> +					eerror "implementation. Please set it to just one value. If you need"
> +					eerror "to override the value for a single package, please use package.env"
> +					eerror "or an equivalent solution (man 5 portage)."
> +					echo
> +					die "More than one implementation in ADA_TARGET."
> +				fi
> +
> +				ada_export "${impl}" EADA GCC GCC_PV GNATMAKE
> +				ada_wrapper_setup
> +			fi
> +		done
> +	fi
> +
> +	if [[ ! ${EADA} ]]; then
> +		eerror "No Ada implementation selected for the build. Please set"
> +		if [[ ${#_ADA_SUPPORTED_IMPLS[@]} -eq 1 ]]; then
> +			eerror "the ADA_TARGETS variable in your make.conf to include one"
> +		else
> +			eerror "the ADA_SINGLE_TARGET variable in your make.conf to one"
> +		fi
> +		eerror "of the following values:"
> +		eerror
> +		eerror "${_ADA_SUPPORTED_IMPLS[@]}"
> +		echo
> +		die "No supported Ada implementation in ADA_SINGLE_TARGET/ADA_TARGETS."
> +	fi
> +}
> +
> +# @FUNCTION: ada_pkg_setup
> +# @DESCRIPTION:
> +# Runs ada_setup.
> +ada_pkg_setup() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	[[ ${MERGE_TYPE} != binary ]] && ada_setup
> +}

-- 
Best regards,
Michał Górny


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 618 bytes --]

      reply	other threads:[~2019-09-13 20:15 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-05 18:25 [gentoo-dev] [PATCH] ada.eclass: New eclass for dev-ada packages Tupone Alfredo
2019-09-13 20:14 ` Michał Górny [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ac6b57e38c0ebb1839cf8dcf22bb5c4bcda0a69f.camel@gentoo.org \
    --to=mgorny@gentoo.org \
    --cc=gentoo-dev@lists.gentoo.org \
    --cc=tupone@gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox