public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
From: "Arsen Arsenović" <arsen@gentoo.org>
To: gentoo-dev@lists.gentoo.org
Cc: "Arsen Arsenović" <arsen@gentoo.org>
Subject: [gentoo-dev] [RFC HELP WANTED 3/9] guile.eclass: new eclass, for guile multi-impl packages
Date: Mon, 12 Aug 2024 00:22:48 +0200	[thread overview]
Message-ID: <20240811231742.942813-4-arsen@gentoo.org> (raw)
In-Reply-To: <20240811231742.942813-1-arsen@gentoo.org>

Bug: https://bugs.gentoo.org/689408
Signed-off-by: Arsen Arsenović <arsen@gentoo.org>
---
 eclass/guile.eclass | 358 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 358 insertions(+)
 create mode 100644 eclass/guile.eclass

diff --git a/eclass/guile.eclass b/eclass/guile.eclass
new file mode 100644
index 000000000000..0e222d289274
--- /dev/null
+++ b/eclass/guile.eclass
@@ -0,0 +1,358 @@
+# Copyright 2023-2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: guile.eclass
+# @PROVIDES: guile-utils
+# @MAINTAINER:
+# Gentoo Scheme project <scheme@gentoo.org>
+# @AUTHOR:
+# Author: Arsen Arsenović <arsen@gentoo.org>
+# Inspired by prior work in the Gentoo Python ecosystem.
+# @SUPPORTED_EAPIS: 8
+# @BLURB: Utilities for packages multi-implementation Guile packages.
+# @DESCRIPTION:
+# This eclass facilitates building against many Guile implementations,
+# useful for Guile libraries.  Each ebuild must set GUILE_COMPAT to a
+# list of versions they support, which will be intersected with
+# GUILE_TARGETS to pick which versions to install.  The eclass will
+# generate a GUILE_DEPS based on the configured GUILE_COMPAT, as well as
+# a GUILE_REQUIRED_USE, that the user must use.
+#
+# If the user of the eclass needs some USE flag on Guile itself, they
+# should provide it via GUILE_REQ_USE.
+#
+# This ebuild provides multibuild functionality.  Use guile_foreach_impl
+# to run a given command for each enabled Guile version.  The command
+# provided will be ran in a modified environment, see the description of
+# that function for more details.
+#
+# This package provides some stage functions written assuming a
+# conventional GNU Build System-based Guile library and may or may not
+# work.
+#
+# For each Guile target, a Guile library should have at least compiled
+# .go files in the ccache or %site-ccache-dir.  It must also have
+# corresponding sources installed in %site-dir.
+#
+# If your package has some steps that should only happen for one
+# implementation (e.g. installing a program), you can utilize
+# guile_for_best_impl.
+#
+# Due to http://debbugs.gnu.org/cgi/bugreport.cgi?bug=38112, Guile
+# packages ought to bump their sources before building.  To this end,
+# the src_prepare this eclass provides will call guile_bump_sources of
+# the guile-utils eclass.
+#
+# When installing, the packages using this eclass ought to use
+# guile_foreach_impl and its SLOTTED_{,E}D, followed by merging roots
+# via guile_merge_roots and unstripping ccache objects via
+# guile_unstrip_ccache.  See descriptions of those functions for
+# details.
+#
+# Ebuild authors, please pay attention for potential conflicts between
+# slots.  As an example, dev-scheme/guile-lib installs a pkg-config file
+# that depends on the Guile version it is installed for.  This is not
+# acceptable, as it means revdeps will only ever see the version of the
+# file for the best Guile implementation in GUILE_TARGETS.
+#
+# @EXAMPLE:
+# The following example demonstrates a simple package relying entirely
+# on the setup of this eclass.  For each enabled, compatible target, the
+# ebuild will bump sources (see description), and run the default
+# configure, compile and test stages (per PMS, meaning GNU Build
+# System), and an install stage modified such that it installs each
+# variant into SLOTTED_D followed by merging roots and unstripping.
+#
+# @CODE
+# EAPI=8
+#
+# GUILE_COMPAT=( 2-2 3-0 )
+# inherit guile
+#
+# DESCRIPTION="iCalendar/vCard parser for GNU Guile"
+# HOMEPAGE="https://github.com/artyom-poptsov/guile-ics"
+# SRC_URI="https://github.com/artyom-poptsov/${PN}/releases/download/v${PV}/${P}.tar.gz"
+#
+# LICENSE="GPL-3+"
+# SLOT="0"
+# KEYWORDS="~amd64"
+# REQUIRED_USE="${GUILE_REQUIRED_USE}"
+#
+# RDEPEND="
+# 	${GUILE_DEPS}
+# 	dev-scheme/guile-smc[${GUILE_USEDEP}]
+# "
+# DEPEND="${RDEPEND}"
+# @CODE
+
+case "${EAPI}" in
+	8) ;;
+	*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+if [[ ! "${_GUILE_ECLASS}" ]]; then
+_GUILE_ECLASS=1
+
+inherit guile-utils multibuild
+
+# @ECLASS_VARIABLE: GUILE_USEDEP
+# @OUTPUT_VARIABLE
+# @DESCRIPTION:
+# USE dependency string that can be applied to Guile
+# multi-implementation dependencies.
+#
+# @EXAMPLE:
+# RDEPEND="
+# 	${GUILE_DEPS}
+# 	dev-scheme/bytestructures[${GUILE_USEDEP}]
+# 	>=dev-libs/libgit2-1:=
+# "
+# DEPEND="${RDEPEND}"
+
+# @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} "${@}"
+
+	guile_generate_depstrings guile_targets '||'
+}
+
+_guile_setup
+unset -f _guile_setup
+
+# @ECLASS_VARIABLE: GUILE_SELECTED_TARGETS
+# @INTERNAL
+# @DESCRIPTION:
+# Contains the intersection of GUILE_TARGETS and GUILE_COMPAT.
+# Generated in guile_pkg_setup.
+
+# @FUNCTION: guile_pkg_setup
+# @DESCRIPTION:
+# Sets up eclass-internal variables for this build.
+guile_pkg_setup() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	guile_set_common_vars
+	GUILE_SELECTED_TARGETS=()
+	for ver in "${GUILE_COMPAT[@]}"; do
+		debug-print "${FUNCNAME}: checking for ${ver}"
+		use "guile_targets_${ver}" || continue
+		GUILE_SELECTED_TARGETS+=("${ver/-/.}")
+	done
+	if [[ "${#GUILE_SELECTED_TARGETS[@]}" -eq 0 ]]; then
+		die "No GUILE_TARGETS specified."
+	fi
+}
+
+# @FUNCTION: guile_copy_sources
+# @DESCRIPTION:
+# Create a single copy of the package sources for each selected Guile
+# implementation.
+guile_copy_sources() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local MULTIBUILD_VARIANTS
+	MULTIBUILD_VARIANTS=("${GUILE_SELECTED_TARGETS[@]}")
+
+	multibuild_copy_sources
+}
+
+# @FUNCTION: _guile_multibuild_wrapper
+# @USAGE: <command> [<argv>...]
+# @INTERNAL
+# @DESCRIPTION:
+# Initialize the environment for a single build variant.  See
+# guile_foreach_impl.
+_guile_multibuild_wrapper() {
+	local GUILE_CURRENT_VERSION="${MULTIBUILD_VARIANT}"
+	debug-print-function ${FUNCNAME} "${@}" "on ${MULTIBUILD_VARIANT}"
+
+	local -x PATH="${PATH}"
+	guile_create_temporary_config "${GUILE_CURRENT_VERSION}"
+	guile_export GUILE GUILD GUILESNARF
+
+	local -x PKG_CONFIG_PATH="${PKG_CONFIG_PATH}"
+	guile_filter_pkgconfig_path "${MULTIBUILD_VARIANT}"
+	local ECONF_SOURCE="${S}"
+	local -x SLOTTED_D="${T}/dests/image${MULTIBUILD_ID}/"
+	local -x SLOTTED_ED="${SLOTTED_D%/}${EPREFIX}/"
+	local -x GUILE_EFFECTIVE_VERSION="${GUILE_CURRENT_VERSION}"
+	mkdir -p "${BUILD_DIR}" || die
+	cd "${BUILD_DIR}" || die
+	"$@"
+}
+
+# @VARIABLE: SLOTTED_D
+# @DESCRIPTION:
+# In functions ran by guile_foreach_impl, this variable is set to a new
+# ${D} value that the variant being installed should use.
+
+# @VARIABLE: SLOTTED_ED
+# @DESCRIPTION:
+# In functions ran by guile_foreach_impl, this variable is set to a new
+# ${ED} value that the variant being installed should use.  It is
+# equivalent to "${SLOTTED_D%/}${EPREFIX}/".
+
+# @VARIABLE: ECONF_SOURCE
+# @DESCRIPTION:
+# In functions ran by guile_foreach_impl, this variable is set to ${S},
+# for convenience.
+
+# @VARIABLE: PKG_CONFIG_PATH
+# @DESCRIPTION:
+# In functions ran by guile_foreach_impl, PKG_CONFIG_PATH is filtered to
+# contain only the current ${MULTIBUILD_VARIANT}.
+
+# @VARIABLE: BUILD_DIR
+# @DESCRIPTION:
+# In functions ran by guile_foreach_impl, this variable is set to a
+# newly-generated build directory for this variant.
+
+# @FUNCTION: guile_foreach_impl
+# @USAGE: <command> [<argv>...]
+# @DESCRIPTION:
+# Runs the given command for each of the selected Guile implementations.
+#
+# The function will return 0 status if all invocations succeed.
+# Otherwise, the return code from first failing invocation will
+# be returned.
+#
+# Each invocation will have PKG_CONFIG_DIR altered to contain only one
+# Guile implementation, as well as a SLOTTED_D, SLOTTED_ED for
+# installation purposes, and a new BUILD_DIR, in which the wrapped
+# function will be executed, with a pre-configured ECONF_SOURCE.  A
+# temporary program called 'guile-config' is generated and inserted into
+# the PATH.
+#
+# Also automatically exported are GUILE, GUILD, and GUILESNARF - see
+# guile_export for details - as well as GUILE_CURRENT_VERSION and
+# GUILE_EFFECTIVE_VERSION, which are set to the same value (the current
+# version).
+#
+# This combination should cover Guile detection of a large amount of
+# packages out of the box.
+guile_foreach_impl() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local MULTIBUILD_VARIANTS
+	MULTIBUILD_VARIANTS=("${GUILE_SELECTED_TARGETS[@]}")
+
+	debug-print "${FUNCNAME}: Running for each of:" \
+				"${GUILE_SELECTED_TARGETS[@]}"
+
+	multibuild_foreach_variant _guile_multibuild_wrapper "${@}"
+}
+
+# @FUNCTION: _guile_merge_single_root
+# @INTERNAL
+# @DESCRIPTION:
+# Runs a single merge_root step for guile_merge_roots.
+_guile_merge_single_root() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	multibuild_merge_root "${SLOTTED_D}" "${D}"
+}
+
+# @FUNCTION: guile_merge_roots
+# @DESCRIPTION:
+# Merges install roots from all slots, diagnosing conflicts.
+guile_merge_roots() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	guile_foreach_impl _guile_merge_single_root
+}
+
+# @FUNCTION: guile_for_best_impl
+# @DESCRIPTION:
+# Runs the passed command once, for the best installed Guile
+# implementation.
+guile_for_best_impl() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	multibuild_for_best_variant _guile_multibuild_wrapper "${@}"
+}
+
+# Default implementations for a GNU Build System based Guile package.
+
+# @FUNCTION: guile_src_prepare
+# @DESCRIPTION:
+# Bumps SCM sources runs the default src_prepare and bumps all *.scm
+# files.  See guile_bump_sources of guile-utils.eclass.
+guile_src_prepare() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	default
+	guile_bump_sources
+}
+
+# @FUNCTION: guile_src_configure
+# @DESCRIPTION:
+# Runs the default src_configure for each selected variant target.
+guile_src_configure() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	guile_foreach_impl default
+}
+
+# @FUNCTION: guile_src_compile
+# @DESCRIPTION:
+# Runs the default src_compile for each selected variant target.
+guile_src_compile() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	guile_foreach_impl default
+}
+
+# @FUNCTION: guile_src_test
+# @DESCRIPTION:
+# Runs the default src_test phase for each implementation.
+guile_src_test() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	guile_foreach_impl default
+}
+
+# @FUNCTION: _guile_default_install_slot
+# @INTERNAL
+# @DESCRIPTION:
+# Imitates the default build system install "substep", but for a given
+# ${SLOTTED_D} rather than the usual ${D}.  See guile_src_install.
+_guile_default_install_slot() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	if [[ -f Makefile ]] || [[ -f GNUmakefile ]] || [[ -f makefile ]]; then
+		emake DESTDIR="${SLOTTED_D}" install
+	fi
+}
+
+# @FUNCTION: guile_src_install
+# @DESCRIPTION:
+# Runs the an imitation of the src_install that does the right thing for
+# a GNU Build System based Guile package, for each selected variant
+# target.  Merges roots after completing the installs.
+guile_src_install() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	guile_foreach_impl _guile_default_install_slot
+	guile_merge_roots
+	guile_unstrip_ccache
+
+	einstalldocs
+}
+
+EXPORT_FUNCTIONS pkg_setup src_prepare src_configure src_compile \
+				 src_install src_test
+
+fi  # _GUILE_ECLASS
-- 
2.45.2



  parent reply	other threads:[~2024-08-11 23:19 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-08-11 22:22 [gentoo-dev] [RFC HELP WANTED 0/9] Mending the Guile ecosystem Arsen Arsenović
2024-08-11 22:22 ` [gentoo-dev] [RFC HELP WANTED 1/9] guile-utils.eclass: new eclass, common code for guile packages Arsen Arsenović
2024-08-11 22:22 ` [gentoo-dev] [RFC HELP WANTED 2/9] guile-single.eclass: new eclass, for single-impl " Arsen Arsenović
2024-08-11 22:22 ` Arsen Arsenović [this message]
2024-08-11 22:22 ` [gentoo-dev] [RFC HELP WANTED 4/9] profiles/base: add guile _TARGETS USE_EXPAND variables Arsen Arsenović
2024-08-11 22:22 ` [gentoo-dev] [RFC HELP WANTED 5/9] dev-build/make: switch to new guile mechanism Arsen Arsenović
2024-08-11 22:22 ` [gentoo-dev] [RFC HELP WANTED 6/9] dev-scheme/guile-reader: port to new guile eclasses Arsen Arsenović
2024-08-11 22:22 ` [gentoo-dev] [RFC HELP WANTED 7/9] dev-scheme/guile-commonmark: new package, add 0.1.2_pre20240803 Arsen Arsenović
2024-08-11 22:22 ` [gentoo-dev] [RFC HELP WANTED 8/9] www-apps/haunt: new package, add 0.3.0 Arsen Arsenović
2024-08-11 22:22 ` [gentoo-dev] [RFC HELP WANTED 9/9] dev-scheme/slib: add 3c1, port to new guile eclasses Arsen Arsenović
2024-08-18  9:29 ` [gentoo-dev] [RFC HELP WANTED 0/9] Mending the Guile ecosystem Sam James

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=20240811231742.942813-4-arsen@gentoo.org \
    --to=arsen@gentoo.org \
    --cc=gentoo-dev@lists.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