summaryrefslogtreecommitdiff
path: root/eclass/guile-single.eclass
diff options
context:
space:
mode:
Diffstat (limited to 'eclass/guile-single.eclass')
-rw-r--r--eclass/guile-single.eclass245
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