diff options
Diffstat (limited to 'eclass/guile-single.eclass')
-rw-r--r-- | eclass/guile-single.eclass | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/eclass/guile-single.eclass b/eclass/guile-single.eclass new file mode 100644 index 000000000000..3498044b6d76 --- /dev/null +++ b/eclass/guile-single.eclass @@ -0,0 +1,245 @@ +# Copyright 2024 Gentoo Authors +# Distributed under the terms of the GNU General Public License v2 + +# @ECLASS: guile-single.eclass +# @MAINTAINER: +# Gentoo Scheme project <scheme@gentoo.org> +# @AUTHOR: +# Author: Arsen Arsenović <arsen@gentoo.org> +# @SUPPORTED_EAPIS: 8 +# @PROVIDES: guile-utils +# @BLURB: Utilities for packages that build against a single Guile. +# @DESCRIPTION: +# This eclass facilitates packages building against a single slot of +# Guile, which is normally something that uses Guile for extending, like +# GNU Make, or for programs built in Guile, like Haunt. +# +# Inspired by prior work in the Gentoo Python ecosystem. +# +# These packages should use guile_gen_cond_dep to generate a dependency +# string for their Guile package dependencies (i.e. other Guile single- +# and multi-implementation packages). They should also utilize +# GUILE_DEPS and GUILE_REQUIRED_USE to specify a dependency on their +# Guile versions. +# +# They should also bump sources via guile_bump_sources during +# src_prepare, and unstrip ccache via guile_unstrip_ccache during +# src_install. +# +# If the user of the eclass needs some USE flag on Guile itself, they +# should provide it via GUILE_REQ_USE. +# +# This eclass provides a guile-single_pkg_setup that sets up environment +# variables needed for Guile and build systems using it. See the +# documentation for that function for more details. +# +# @EXAMPLE: +# A Guile program: +# +# @CODE +# # Copyright 2024 Gentoo Authors +# # Distributed under the terms of the GNU General Public License v2 +# +# EAPI=8 +# +# GUILE_COMPAT=( 2-2 3-0 ) +# inherit guile-single +# +# DESCRIPTION="Haunt is a simple, functional, hackable static site generator" +# HOMEPAGE="https://dthompson.us/projects/haunt.html" +# SRC_URI="https://files.dthompson.us/releases/${PN}/${P}.tar.gz" +# +# LICENSE="GPL-3+" +# SLOT="0" +# KEYWORDS="~amd64" +# REQUIRED_USE="${GUILE_REQUIRED_USE}" +# +# RDEPEND=" +# ${GUILE_DEPS} +# $(guile_gen_cond_dep ' +# dev-scheme/guile-reader[${GUILE_MULTI_USEDEP}] +# dev-scheme/guile-commonmark[${GUILE_MULTI_USEDEP}] +# ') +# " +# DEPEND="${RDEPEND}" +# @CODE +# +# A program utilizing Guile for extension (GNU make, irrelevant pieces +# elided): +# @CODE +# GUILE_COMPAT=( 1-8 2-0 2-2 3-0 ) +# inherit flag-o-matic unpacker verify-sig guile-single +# # ... +# REQUIRED_USE="guile? ( ${GUILE_REQUIRED_USE} )" +# DEPEND=" +# guile? ( ${GUILE_DEPS} ) +# " +# +# src_prepare() { +# # ... +# if use guile; then +# guile-single_src_prepare +# fi +# } +# +# pkg_setup() { +# if use guile; then +# guile-single_pkg_setup +# fi +# } +# +# src_configure() { +# # ... +# local myeconfargs=( +# $(use_with guile) +# ) +# econf "${myeconfargs[@]}" +# } +# +# src_install() { +# # ... +# if use guile; then +# guile_unstrip_ccache +# fi +# } +# @CODE + +case "${EAPI}" in + 8) ;; + *) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;; +esac + +if [[ ! "${_GUILE_SINGLE_ECLASS}" ]]; then +_GUILE_SINGLE_ECLASS=1 + +inherit guile-utils + +# @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. + +_guile_setup() { + debug-print-function ${FUNCNAME} "$@" + + # Inhibit generating the GUILE_USEDEP. This variable is not usable + # for single packages. + local GUILE_USEDEP + guile_generate_depstrings guile_single_target ^^ +} + +_guile_setup +unset -f _guile_setup + +# @FUNCTION: guile_gen_cond_dep +# @USAGE: <dependency> [<pattern>...] +# @DESCRIPTION: +# Takes a string that uses (quoted) ${GUILE_SINGLE_USEDEP} and +# ${GUILE_MULTI_USEDEP} markers as placeholders for the correct USE +# dependency strings for each compatible slot. +# +# If the pattern is provided, it is taken to be list of slots to +# generate the dependency string for, otherwise, ${GUILE_COMPAT[@]} is +# taken. +# +# @EXAMPLE: +# Note that the "inner" dependency string is in single quotes! +# @CODE +# RDEPEND=" +# $(guile_gen_cond_dep ' +# dev-scheme/guile-zstd[${GUILE_MULTI_USEDEP}] +# dev-scheme/guile-config[${GUILE_SINGLE_USEDEP}] +# ') +# " +# @CODE +guile_gen_cond_dep() { + debug-print-function ${FUNCNAME} "$@" + + local deps="$1" + shift + + local candidates=( "$@" ) + if [[ ${#candidates[@]} -eq 0 ]]; then + candidates=( "${GUILE_COMPAT[@]}" ) + fi + + local candidate + for candidate in "${candidates[@]}"; do + local s="guile_single_target_${candidate}(-)" \ + m="guile_targets_${candidate}(-)" \ + subdeps=${deps//\$\{GUILE_SINGLE_USEDEP\}/${s}} + subdeps=${subdeps//\$\{GUILE_MULTI_USEDEP\}/${m}} + echo " + guile_single_target_${candidate}? ( + ${subdeps} + ) + " + done +} + +# @FUNCTION: guile-single_pkg_setup +# @DESCRIPTION: +# Sets up the PKG_CONFIG_PATH with the appropriate GUILE_SINGLE_TARGET, +# as well as setting up a guile-config and the GUILE, GUILD and +# GUILESNARF environment variables. Also sets GUILE_EFFECTIVE_VERSION +# to the same value as GUILE_SELECTED_TARGET, as build systems sometimes +# check that variable. +# +# For details on the latter three, see guile_export. +guile-single_pkg_setup() { + debug-print-function ${FUNCNAME} "$@" + + guile_set_common_vars + + GUILE_SELECTED_TARGET= + for ver in "${GUILE_COMPAT[@]}"; do + debug-print "${FUNCNAME}: checking for ${ver}" + use "guile_single_target_${ver}" || continue + GUILE_SELECTED_TARGET="${ver/-/.}" + break + done + + [[ ${GUILE_SELECTED_TARGET} ]] \ + || die "No GUILE_SINGLE_TARGET specified." + + export PKG_CONFIG_PATH + guile_filter_pkgconfig_path "${GUILE_SELECTED_TARGET}" + guile_create_temporary_config "${GUILE_SELECTED_TARGET}" + local -x GUILE_EFFECTIVE_VERSION="${GUILE_SELECTED_TARGET}" + guile_export GUILE GUILD GUILESNARF +} + +# @FUNCTION: guile-single_src_prepare +# @DESCRIPTION: +# Runs the default prepare stage, and then bumps Guile sources via +# guile_bump_sources. +guile-single_src_prepare() { + debug-print-function ${FUNCNAME} "$@" + + default + guile_bump_sources +} + +# @FUNCTION: guile-single_src_install +# @DESCRIPTION: +# Runs the default install stage, and then marks ccache files not to be +# stripped using guile_unstrip_ccache. +guile-single_src_install() { + debug-print-function ${FUNCNAME} "$@" + + default + guile_unstrip_ccache +} + +fi # _GUILE_SINGLE_ECLASS + +EXPORT_FUNCTIONS pkg_setup src_prepare src_install |