public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-dev] [PATCH 0/2] Introduce rebar3.eclass
@ 2024-07-16  9:35 Florian Schmaus
  2024-07-16  9:35 ` [gentoo-dev] [PATCH 1/2] rebar.eclass: factor out common functions into rebar-utils.eclass Florian Schmaus
  2024-07-16  9:35 ` [gentoo-dev] [PATCH 2/2] rebar3.eclass: add new eclass Florian Schmaus
  0 siblings, 2 replies; 3+ messages in thread
From: Florian Schmaus @ 2024-07-16  9:35 UTC (permalink / raw
  To: gentoo-dev; +Cc: Anna Vyalkova, Matthew Smith, Florian Schmaus

[This patchset was initially send with the wrong 'from' address to gentoo-dev@ and therefore never arrived at this mailing list]

The Erlang/OTP ecosystem, or at least parts of it, are moving away
from Rebar2 and towards Rebar3. While Rebar3 is packaged in Gentoo as
dev-util/rebar:3, the current rebar.eclass only supports building
projects with Rebar2.

This is becoming more and more of a problem.

For example, Ejabberd upstream is so kind to support building with
Rebar2 and Rebar3. However, I've been told by upstream that sooner or
later, probably sooner rather than later, support for Rebar2 will be
dropped.

We should prepare for this future and support Rebar3 via an eclass.

Fortunately, ::guru already has a rebar3.eclass, which was used as
starting point for this patchset. Not much needed to be changed, and
tests in an overlay showed that, for example, ejabberd could be simply
build by swapping rebar.eclass with rebar3.eclass (no further changes
where necessary).

I briefly considered adding support for Rebar3 to rebar.eclass,
however, after examining the eclass' code and considering the
consequences of doing so, I concluded that a new rebar3.eclass is the
best approach.

Florian Schmaus (2):
  rebar.eclass: factor out common functions into rebar-utils.eclass
  rebar3.eclass: add new eclass

 eclass/rebar-utils.eclass | 154 ++++++++++++++++++++++++++++
 eclass/rebar.eclass       |  99 +-----------------
 eclass/rebar3.eclass      | 204 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 361 insertions(+), 96 deletions(-)
 create mode 100644 eclass/rebar-utils.eclass
 create mode 100644 eclass/rebar3.eclass

-- 
2.44.2



^ permalink raw reply	[flat|nested] 3+ messages in thread

* [gentoo-dev] [PATCH 1/2] rebar.eclass: factor out common functions into rebar-utils.eclass
  2024-07-16  9:35 [gentoo-dev] [PATCH 0/2] Introduce rebar3.eclass Florian Schmaus
@ 2024-07-16  9:35 ` Florian Schmaus
  2024-07-16  9:35 ` [gentoo-dev] [PATCH 2/2] rebar3.eclass: add new eclass Florian Schmaus
  1 sibling, 0 replies; 3+ messages in thread
From: Florian Schmaus @ 2024-07-16  9:35 UTC (permalink / raw
  To: gentoo-dev; +Cc: Anna Vyalkova, Matthew Smith, Florian Schmaus

In preperation for rebar3.eclass, factor out common functions into rebar-utils.eclass.

Signed-off-by: Florian Schmaus <flow@gentoo.org>
---
 eclass/rebar-utils.eclass | 160 ++++++++++++++++++++++++++++++++++++++
 eclass/rebar.eclass       | 112 +-------------------------
 2 files changed, 163 insertions(+), 109 deletions(-)
 create mode 100644 eclass/rebar-utils.eclass

diff --git a/eclass/rebar-utils.eclass b/eclass/rebar-utils.eclass
new file mode 100644
index 000000000000..5657908eb8e9
--- /dev/null
+++ b/eclass/rebar-utils.eclass
@@ -0,0 +1,160 @@
+# Copyright 1999-2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: rebar-utils.eclass
+# @MAINTAINER:
+# Florian Schmaus <flow@gentoo.org>
+# @AUTHOR:
+# Amadeusz Żołnowski <aidecoe@gentoo.org>
+# @SUPPORTED_EAPIS: 7 8
+# @BLURB: Auxiliary functions for using dev-util/rebar.
+# @DESCRIPTION:
+# This eclass provides a set of axiliary functions commonly needed
+# when building Erlang/OTP packages with rebar.
+
+case ${EAPI} in
+	7|8) ;;
+	*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+if [[ -z ${_REBAR_UTILS_ECLASS} ]]; then
+_REBAR_UTILS_ECLASS=1
+
+# @ECLASS_VARIABLE: REBAR_APP_SRC
+# @DESCRIPTION:
+# Relative path to .app.src description file. Defaults to
+# 'src/${PN}.app.src'.
+: "${REBAR_APP_SRC:=src/${PN}.app.src}"
+
+# @FUNCTION: get_erl_libs
+# @RETURN: the path to Erlang lib directory
+# @DESCRIPTION:
+# Get the full path without EPREFIX to Erlang lib directory.
+get_erl_libs() {
+	echo "/usr/$(get_libdir)/erlang/lib"
+}
+
+# @FUNCTION: _rebar_find_dep
+# @INTERNAL
+# @USAGE: <project_name>
+# @RETURN: 0 success, 1 dependency not found, 2 multiple versions found
+# @DESCRIPTION:
+# Find a Erlang package/project by name in Erlang lib directory. Project
+# directory is usually suffixed with version. It is matched to '<project_name>'
+# or '<project_name>-*'.
+_rebar_find_dep() {
+	local pn="${1}"
+	local p
+	local result
+
+	pushd "${EPREFIX}$(get_erl_libs)" >/dev/null || return 1
+	for p in ${pn} ${pn}-*; do
+		if [[ -d ${p} ]]; then
+			# Ensure there's at most one matching.
+			[[ ${result} ]] && return 2
+			result="${p}"
+		fi
+	done
+	popd >/dev/null || die
+
+	[[ ${result} ]] || return 1
+	echo "${result}"
+}
+
+# @FUNCTION: rebar_disable_coverage
+# @USAGE: [<rebar_config>]
+# @DESCRIPTION:
+# Disable coverage in rebar.config. This is a workaround for failing coverage.
+# Coverage is not relevant in this context, so there's no harm to disable it,
+# although the issue should be fixed.
+rebar_disable_coverage() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local rebar_config="${1:-rebar.config}"
+
+	sed -e 's/{cover_enabled, true}/{cover_enabled, false}/' \
+		-i "${rebar_config}" \
+		|| die "failed to disable coverage in ${rebar_config}"
+}
+
+# @FUNCTION: rebar_fix_include_path
+# @USAGE: <project_name> [<rebar_config>]
+# @DESCRIPTION:
+# Fix path in rebar.config to 'include' directory of dependent project/package,
+# so it points to installation in system Erlang lib rather than relative 'deps'
+# directory.
+#
+# <rebar_config> is optional. Default is 'rebar.config'.
+#
+# The function dies on failure.
+rebar_fix_include_path() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local pn="${1}"
+	local rebar_config="${2:-rebar.config}"
+	local erl_libs="${EPREFIX}$(get_erl_libs)"
+	local p
+
+	p="$(_rebar_find_dep "${pn}")" \
+		|| die "failed to unambiguously resolve dependency of '${pn}'"
+
+	gawk -i inplace \
+		-v erl_libs="${erl_libs}" -v pn="${pn}" -v p="${p}" '
+/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
+	pattern = "\"(./)?deps/" pn "/include\"";
+	if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
+		sub(pattern, "\"" erl_libs "/" p "/include\"");
+	}
+	print $0;
+	next;
+}
+1
+' "${rebar_config}" || die "failed to fix include paths in ${rebar_config} for '${pn}'"
+}
+
+# @FUNCTION: rebar_remove_deps
+# @USAGE: [<rebar_config>]
+# @DESCRIPTION:
+# Remove dependencies list from rebar.config and deceive build rules that any
+# dependencies are already fetched and built. Otherwise rebar tries to fetch
+# dependencies and compile them.
+#
+# <rebar_config> is optional. Default is 'rebar.config'.
+#
+# The function dies on failure.
+rebar_remove_deps() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local rebar_config="${1:-rebar.config}"
+
+	mkdir -p "${S}/deps" && :>"${S}/deps/.got" && :>"${S}/deps/.built" || die
+	gawk -i inplace '
+/^{[[:space:]]*deps[[:space:]]*,/, /}[[:space:]]*\.$/ {
+	if ($0 ~ /}[[:space:]]*\.$/) {
+		print "{deps, []}.";
+	}
+	next;
+}
+1
+' "${rebar_config}" || die "failed to remove deps from ${rebar_config}"
+}
+
+# @FUNCTION: rebar_set_vsn
+# @USAGE: [<version>]
+# @DESCRIPTION:
+# Set version in project description file if it's not set.
+#
+# <version> is optional. Default is PV stripped from version suffix.
+#
+# The function dies on failure.
+rebar_set_vsn() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local version="${1:-${PV%_*}}"
+
+	sed -e "s/vsn, git/vsn, \"${version}\"/" \
+		-i "${S}/${REBAR_APP_SRC}" \
+		|| die "failed to set version in src/${PN}.app.src"
+}
+
+fi
diff --git a/eclass/rebar.eclass b/eclass/rebar.eclass
index 97638c761814..1e4e845a9adb 100644
--- a/eclass/rebar.eclass
+++ b/eclass/rebar.eclass
@@ -7,6 +7,7 @@
 # @AUTHOR:
 # Amadeusz Żołnowski <aidecoe@gentoo.org>
 # @SUPPORTED_EAPIS: 7 8
+# @PROVIDES: rebar-utils
 # @BLURB: Build Erlang/OTP projects using dev-util/rebar.
 # @DESCRIPTION:
 # An eclass providing functions to build Erlang/OTP projects using
@@ -27,6 +28,8 @@ esac
 if [[ -z ${_REBAR_ECLASS} ]]; then
 _REBAR_ECLASS=1
 
+inherit rebar-utils
+
 RDEPEND="dev-lang/erlang:="
 DEPEND="${RDEPEND}"
 BDEPEND="
@@ -34,19 +37,6 @@ BDEPEND="
 	>=sys-apps/gawk-4.1
 "
 
-# @ECLASS_VARIABLE: REBAR_APP_SRC
-# @DESCRIPTION:
-# Relative path to .app.src description file.
-REBAR_APP_SRC="${REBAR_APP_SRC-src/${PN}.app.src}"
-
-# @FUNCTION: get_erl_libs
-# @RETURN: the path to Erlang lib directory
-# @DESCRIPTION:
-# Get the full path without EPREFIX to Erlang lib directory.
-get_erl_libs() {
-	echo "/usr/$(get_libdir)/erlang/lib"
-}
-
 # @FUNCTION: _rebar_find_dep
 # @INTERNAL
 # @USAGE: <project_name>
@@ -74,22 +64,6 @@ _rebar_find_dep() {
 	echo "${result}"
 }
 
-# @FUNCTION: rebar_disable_coverage
-# @USAGE: [<rebar_config>]
-# @DESCRIPTION:
-# Disable coverage in rebar.config. This is a workaround for failing coverage.
-# Coverage is not relevant in this context, so there's no harm to disable it,
-# although the issue should be fixed.
-rebar_disable_coverage() {
-	debug-print-function ${FUNCNAME} "${@}"
-
-	local rebar_config="${1:-rebar.config}"
-
-	sed -e 's/{cover_enabled, true}/{cover_enabled, false}/' \
-		-i "${rebar_config}" \
-		|| die "failed to disable coverage in ${rebar_config}"
-}
-
 # @FUNCTION: erebar
 # @USAGE: <targets>
 # @DESCRIPTION:
@@ -105,86 +79,6 @@ erebar() {
 	rebar -v skip_deps=true "$@" || die -n "rebar $@ failed"
 }
 
-# @FUNCTION: rebar_fix_include_path
-# @USAGE: <project_name> [<rebar_config>]
-# @DESCRIPTION:
-# Fix path in rebar.config to 'include' directory of dependent project/package,
-# so it points to installation in system Erlang lib rather than relative 'deps'
-# directory.
-#
-# <rebar_config> is optional. Default is 'rebar.config'.
-#
-# The function dies on failure.
-rebar_fix_include_path() {
-	debug-print-function ${FUNCNAME} "${@}"
-
-	local pn="${1}"
-	local rebar_config="${2:-rebar.config}"
-	local erl_libs="${EPREFIX}$(get_erl_libs)"
-	local p
-
-	p="$(_rebar_find_dep "${pn}")" \
-		|| die "failed to unambiguously resolve dependency of '${pn}'"
-
-	gawk -i inplace \
-		-v erl_libs="${erl_libs}" -v pn="${pn}" -v p="${p}" '
-/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
-	pattern = "\"(./)?deps/" pn "/include\"";
-	if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
-		sub(pattern, "\"" erl_libs "/" p "/include\"");
-	}
-	print $0;
-	next;
-}
-1
-' "${rebar_config}" || die "failed to fix include paths in ${rebar_config} for '${pn}'"
-}
-
-# @FUNCTION: rebar_remove_deps
-# @USAGE: [<rebar_config>]
-# @DESCRIPTION:
-# Remove dependencies list from rebar.config and deceive build rules that any
-# dependencies are already fetched and built. Otherwise rebar tries to fetch
-# dependencies and compile them.
-#
-# <rebar_config> is optional. Default is 'rebar.config'.
-#
-# The function dies on failure.
-rebar_remove_deps() {
-	debug-print-function ${FUNCNAME} "${@}"
-
-	local rebar_config="${1:-rebar.config}"
-
-	mkdir -p "${S}/deps" && :>"${S}/deps/.got" && :>"${S}/deps/.built" || die
-	gawk -i inplace '
-/^{[[:space:]]*deps[[:space:]]*,/, /}[[:space:]]*\.$/ {
-	if ($0 ~ /}[[:space:]]*\.$/) {
-		print "{deps, []}.";
-	}
-	next;
-}
-1
-' "${rebar_config}" || die "failed to remove deps from ${rebar_config}"
-}
-
-# @FUNCTION: rebar_set_vsn
-# @USAGE: [<version>]
-# @DESCRIPTION:
-# Set version in project description file if it's not set.
-#
-# <version> is optional. Default is PV stripped from version suffix.
-#
-# The function dies on failure.
-rebar_set_vsn() {
-	debug-print-function ${FUNCNAME} "${@}"
-
-	local version="${1:-${PV%_*}}"
-
-	sed -e "s/vsn, git/vsn, \"${version}\"/" \
-		-i "${S}/${REBAR_APP_SRC}" \
-		|| die "failed to set version in src/${PN}.app.src"
-}
-
 # @FUNCTION: rebar_src_prepare
 # @DESCRIPTION:
 # Prevent rebar from fetching and compiling dependencies. Set version in
-- 
2.44.2



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [gentoo-dev] [PATCH 2/2] rebar3.eclass: add new eclass
  2024-07-16  9:35 [gentoo-dev] [PATCH 0/2] Introduce rebar3.eclass Florian Schmaus
  2024-07-16  9:35 ` [gentoo-dev] [PATCH 1/2] rebar.eclass: factor out common functions into rebar-utils.eclass Florian Schmaus
@ 2024-07-16  9:35 ` Florian Schmaus
  1 sibling, 0 replies; 3+ messages in thread
From: Florian Schmaus @ 2024-07-16  9:35 UTC (permalink / raw
  To: gentoo-dev; +Cc: Anna Vyalkova, Matthew Smith, Florian Schmaus

Add a new eclass for dev-util/rebar:3, based on the work of Anna
Vyalkova in ::guru (thanks!).

The Erlang/OTP ecosystem is moving to Rebar3. Upstreams start to drop
support for Rebar2, or at least consider it.

Signed-off-by: Florian Schmaus <flow@gentoo.org>
---
 eclass/rebar3.eclass | 194 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 194 insertions(+)
 create mode 100644 eclass/rebar3.eclass

diff --git a/eclass/rebar3.eclass b/eclass/rebar3.eclass
new file mode 100644
index 000000000000..f6383b9c8cdd
--- /dev/null
+++ b/eclass/rebar3.eclass
@@ -0,0 +1,194 @@
+# Copyright 1999-2024 Gentoo Authors
+# Distributed under the terms of the GNU General Public License v2
+
+# @ECLASS: rebar3.eclass
+# @MAINTAINER:
+# Florian Schmaus <flow@gentoo.org>
+# @AUTHOR:
+# Amadeusz Żołnowski <aidecoe@gentoo.org>
+# Anna (cybertailor) Vyalkova <cyber+gentoo@sysrq.in>
+# @SUPPORTED_EAPIS: 8
+# @PROVIDES: rebar-utils
+# @BLURB: Build Erlang/OTP projects using dev-util/rebar:3.
+# @DESCRIPTION:
+# An eclass providing functions to build Erlang/OTP projects using
+# dev-util/rebar:3.
+#
+# rebar is a tool which tries to resolve dependencies itself which is by
+# cloning remote git repositories. Dependent projects are usually expected to
+# be in sub-directory 'deps' rather than looking at system Erlang lib
+# directory. Projects relying on rebar usually don't have 'install' make
+# targets. The eclass workarounds some of these problems. It handles
+# installation in a generic way for Erlang/OTP structured projects.
+
+case ${EAPI} in
+	8) ;;
+	*) die "${ECLASS}: EAPI ${EAPI:-0} not supported" ;;
+esac
+
+if [[ -z ${_REBAR3_ECLASS} ]]; then
+_REBAR3_ECLASS=1
+
+inherit edo rebar-utils
+
+RDEPEND="dev-lang/erlang:="
+DEPEND="${RDEPEND}"
+BDEPEND="
+	dev-util/rebar:3
+	>=sys-apps/gawk-4.1
+"
+
+# @ECLASS_VARIABLE: REBAR_PROFILE
+# @DESCRIPTION:
+# Rebar profile to use. Defaults to
+# 'default'.
+: "${REBAR_PROFILE:=default}"
+
+# @FUNCTION: _rebar_find_dep
+# @INTERNAL
+# @USAGE: <project_name>
+# @RETURN: 0 success, 1 dependency not found, 2 multiple versions found
+# @DESCRIPTION:
+# Find a Erlang package/project by name in Erlang lib directory. Project
+# directory is usually suffixed with version. It is matched to '<project_name>'
+# or '<project_name>-*'.
+_rebar_find_dep() {
+	local pn="${1}"
+	local p
+	local result
+
+	pushd "${EPREFIX}$(get_erl_libs)" >/dev/null || return 1
+	for p in ${pn} ${pn}-*; do
+		if [[ -d ${p} ]]; then
+			# Ensure there's at most one matching.
+			[[ ${result} ]] && return 2
+			result="${p}"
+		fi
+	done
+	popd >/dev/null || die
+
+	[[ ${result} ]] || return 1
+	echo "${result}"
+}
+
+# @FUNCTION: erebar3
+# @USAGE: <targets>
+# @DESCRIPTION:
+# Run rebar with verbose flag. Die on failure.
+erebar3() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	(( $# > 0 )) || die "${FUNCNAME}: at least one target is required"
+
+	case ${1} in
+		eunit|ct)
+			local -x ERL_LIBS="." ;;
+		*)
+			local -x ERL_LIBS="${EPREFIX}$(get_erl_libs)" ;;
+	esac
+
+	local -x HEX_OFFLINE=true
+	edo rebar3 "$@"
+}
+
+# @FUNCTION: rebar3_src_prepare
+# @DESCRIPTION:
+# Prevent rebar3 from fetching and compiling dependencies. Set version in
+# project description file if it's not set.
+#
+# Existence of rebar.config is optional, but file description file must exist
+# at 'src/${PN}.app.src'.
+rebar3_src_prepare() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	default
+	rebar_set_vsn
+
+	if [[ -f rebar.lock ]]; then
+		rm rebar.lock || die
+	fi
+
+	if [[ -f rebar.config ]]; then
+		rebar_disable_coverage
+		rebar_remove_deps
+	fi
+}
+
+# @FUNCTION: rebar3_src_configure
+# @DESCRIPTION:
+# Configure with ERL_LIBS set.
+rebar3_src_configure() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local -x ERL_LIBS="${EPREFIX}$(get_erl_libs)"
+	default
+}
+
+# @FUNCTION: rebar3_src_compile
+# @DESCRIPTION:
+# Compile project with rebar3.
+rebar3_src_compile() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	erebar3 as "${REBAR_PROFILE}" release --all
+}
+
+# @FUNCTION: rebar3_src_test
+# @DESCRIPTION:
+# Run unit tests.
+rebar3_src_test() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	erebar3 eunit -v
+}
+
+# @FUNCTION: rebar3_install_lib
+# @USAGE: <dir>
+# @DESCRIPTION:
+# Install BEAM files, include headers and native libraries.
+#
+# Function expects that project conforms to Erlang/OTP structure.
+rebar3_install_lib() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local dest="$(get_erl_libs)/${P}"
+	insinto "${dest}"
+
+	pushd "${1?}" >/dev/null || die
+	for dir in ebin include priv; do
+		if [[ -d ${dir} && ! -L ${dir} ]]; then
+			doins -r "${dir}"
+		fi
+	done
+	popd >/dev/null || die
+}
+
+# @FUNCTION: rebar3_src_install
+# @DESCRIPTION:
+# Install built release or library.
+#
+# Function expects that project conforms to Erlang/OTP structure.
+rebar3_src_install() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	pushd "_build/${REBAR_PROFILE}" >/dev/null || die
+	if [[ -d rel/${PN} ]]; then
+		if ! declare -f rebar3_install_release >/dev/null; then
+			die "${FUNCNAME}: a custom function named 'rebar3_install_release' is required to install a release"
+		fi
+		pushd rel/${PN} >/dev/null || die
+		rebar3_install_release || die
+		popd >/dev/null || die
+	elif [[ -d lib/${PN} ]]; then
+		rebar3_install_lib lib/${PN}
+	else
+		die "No releases or libraries to install"
+	fi
+	popd >/dev/null || die
+
+	einstalldocs
+}
+
+fi
+
+EXPORT_FUNCTIONS src_prepare src_compile src_test src_install
-- 
2.44.2



^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2024-07-16  9:37 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-16  9:35 [gentoo-dev] [PATCH 0/2] Introduce rebar3.eclass Florian Schmaus
2024-07-16  9:35 ` [gentoo-dev] [PATCH 1/2] rebar.eclass: factor out common functions into rebar-utils.eclass Florian Schmaus
2024-07-16  9:35 ` [gentoo-dev] [PATCH 2/2] rebar3.eclass: add new eclass Florian Schmaus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox