From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from lists.gentoo.org (pigeon.gentoo.org [208.92.234.80]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by finch.gentoo.org (Postfix) with ESMTPS id 0C2AA159C9B for ; Sun, 11 Aug 2024 23:18:30 +0000 (UTC) Received: from pigeon.gentoo.org (localhost [127.0.0.1]) by pigeon.gentoo.org (Postfix) with SMTP id 833F3E2A62; Sun, 11 Aug 2024 23:18:10 +0000 (UTC) Received: from smtp.gentoo.org (woodpecker.gentoo.org [IPv6:2001:470:ea4a:1:5054:ff:fec7:86e4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by pigeon.gentoo.org (Postfix) with ESMTPS id EC853E2A5E for ; Sun, 11 Aug 2024 23:18:09 +0000 (UTC) From: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= To: gentoo-dev@lists.gentoo.org Cc: =?UTF-8?q?Arsen=20Arsenovi=C4=87?= Subject: [gentoo-dev] [RFC HELP WANTED 1/9] guile-utils.eclass: new eclass, common code for guile packages Date: Mon, 12 Aug 2024 00:22:46 +0200 Message-ID: <20240811231742.942813-2-arsen@gentoo.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240811231742.942813-1-arsen@gentoo.org> References: <20240811231742.942813-1-arsen@gentoo.org> Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Id: Gentoo Linux mail X-BeenThere: gentoo-dev@lists.gentoo.org Reply-to: gentoo-dev@lists.gentoo.org X-Auto-Response-Suppress: DR, RN, NRN, OOF, AutoReply MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Archives-Salt: 455e4dd0-de0b-4c5b-8d4f-5c708eabb5de X-Archives-Hash: 857ae74c11b00834c31e1b1bd7c0121a Bug: https://bugs.gentoo.org/689408 Signed-off-by: Arsen Arsenović --- eclass/guile-utils.eclass | 277 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 277 insertions(+) create mode 100644 eclass/guile-utils.eclass diff --git a/eclass/guile-utils.eclass b/eclass/guile-utils.eclass new file mode 100644 index 000000000000..a7cfc0cc8724 --- /dev/null +++ b/eclass/guile-utils.eclass @@ -0,0 +1,277 @@ +# Copyright 2023-2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: guile-utils.eclass +# @MAINTAINER: +# Gentoo Scheme project +# @AUTHOR: +# Author: Arsen Arsenović +# Inspired by prior work in the Gentoo Python ecosystem. +# @BLURB: Common code between GNU Guile-related eclasses and ebuilds. +# @SUPPORTED_EAPIS: 8 +# @DESCRIPTION: +# This eclass contains various bits of common code between +# dev-scheme/guile, Guile multi-implementation ebuilds and Guile +# single-implementation ebuilds. + +case "${EAPI}" in + 8) ;; + *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; +esac + +if [[ ! "${_GUILE_UTILS_ECLASS}" ]]; then +_GUILE_UTILS_ECLASS=1 + +inherit toolchain-funcs + +BDEPEND="virtual/pkgconfig" + +# @ECLASS_VARIABLE: GUILE_COMPAT +# @REQUIRED +# @PRE_INHERIT +# @DESCRIPTION: +# List of acceptable versions of Guile. For instance, setting this +# variable like below will allow the package to be built against either +# Guile 2.2 or 3.0: +# +# @CODE +# GUILE_COMPAT=( 2-2 3-0 ) +# @CODE +# +# Please keep in ascending order. + +# @FUNCTION: guile_check_compat +# @DESCRIPTION: +# Checks that GUILE_COMPAT is set to an array, and has no invalid +# values. +guile_check_compat() { + debug-print-function ${FUNCNAME} "${@}" + + if ! [[ $(declare -p GUILE_COMPAT) =~ 'declare -a '* ]]; then + die "GUILE_COMPAT not set to an array" + fi + + if [[ ${#GUILE_COMPAT[@]} -eq 0 ]]; then + die "GUILE_COMPAT is empty" + fi +} + +guile_check_compat + +# @ECLASS_VARIABLE: GUILE_REQ_USE +# @PRE_INHERIT +# @DEFAULT_UNSET +# @DESCRIPTION: +# Specifies a USE dependency string for all versions of Guile in +# GUILE_COMPAT. +# +# @EXAMPLE: +# GUILE_REQ_USE="deprecated" + +# @ECLASS_VARIABLE: GUILE_USEDEP +# @OUTPUT_VARIABLE +# @DESCRIPTION: +# This variable is populated with a USE-dependency string which can be +# used to depend on other Guile multi-implementation packages. +# This variable is not usable from guile-single packages. + +# @ECLASS_VARIABLE: GUILE_DEPS +# @OUTPUT_VARIABLE +# @DESCRIPTION: +# Contains the dependency string for the compatible Guile runtimes. + +# @FUNCTION: guile_set_common_vars +# @USAGE: guile_set_common_vars +# @VARIABLE: QA_PREBUILT +# @DESCRIPTION: +# Sets common variables that apply to all Guile packages, namely, +# QA_PREBUILT. +guile_set_common_vars() { + debug-print-function ${FUNCNAME} "${@}" + + # These aren't strictly speaking prebuilt. but they do generated a + # nonstandard ELF object. + if [[ -z ${QA_PREBUILT} ]]; then + QA_PREBUILT="usr/$(get_libdir)/guile/*/site-ccache/*" + fi +} + +# @FUNCTION: guile_filter_pkgconfig_path +# @USAGE: ... +# @DESCRIPTION: +# Alters ${PKG_CONFIG_PATH} such that it does not contain any Guile +# slots besides the ones required by the caller. +guile_filter_pkgconfig_path() { + debug-print-function ${FUNCNAME} "${@}" + + local filtered_path= unfiltered_path path + IFS=: read -ra unfiltered_path <<<"${PKG_CONFIG_PATH}" + debug-print "Unfiltered PKG_CONFIG_PATH:" "${unfiltered_path[@]}" + for p in "${unfiltered_path[@]}"; do + for v in "$@"; do + debug-print "... considering '${p}' for ${v}" + # Exclude non-selected versions. + [[ ${p} == */usr/share/guile-data/${v}/pkgconfig* ]] \ + || continue + debug-print "... OK" + + # Add separator, if some data already exists. + [[ "${filtered_path}" ]] && filtered_path+=: + + filtered_path+="${p}" + break + done + done + + debug-print "${FUNCNAME}: Constructed PKG_CONFIG_PATH: ${filtered_path}" + PKG_CONFIG_PATH="$filtered_path" +} + +# @FUNCTION: guile_generate_depstrings +# @USAGE: +# @DESCRIPTION: +# Generates GUILE_REQUIRED_USE/GUILE_DEPS/GUILE_USEDEP based on +# GUILE_COMPAT, and populates IUSE. +guile_generate_depstrings() { + debug-print-function ${FUNCNAME} "${@}" + + # Generate IUSE, REQUIRED_USE, GUILE_USEDEP + local prefix="$1" depop="$2" + GUILE_USEDEP="" + local ver uses=() + # TODO(arsen): enforce GUILE_COMPAT is in ascending order. + for ver in "${GUILE_COMPAT[@]}"; do + [[ -n ${GUILE_USEDEP} ]] && GUILE_USEDEP+="," + uses+=("${prefix}_${ver}") + GUILE_USEDEP+="${prefix}_${ver}" + done + GUILE_REQUIRED_USE="${depop} ( ${uses[@]} )" + IUSE="${uses[@]}" + debug-print "${FUNCNAME}: requse ${GUILE_REQUIRED_USE}" + debug-print "${FUNCNAME}: generated ${uses[*]}" + debug-print "${FUNCNAME}: iuse ${IUSE}" + + # Generate GUILE_DEPS + local base_deps=() + local requse="${GUILE_REQ_USE+[}${GUILE_REQ_USE:-}${GUILE_REQ_USE+]}" + for ver in "${GUILE_COMPAT[@]}"; do + base_deps+=" + ${prefix}_${ver}? ( + dev-scheme/guile:${ver/-/.}${requse} + ) + " + done + GUILE_DEPS="${base_deps[*]}" + debug-print "${FUNCNAME}: GUILE_DEPS=${GUILE_DEPS}" + debug-print "${FUNCNAME}: GUILE_USEDEP=${GUILE_USEDEP}" +} + +# @FUNCTION: guile_unstrip_ccache +# @DESCRIPTION: +# Marks site-ccache files not to be stripped. Operates on ${D}. +guile_unstrip_ccache() { + debug-print-function ${FUNCNAME} "${@}" + + local ccache + while read -r -d $'\0' ccache; do + debug-print "${FUNCNAME}: ccache found: ${ccache#.}" + dostrip -x "${ccache#.}" + done < <(cd "${ED}" || die; \ + find . \ + -name '*.go' \ + -path "*/usr/$(get_libdir)/guile/*/site-ccache/*" \ + -print0 || die) || die +} + +# @FUNCTION: guile_export +# @USAGE: [GUILE|GUILD|GUILE_SITECCACHEDIR|GUILE_SITEDIR]... +# @DESCRIPTION: +# Exports a given variable for the selected Guile variant. +# +# Supported variables are: +# +# - GUILE - Path to the guile executable, +# - GUILD - Path to the guild executable, +# - GUILESNARF - Path to the guile-snarf executable +# - GUILECONFIG - Path to the guile-config executable +# - GUILE_SITECCACHEDIR - Path to the site-ccache directory, +# - GUILE_SITEDIR - Path to the site Scheme directory +guile_export() { + debug-print-function ${FUNCNAME} "${@}" + + local gver + if [[ "${GUILE_CURRENT_VERSION}" ]]; then + gver="${GUILE_CURRENT_VERSION}" + elif [[ "${GUILE_SELECTED_TARGET}" ]]; then + gver="${GUILE_SELECTED_TARGET}" + else + die "Calling guile_export outside of a Guile build context?" + fi + + _guile_pcvar() { + local tip="Did you source /etc/profile after an update?" + $(tc-getPKG_CONFIG) --variable="$1" guile-"${gver}" \ + || die "Could not get $1 out of guile-${gver}. ${tip}" + } + + for var; do + case "${var}" in + GUILE) export GUILE="$(_guile_pcvar guile)" ;; + GUILD) export GUILD="$(_guile_pcvar guild)" ;; + GUILESNARF) + GUILESNARF="${EPREFIX}/usr/bin/guile-snarf-${gver}" + export GUILESNARF + ;; + GUILECONFIG) + GUILECONFIG="${EPREFIX}/usr/bin/guile-config-${gver}" + export GUILECONFIG + ;; + GUILE_SITECCACHEDIR) + GUILE_SITECCACHEDIR="$(_guile_pcvar siteccachedir)" + export GUILE_SITECCACHEDIR + ;; + GUILE_SITEDIR) + export GUILE_SITEDIR="$(_guile_pcvar sitedir)" + ;; + *) die "Unknown variable '${var}'" ;; + esac + done +} + +# @FUNCTION: guile_create_temporary_config +# @USAGE: +# @DESCRIPTION: +# Creates a guile-config executable for a given Guile version, and +# inserts it into path. +guile_create_temporary_config() { + debug-print-function ${FUNCNAME} "${@}" + + [[ ${1} ]] || die "Must specify a Guile version" + + local cdir="${T}/guiles/${1}/" + mkdir -p "${cdir}" || die + + pushd "${cdir}" >/dev/null 2>&1 || die + cat >guile-config <<-EOF + #!/bin/sh + exec guile-config-${1} "\${@}" + EOF + chmod +x guile-config + popd >/dev/null 2>&1 || die + PATH="${cdir}:${PATH}" +} + +# @FUNCTION: guile_bump_sources +# @DESCRIPTION: +# Searches over ${S} for .scm files and bumps them to avoid Guile using +# the system ccache while trying to build packages. +# +# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=38112 +guile_bump_sources() { + debug-print-function ${FUNCNAME} "${@}" + + einfo "bumping *.scm source files..." + find "${S}" -name "*.scm" -exec touch {} + || die +} + +fi # _GUILE_UTILS_ECLASS -- 2.45.2