public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
@ 2016-05-18 22:35 aidecoe
  2016-05-18 23:26 ` Peter Stuge
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: aidecoe @ 2016-05-18 22:35 UTC (permalink / raw
  To: gentoo-dev; +Cc: Amadeusz Żołnowski

From: Amadeusz Żołnowski <aidecoe@gentoo.org>

It is an eclass providing functions to build Erlang/OTP projects using
dev-util/rebar. All packages in upcoming category dev-erlang are going
to use this eclass.
---
 eclass/rebar.eclass | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 220 insertions(+)
 create mode 100644 eclass/rebar.eclass

diff --git a/eclass/rebar.eclass b/eclass/rebar.eclass
new file mode 100644
index 0000000..e1ac52f
--- /dev/null
+++ b/eclass/rebar.eclass
@@ -0,0 +1,220 @@
+# Copyright 1999-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+# @ECLASS: rebar.eclass
+# @MAINTAINER:
+# Amadeusz Żołnowski <aidecoe@gentoo.org>
+# @AUTHOR:
+# Amadeusz Żołnowski <aidecoe@gentoo.org>
+# @BLURB: Build Erlang/OTP projects using dev-util/rebar.
+# @DESCRIPTION:
+# An eclass providing functions to build Erlang/OTP projects using
+# dev-util/rebar.
+#
+# rebar is a tool which tries to resolve dependencies itself which is by
+# cloning remote git repositories. Dependant 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:-0}" in
+	0|1|2|3|4)
+		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
+		;;
+	5|6)
+		;;
+	*)
+		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
+		;;
+esac
+
+[[ ${EAPI} = 5 ]] && inherit eutils
+
+EXPORT_FUNCTIONS src_prepare src_compile src_install
+
+RDEPEND="dev-lang/erlang"
+DEPEND="${RDEPEND}
+	dev-util/rebar"
+
+# @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"
+}
+
+# @VARIABLE: ERL_LIBS
+# @DESCRIPTION:
+# Full path with EPREFIX to Erlang lib directory. Some rebar scripts expect it.
+export ERL_LIBS="${EPREFIX}$(get_erl_libs)"
+
+# @FUNCTION: _find_dep_version
+# @INTERNAL
+# @USAGE: <project_name>
+# @RETURN: full path with EPREFIX to a Erlang package/project
+# @DESCRIPTION:
+# Find a Erlang package/project by name in Erlang lib directory. Project
+# directory is usually suffixed with version. First match to <project_name> or
+# <project_name>-* is returned.
+_find_dep_version() {
+	local pn="$1"
+	local p
+
+	pushd "${EPREFIX}$(get_erl_libs)" >/dev/null
+	for p in ${pn} ${pn}-*; do
+		if [[ -d ${p} ]]; then
+			echo "${p#${pn}-}"
+			return 0
+		fi
+	done
+	popd >/dev/null
+
+	return 1
+}
+
+# @FUNCTION: eawk
+# @USAGE: <file> <args>
+# @DESCRIPTION:
+# Edit file <file> in place with awk. Pass all arguments following <file> to
+# awk.
+eawk() {
+	local f="$1"; shift
+	local tmpf="$(emktemp)"
+
+	cat "${f}" >"${tmpf}" || return 1
+	awk "$@" "${tmpf}" >"${f}"
+}
+
+# @FUNCTION: erebar
+# @USAGE: <target>
+# @DESCRIPTION:
+# Run rebar with verbose flag. Die on failure.
+erebar() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	rebar -v skip_deps=true "$1" || die "rebar $1 failed"
+}
+
+# @FUNCTION: rebar_fix_include_path
+# @USAGE: <project_name> [<rebar_config>]
+# @DESCRIPTION:
+# Fix path in rebar.config to 'include' directory of dependant 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 pv="$(_find_dep_version "${pn}")"
+
+	eawk "${rebar_config}" \
+		-v erl_libs="${erl_libs}" -v pn="${pn}" -v pv="${pv}" \
+		'/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
+	pattern = "\"(./)?deps/" pn "/include\"";
+	if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
+		sub(pattern, "\"" erl_libs "/" pn "-" pv "/include\"");
+	}
+	print $0;
+	next;
+}
+1
+' || die "failed to fix include paths in ${rebar_config}"
+}
+
+# @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
+	eawk "${rebar_config}" \
+		'/^{[[:space:]]*deps[[:space:]]*,/, /}[[:space:]]*\.$/ {
+	if ($0 ~ /}[[:space:]]*\.$/) {
+		print "{deps, []}.";
+	}
+	next;
+}
+1
+' || 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}/src/${PN}.app.src" \
+		|| die "failed to set version in src/${PN}.app.src"
+}
+
+# @FUNCTION: rebar_src_prepare
+# @DESCRIPTION:
+# Prevent rebar from fetching in 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'.
+rebar_src_prepare() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	rebar_set_vsn
+	[[ -f rebar.config ]] && rebar_remove_deps
+}
+
+# @FUNCTION: rebar_src_compile
+# @DESCRIPTION:
+# Compile project with rebar.
+rebar_src_compile() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	erebar compile
+}
+
+# @FUNCTION: rebar_src_install
+# @DESCRIPTION:
+# Install BEAM files, include headers, executables and native libraries.
+# Install standard docs like README or defined in DOCS variable. Optionally
+#
+# Function expects that project conforms to Erlang/OTP structure.
+rebar_src_install() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local bin
+	local dest="$(get_erl_libs)/${P}"
+
+	insinto "${dest}"
+	doins -r ebin
+	[[ -d include ]] && doins -r include
+	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done
+	[[ -d priv ]] && cp -pR priv "${ED}${dest}/"
+
+	einstalldocs
+}
-- 
2.8.2



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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-18 22:35 [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar aidecoe
@ 2016-05-18 23:26 ` Peter Stuge
  2016-05-20 23:09   ` Amadeusz Żołnowski
  2016-05-19  4:39 ` Michał Górny
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: Peter Stuge @ 2016-05-18 23:26 UTC (permalink / raw
  To: gentoo-dev

Cool!

aidecoe@gentoo.org wrote:
> +_find_dep_version() {
> +	local pn="$1"
> +	local p
> +
> +	pushd "${EPREFIX}$(get_erl_libs)" >/dev/null
> +	for p in ${pn} ${pn}-*; do
> +		if [[ -d ${p} ]]; then
> +			echo "${p#${pn}-}"
> +			return 0

No popd on success?

> +		fi
> +	done
> +	popd >/dev/null
> +
> +	return 1
> +}



> +# @FUNCTION: eawk
> +# @USAGE: <file> <args>
> +# @DESCRIPTION:
> +# Edit file <file> in place with awk. Pass all arguments following <file> to
> +# awk.
> +eawk() {
> +	local f="$1"; shift
> +	local tmpf="$(emktemp)"
> +
> +	cat "${f}" >"${tmpf}" || return 1
> +	awk "$@" "${tmpf}" >"${f}"
> +}

Wouldn't it be nicer to cut cat, awk > $tmpf && mv $tmpf $f ?


//Peter


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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-18 22:35 [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar aidecoe
  2016-05-18 23:26 ` Peter Stuge
@ 2016-05-19  4:39 ` Michał Górny
  2016-05-20 23:06   ` Amadeusz Żołnowski
  2016-05-21 13:26 ` aidecoe
  2016-05-21 23:19 ` aidecoe
  3 siblings, 1 reply; 14+ messages in thread
From: Michał Górny @ 2016-05-19  4:39 UTC (permalink / raw
  To: aidecoe; +Cc: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 8553 bytes --]

On Wed, 18 May 2016 23:35:18 +0100
aidecoe@gentoo.org wrote:

> From: Amadeusz Żołnowski <aidecoe@gentoo.org>
> 
> It is an eclass providing functions to build Erlang/OTP projects using
> dev-util/rebar. All packages in upcoming category dev-erlang are going
> to use this eclass.
> ---
>  eclass/rebar.eclass | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 220 insertions(+)
>  create mode 100644 eclass/rebar.eclass
> 
> diff --git a/eclass/rebar.eclass b/eclass/rebar.eclass
> new file mode 100644
> index 0000000..e1ac52f
> --- /dev/null
> +++ b/eclass/rebar.eclass
> @@ -0,0 +1,220 @@
> +# Copyright 1999-2016 Gentoo Foundation
> +# Distributed under the terms of the GNU General Public License v2
> +# $Id$
> +
> +# @ECLASS: rebar.eclass
> +# @MAINTAINER:
> +# Amadeusz Żołnowski <aidecoe@gentoo.org>
> +# @AUTHOR:
> +# Amadeusz Żołnowski <aidecoe@gentoo.org>
> +# @BLURB: Build Erlang/OTP projects using dev-util/rebar.
> +# @DESCRIPTION:
> +# An eclass providing functions to build Erlang/OTP projects using
> +# dev-util/rebar.
> +#
> +# rebar is a tool which tries to resolve dependencies itself which is by
> +# cloning remote git repositories. Dependant 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:-0}" in
> +	0|1|2|3|4)
> +		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
> +		;;
> +	5|6)
> +		;;
> +	*)
> +		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
> +		;;
> +esac
> +
> +[[ ${EAPI} = 5 ]] && inherit eutils
> +
> +EXPORT_FUNCTIONS src_prepare src_compile src_install
> +
> +RDEPEND="dev-lang/erlang"
> +DEPEND="${RDEPEND}
> +	dev-util/rebar"
> +
> +# @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"

Missing multilib inherit for EAPI 5.

> +}
> +
> +# @VARIABLE: ERL_LIBS
> +# @DESCRIPTION:
> +# Full path with EPREFIX to Erlang lib directory. Some rebar scripts expect it.
> +export ERL_LIBS="${EPREFIX}$(get_erl_libs)"

I think calling get_libdir in global scope is forbidden. You should
really export this somewhere in phase function.

> +
> +# @FUNCTION: _find_dep_version

Namespace it, please. Just in case.

> +# @INTERNAL
> +# @USAGE: <project_name>
> +# @RETURN: full path with EPREFIX to a Erlang package/project
> +# @DESCRIPTION:
> +# Find a Erlang package/project by name in Erlang lib directory. Project
> +# directory is usually suffixed with version. First match to <project_name> or
> +# <project_name>-* is returned.
> +_find_dep_version() {
> +	local pn="$1"
> +	local p
> +
> +	pushd "${EPREFIX}$(get_erl_libs)" >/dev/null

|| die

> +	for p in ${pn} ${pn}-*; do
> +		if [[ -d ${p} ]]; then
> +			echo "${p#${pn}-}"
> +			return 0
> +		fi
> +	done
> +	popd >/dev/null

|| die

> +
> +	return 1
> +}
> +
> +# @FUNCTION: eawk
> +# @USAGE: <file> <args>
> +# @DESCRIPTION:
> +# Edit file <file> in place with awk. Pass all arguments following <file> to
> +# awk.
> +eawk() {
> +	local f="$1"; shift
> +	local tmpf="$(emktemp)"

Missing eutils inherit for EAPI 6.

> +
> +	cat "${f}" >"${tmpf}" || return 1
> +	awk "$@" "${tmpf}" >"${f}"
> +}
> +
> +# @FUNCTION: erebar
> +# @USAGE: <target>
> +# @DESCRIPTION:
> +# Run rebar with verbose flag. Die on failure.
> +erebar() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	rebar -v skip_deps=true "$1" || die "rebar $1 failed"
> +}

Any reason it doesn't pass all the parameters? This inconsistency with
emake etc. could be mildly confusing, esp. that you don't check for
wrong argc.

> +
> +# @FUNCTION: rebar_fix_include_path
> +# @USAGE: <project_name> [<rebar_config>]
> +# @DESCRIPTION:
> +# Fix path in rebar.config to 'include' directory of dependant project/package,
> +# so it points to installation in system Erlang lib rather than relative 'deps'
> +# directory.
> +#
> +# <rebar_config> is optional. Default is 'rebar.config'.

Is it likely that you would be passing different values to it? Maybe it
would be reasonable to make this an eclass variable.

> +#
> +# 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 pv="$(_find_dep_version "${pn}")"
> +
> +	eawk "${rebar_config}" \
> +		-v erl_libs="${erl_libs}" -v pn="${pn}" -v pv="${pv}" \
> +		'/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
> +	pattern = "\"(./)?deps/" pn "/include\"";
> +	if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
> +		sub(pattern, "\"" erl_libs "/" pn "-" pv "/include\"");
> +	}
> +	print $0;
> +	next;
> +}
> +1
> +' || die "failed to fix include paths in ${rebar_config}"

I suggest you indent this a bit more since it feels like you start at
two tabs and finish at zero.

> +}
> +
> +# @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
> +	eawk "${rebar_config}" \
> +		'/^{[[:space:]]*deps[[:space:]]*,/, /}[[:space:]]*\.$/ {
> +	if ($0 ~ /}[[:space:]]*\.$/) {
> +		print "{deps, []}.";
> +	}
> +	next;
> +}
> +1
> +' || 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}/src/${PN}.app.src" \
> +		|| die "failed to set version in src/${PN}.app.src"
> +}
> +
> +# @FUNCTION: rebar_src_prepare
> +# @DESCRIPTION:
> +# Prevent rebar from fetching in 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'.

Wouldn't it be reasonable to make this configurable? Of course, it
might be better to leave it for a possible future extension when
it becomes necessary.

> +rebar_src_prepare() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	rebar_set_vsn
> +	[[ -f rebar.config ]] && rebar_remove_deps
> +}

You're missing obligatory default call for EAPI 6. You should really
test stuff before submitting it.

> +
> +# @FUNCTION: rebar_src_compile
> +# @DESCRIPTION:
> +# Compile project with rebar.
> +rebar_src_compile() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	erebar compile
> +}
> +
> +# @FUNCTION: rebar_src_install
> +# @DESCRIPTION:
> +# Install BEAM files, include headers, executables and native libraries.
> +# Install standard docs like README or defined in DOCS variable. Optionally

Optionally what? It looks like an unfinished sentence.

> +#
> +# Function expects that project conforms to Erlang/OTP structure.
> +rebar_src_install() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	local bin
> +	local dest="$(get_erl_libs)/${P}"
> +
> +	insinto "${dest}"
> +	doins -r ebin
> +	[[ -d include ]] && doins -r include
> +	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done

Please don't do inlines like this.

> +	[[ -d priv ]] && cp -pR priv "${ED}${dest}/"

This is about preserving executable bits, correct?

> +
> +	einstalldocs
> +}



-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 949 bytes --]

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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-19  4:39 ` Michał Górny
@ 2016-05-20 23:06   ` Amadeusz Żołnowski
  2016-05-21  7:00     ` Michał Górny
  0 siblings, 1 reply; 14+ messages in thread
From: Amadeusz Żołnowski @ 2016-05-20 23:06 UTC (permalink / raw
  To: Michał Górny; +Cc: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 4257 bytes --]

Michał Górny <mgorny@gentoo.org> writes:
>> +export ERL_LIBS="${EPREFIX}$(get_erl_libs)"
>
> I think calling get_libdir in global scope is forbidden. You should
> really export this somewhere in phase function.

Fixed.


>> +# @FUNCTION: _find_dep_version
>
> Namespace it, please. Just in case.

Fixed.

>> +_find_dep_version() {
>> [...]
>> +	pushd "${EPREFIX}$(get_erl_libs)" >/dev/null
>
> || die
>
> [...]
>
>> +	popd >/dev/null
>
> || die

Fixed.


>> +eawk() {
>> +	local f="$1"; shift
>> +	local tmpf="$(emktemp)"
>
> Missing eutils inherit for EAPI 6.

Fixed.

>> +# @FUNCTION: erebar
>> +# @USAGE: <target>
>> +# @DESCRIPTION:
>> +# Run rebar with verbose flag. Die on failure.
>> +erebar() {
>> +	debug-print-function ${FUNCNAME} "${@}"
>> +
>> +	rebar -v skip_deps=true "$1" || die "rebar $1 failed"
>> +}
>
> Any reason it doesn't pass all the parameters? This inconsistency with
> emake etc. could be mildly confusing, esp. that you don't check for
> wrong argc.

Fixed.


>> +# @FUNCTION: rebar_fix_include_path
>> +# @USAGE: <project_name> [<rebar_config>]
>> +# @DESCRIPTION:
>> +# Fix path in rebar.config to 'include' directory of dependant project/package,
>> +# so it points to installation in system Erlang lib rather than relative 'deps'
>> +# directory.
>> +#
>> +# <rebar_config> is optional. Default is 'rebar.config'.
>
> Is it likely that you would be passing different values to it? Maybe it
> would be reasonable to make this an eclass variable.

Unlikely. But I'd better just remove these parameters rather than
defining as eclass variable.


>> +	eawk "${rebar_config}" \
>> +		-v erl_libs="${erl_libs}" -v pn="${pn}" -v pv="${pv}" \
>> +		'/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
>> +	pattern = "\"(./)?deps/" pn "/include\"";
>> +	if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
>> +		sub(pattern, "\"" erl_libs "/" pn "-" pv "/include\"");
>> +	}
>> +	print $0;
>> +	next;
>> +}
>> +1
>> +' || die "failed to fix include paths in ${rebar_config}"
>
> I suggest you indent this a bit more since it feels like you start at
> two tabs and finish at zero.

How? Add space between "'" and "||" like follows?

+	eawk "${rebar_config}" \
...
+	print $0;
+	next;
+}
+1
+'          || die "failed to fix include paths in ${rebar_config}"

It looks a bit weird as well...


>> +# @FUNCTION: rebar_src_prepare
>> +# @DESCRIPTION:
>> +# Prevent rebar from fetching in 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'.
>
> Wouldn't it be reasonable to make this configurable? Of course, it
> might be better to leave it for a possible future extension when
> it becomes necessary.

Which part you mean? 'src/${PN}.app.src'? Fixed: REBAR_APP_SRC eclass var.

>> +rebar_src_prepare() {
>> +	debug-print-function ${FUNCNAME} "${@}"
>> +
>> +	rebar_set_vsn
>> +	[[ -f rebar.config ]] && rebar_remove_deps
>> +}
>
> You're missing obligatory default call for EAPI 6. You should really
> test stuff before submitting it.

Shame I have forgot to test it, sorry. I have completely forgotten about
EAPI 6. Fixed - I have made it working with EAPI 6 and dropped EAPI 5.


>> +# @FUNCTION: rebar_src_install
>> +# @DESCRIPTION:
>> +# Install BEAM files, include headers, executables and native libraries.
>> +# Install standard docs like README or defined in DOCS variable. Optionally
>
> Optionally what? It looks like an unfinished sentence.

Nothing. (-: Some leftover.


>> +rebar_src_install() {
>> +	debug-print-function ${FUNCNAME} "${@}"
>> +
>> +	local bin
>> +	local dest="$(get_erl_libs)/${P}"
>> +
>> +	insinto "${dest}"
>> +	doins -r ebin
>> +	[[ -d include ]] && doins -r include
>> +	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done
>
> Please don't do inlines like this.

Is there a particular problem with this?

>> +	[[ -d priv ]] && cp -pR priv "${ED}${dest}/"
>
> This is about preserving executable bits, correct?

Yes.

Thanks for review.

-- 
Amadeusz Żołnowski

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 950 bytes --]

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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-18 23:26 ` Peter Stuge
@ 2016-05-20 23:09   ` Amadeusz Żołnowski
  0 siblings, 0 replies; 14+ messages in thread
From: Amadeusz Żołnowski @ 2016-05-20 23:09 UTC (permalink / raw
  To: Peter Stuge; +Cc: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 550 bytes --]

Peter Stuge <peter@stuge.se> writes:

>> +	pushd "${EPREFIX}$(get_erl_libs)" >/dev/null
>> +	for p in ${pn} ${pn}-*; do
>> +		if [[ -d ${p} ]]; then
>> +			echo "${p#${pn}-}"
>> +			return 0
>
> No popd on success?

Thanks for catching this up! Fixed.

>> +	local tmpf="$(emktemp)"
>> +
>> +	cat "${f}" >"${tmpf}" || return 1
>> +	awk "$@" "${tmpf}" >"${f}"
>> +}
>
> Wouldn't it be nicer to cut cat, awk > $tmpf && mv $tmpf $f ?

No. Please see separate review of eawk where it is explained.

Thanks,
-- Amadeusz Żołnowski

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 950 bytes --]

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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-20 23:06   ` Amadeusz Żołnowski
@ 2016-05-21  7:00     ` Michał Górny
  2016-05-21  8:35       ` Amadeusz Żołnowski
  0 siblings, 1 reply; 14+ messages in thread
From: Michał Górny @ 2016-05-21  7:00 UTC (permalink / raw
  To: Amadeusz Żołnowski; +Cc: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 692 bytes --]

On Sat, 21 May 2016 00:06:01 +0100
Amadeusz Żołnowski <aidecoe@gentoo.org> wrote:

> >> +rebar_src_install() {
> >> +	debug-print-function ${FUNCNAME} "${@}"
> >> +
> >> +	local bin
> >> +	local dest="$(get_erl_libs)/${P}"
> >> +
> >> +	insinto "${dest}"
> >> +	doins -r ebin
> >> +	[[ -d include ]] && doins -r include
> >> +	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done  
> >
> > Please don't do inlines like this.  
> 
> Is there a particular problem with this?

Readability and maintainability. At some point someone may want to
extend this, and it will no longer work as one-liner.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 949 bytes --]

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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-21  7:00     ` Michał Górny
@ 2016-05-21  8:35       ` Amadeusz Żołnowski
  0 siblings, 0 replies; 14+ messages in thread
From: Amadeusz Żołnowski @ 2016-05-21  8:35 UTC (permalink / raw
  To: Michał Górny; +Cc: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 655 bytes --]

Michał Górny <mgorny@gentoo.org> writes:
>> >> +	[[ -d include ]] && doins -r include
>> >> +	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done  
>> >
>> > Please don't do inlines like this.  
>> 
>> Is there a particular problem with this?
>
> Readability and maintainability. At some point someone may want to
> extend this, and it will no longer work as one-liner.

That's rather subjective. Given the context I find concise. When
uninlined it takes 4 lines more, gets out of context and looks more
noisy to me. If someone would like to extend the inline version it could
be uninlined at that point.

-- 
Amadeusz Żołnowski

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 950 bytes --]

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

* [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-18 22:35 [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar aidecoe
  2016-05-18 23:26 ` Peter Stuge
  2016-05-19  4:39 ` Michał Górny
@ 2016-05-21 13:26 ` aidecoe
  2016-05-21 20:48   ` Michał Górny
  2016-05-21 23:19 ` aidecoe
  3 siblings, 1 reply; 14+ messages in thread
From: aidecoe @ 2016-05-21 13:26 UTC (permalink / raw
  To: gentoo-dev; +Cc: Amadeusz Żołnowski

From: Amadeusz Żołnowski <aidecoe@gentoo.org>

It is an eclass providing functions to build Erlang/OTP projects using
dev-util/rebar. All packages in upcoming category dev-erlang are going
to use this eclass.
---
 eclass/rebar.eclass | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 217 insertions(+)
 create mode 100644 eclass/rebar.eclass

diff --git a/eclass/rebar.eclass b/eclass/rebar.eclass
new file mode 100644
index 0000000..9da1340
--- /dev/null
+++ b/eclass/rebar.eclass
@@ -0,0 +1,217 @@
+# Copyright 1999-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+# @ECLASS: rebar.eclass
+# @MAINTAINER:
+# Amadeusz Żołnowski <aidecoe@gentoo.org>
+# @AUTHOR:
+# Amadeusz Żołnowski <aidecoe@gentoo.org>
+# @BLURB: Build Erlang/OTP projects using dev-util/rebar.
+# @DESCRIPTION:
+# An eclass providing functions to build Erlang/OTP projects using
+# dev-util/rebar.
+#
+# rebar is a tool which tries to resolve dependencies itself which is by
+# cloning remote git repositories. Dependant 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:-0}" in
+	0|1|2|3|4|5)
+		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
+		;;
+	6)
+		;;
+	*)
+		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
+		;;
+esac
+
+inherit eutils
+
+EXPORT_FUNCTIONS src_prepare src_compile src_install
+
+RDEPEND="dev-lang/erlang"
+DEPEND="${RDEPEND}
+	dev-util/rebar"
+
+# @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_version
+# @INTERNAL
+# @USAGE: <project_name>
+# @RETURN: full path with EPREFIX to a Erlang package/project
+# @DESCRIPTION:
+# Find a Erlang package/project by name in Erlang lib directory. Project
+# directory is usually suffixed with version. First match to <project_name> or
+# <project_name>-* is returned.
+_rebar_find_dep_version() {
+	local pn="$1"
+	local p
+
+	pushd "${EPREFIX}$(get_erl_libs)" >/dev/null || die
+	for p in ${pn} ${pn}-*; do
+		if [[ -d ${p} ]]; then
+			echo "${p#${pn}-}"
+			break
+		fi
+	done
+	popd >/dev/null || die
+
+	[[ -d ${p} ]]
+}
+
+# @FUNCTION: erebar
+# @USAGE: <targets>
+# @DESCRIPTION:
+# Run rebar with verbose flag. Die on failure.
+erebar() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	(( $# > 0 )) || die 'erebar: at least one target is required'
+
+	evar_push ERL_LIBS
+	export ERL_LIBS="${EPREFIX}$(get_erl_libs)"
+	rebar -v skip_deps=true "$@" || die "rebar $@ failed"
+	evar_pop
+}
+
+# @FUNCTION: rebar_fix_include_path
+# @USAGE: <project_name>
+# @DESCRIPTION:
+# Fix path in rebar.config to 'include' directory of dependant project/package,
+# so it points to installation in system Erlang lib rather than relative 'deps'
+# directory.
+#
+# The function dies on failure.
+rebar_fix_include_path() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local pn="$1"
+	local erl_libs="${EPREFIX}$(get_erl_libs)"
+	local pv="$(_rebar_find_dep_version "${pn}")"
+
+	eawk rebar.config \
+		-v erl_libs="${erl_libs}" -v pn="${pn}" -v pv="${pv}" \
+		'/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
+	pattern = "\"(./)?deps/" pn "/include\"";
+	if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
+		sub(pattern, "\"" erl_libs "/" pn "-" pv "/include\"");
+	}
+	print $0;
+	next;
+}
+1
+' || die "failed to fix include paths in rebar.config"
+}
+
+# @FUNCTION: rebar_remove_deps
+# @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.
+#
+# The function dies on failure.
+rebar_remove_deps() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	mkdir -p "${S}/deps" && :>"${S}/deps/.got" && :>"${S}/deps/.built" || die
+	eawk rebar.config \
+		'/^{[[:space:]]*deps[[:space:]]*,/, /}[[:space:]]*\.$/ {
+	if ($0 ~ /}[[:space:]]*\.$/) {
+		print "{deps, []}.";
+	}
+	next;
+}
+1
+' || 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 in 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'.
+rebar_src_prepare() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	default
+	rebar_set_vsn
+	[[ -f rebar.config ]] && rebar_remove_deps
+}
+
+# @FUNCTION: rebar_src_configure
+# @DESCRIPTION:
+# Configure with ERL_LIBS set.
+rebar_src_configure() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	evar_push ERL_LIBS
+	export ERL_LIBS="${EPREFIX}$(get_erl_libs)"
+	default
+	evar_pop
+}
+
+# @FUNCTION: rebar_src_compile
+# @DESCRIPTION:
+# Compile project with rebar.
+rebar_src_compile() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	erebar compile
+}
+
+# @FUNCTION: rebar_src_install
+# @DESCRIPTION:
+# Install BEAM files, include headers, executables and native libraries.
+# Install standard docs like README or defined in DOCS variable.
+#
+# Function expects that project conforms to Erlang/OTP structure.
+rebar_src_install() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local bin
+	local dest="$(get_erl_libs)/${P}"
+
+	insinto "${dest}"
+	doins -r ebin
+	[[ -d include ]] && doins -r include
+	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done
+	[[ -d priv ]] && cp -pR priv "${ED}${dest}/"
+
+	einstalldocs
+}
-- 
2.8.2



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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-21 13:26 ` aidecoe
@ 2016-05-21 20:48   ` Michał Górny
  2016-05-21 22:11     ` Amadeusz Żołnowski
  0 siblings, 1 reply; 14+ messages in thread
From: Michał Górny @ 2016-05-21 20:48 UTC (permalink / raw
  To: aidecoe; +Cc: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 8020 bytes --]

On Sat, 21 May 2016 14:26:00 +0100
aidecoe@gentoo.org wrote:

> From: Amadeusz Żołnowski <aidecoe@gentoo.org>
> 
> It is an eclass providing functions to build Erlang/OTP projects using
> dev-util/rebar. All packages in upcoming category dev-erlang are going
> to use this eclass.
> ---
>  eclass/rebar.eclass | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 217 insertions(+)
>  create mode 100644 eclass/rebar.eclass
> 
> diff --git a/eclass/rebar.eclass b/eclass/rebar.eclass
> new file mode 100644
> index 0000000..9da1340
> --- /dev/null
> +++ b/eclass/rebar.eclass
> @@ -0,0 +1,217 @@
> +# Copyright 1999-2016 Gentoo Foundation
> +# Distributed under the terms of the GNU General Public License v2
> +# $Id$
> +
> +# @ECLASS: rebar.eclass
> +# @MAINTAINER:
> +# Amadeusz Żołnowski <aidecoe@gentoo.org>
> +# @AUTHOR:
> +# Amadeusz Żołnowski <aidecoe@gentoo.org>
> +# @BLURB: Build Erlang/OTP projects using dev-util/rebar.
> +# @DESCRIPTION:
> +# An eclass providing functions to build Erlang/OTP projects using
> +# dev-util/rebar.
> +#
> +# rebar is a tool which tries to resolve dependencies itself which is by
> +# cloning remote git repositories. Dependant 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:-0}" in
> +	0|1|2|3|4|5)
> +		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
> +		;;
> +	6)
> +		;;
> +	*)
> +		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
> +		;;
> +esac
> +
> +inherit eutils
> +
> +EXPORT_FUNCTIONS src_prepare src_compile src_install
> +
> +RDEPEND="dev-lang/erlang"
> +DEPEND="${RDEPEND}
> +	dev-util/rebar"
> +
> +# @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_version
> +# @INTERNAL
> +# @USAGE: <project_name>
> +# @RETURN: full path with EPREFIX to a Erlang package/project
> +# @DESCRIPTION:
> +# Find a Erlang package/project by name in Erlang lib directory. Project
> +# directory is usually suffixed with version. First match to <project_name> or
> +# <project_name>-* is returned.
> +_rebar_find_dep_version() {
> +	local pn="$1"
> +	local p
> +
> +	pushd "${EPREFIX}$(get_erl_libs)" >/dev/null || die
> +	for p in ${pn} ${pn}-*; do
> +		if [[ -d ${p} ]]; then
> +			echo "${p#${pn}-}"
> +			break
> +		fi
> +	done
> +	popd >/dev/null || die
> +
> +	[[ -d ${p} ]]
> +}
> +
> +# @FUNCTION: erebar
> +# @USAGE: <targets>
> +# @DESCRIPTION:
> +# Run rebar with verbose flag. Die on failure.
> +erebar() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	(( $# > 0 )) || die 'erebar: at least one target is required'

Why not [[ $# -gt 0 ]]? It's the first time I see someone using (( ))
for conditionals.

> +
> +	evar_push ERL_LIBS
> +	export ERL_LIBS="${EPREFIX}$(get_erl_libs)"

local -x ERL_LIBS=...

We don't really have to employ terribly ugly eval hackery to have
a local variable.

> +	rebar -v skip_deps=true "$@" || die "rebar $@ failed"
> +	evar_pop
> +}
> +
> +# @FUNCTION: rebar_fix_include_path
> +# @USAGE: <project_name>
> +# @DESCRIPTION:
> +# Fix path in rebar.config to 'include' directory of dependant project/package,
> +# so it points to installation in system Erlang lib rather than relative 'deps'
> +# directory.
> +#
> +# The function dies on failure.
> +rebar_fix_include_path() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	local pn="$1"
> +	local erl_libs="${EPREFIX}$(get_erl_libs)"
> +	local pv="$(_rebar_find_dep_version "${pn}")"
> +
> +	eawk rebar.config \
> +		-v erl_libs="${erl_libs}" -v pn="${pn}" -v pv="${pv}" \
> +		'/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
> +	pattern = "\"(./)?deps/" pn "/include\"";
> +	if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
> +		sub(pattern, "\"" erl_libs "/" pn "-" pv "/include\"");
> +	}
> +	print $0;
> +	next;
> +}
> +1
> +' || die "failed to fix include paths in rebar.config"

I meant indent like this:

+	eawk rebar.config \
+		-v erl_libs="${erl_libs}" -v pn="${pn}" -v pv="${pv}" \
+		'/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
+			pattern = "\"(./)?deps/" pn "/include\"";
+			if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
+				sub(pattern, "\"" erl_libs "/" pn "-" pv "/include\"");
+			}
+			print $0;
+			next;
+		}
+		1
+	' || die "failed to fix include paths in rebar.config"


> +}
> +
> +# @FUNCTION: rebar_remove_deps
> +# @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.
> +#
> +# The function dies on failure.
> +rebar_remove_deps() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	mkdir -p "${S}/deps" && :>"${S}/deps/.got" && :>"${S}/deps/.built" || die
> +	eawk rebar.config \
> +		'/^{[[:space:]]*deps[[:space:]]*,/, /}[[:space:]]*\.$/ {
> +	if ($0 ~ /}[[:space:]]*\.$/) {
> +		print "{deps, []}.";
> +	}
> +	next;
> +}
> +1
> +' || 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 in 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'.
> +rebar_src_prepare() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	default
> +	rebar_set_vsn
> +	[[ -f rebar.config ]] && rebar_remove_deps
> +}
> +
> +# @FUNCTION: rebar_src_configure
> +# @DESCRIPTION:
> +# Configure with ERL_LIBS set.
> +rebar_src_configure() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	evar_push ERL_LIBS
> +	export ERL_LIBS="${EPREFIX}$(get_erl_libs)"
> +	default
> +	evar_pop
> +}
> +
> +# @FUNCTION: rebar_src_compile
> +# @DESCRIPTION:
> +# Compile project with rebar.
> +rebar_src_compile() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	erebar compile
> +}
> +
> +# @FUNCTION: rebar_src_install
> +# @DESCRIPTION:
> +# Install BEAM files, include headers, executables and native libraries.
> +# Install standard docs like README or defined in DOCS variable.
> +#
> +# Function expects that project conforms to Erlang/OTP structure.
> +rebar_src_install() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	local bin
> +	local dest="$(get_erl_libs)/${P}"
> +
> +	insinto "${dest}"
> +	doins -r ebin
> +	[[ -d include ]] && doins -r include
> +	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done
> +	[[ -d priv ]] && cp -pR priv "${ED}${dest}/"

Missing ||die. Just don't do it as one-liner :-P.

> +
> +	einstalldocs
> +}



-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 949 bytes --]

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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-21 20:48   ` Michał Górny
@ 2016-05-21 22:11     ` Amadeusz Żołnowski
  0 siblings, 0 replies; 14+ messages in thread
From: Amadeusz Żołnowski @ 2016-05-21 22:11 UTC (permalink / raw
  To: Michał Górny; +Cc: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 1422 bytes --]

Michał Górny <mgorny@gentoo.org> writes:
>> +# Run rebar with verbose flag. Die on failure.
>> +erebar() {
>> +	debug-print-function ${FUNCNAME} "${@}"
>> +
>> +	(( $# > 0 )) || die 'erebar: at least one target is required'
>
> Why not [[ $# -gt 0 ]]? It's the first time I see someone using (( ))
> for conditionals.

'>' reads better than some '-gt'.


>> +	evar_push ERL_LIBS
>> +	export ERL_LIBS="${EPREFIX}$(get_erl_libs)"
>
> local -x ERL_LIBS=...
>
> We don't really have to employ terribly ugly eval hackery to have
> a local variable.

Fixed. I hoped there's better way! (-:


> I meant indent like this:
>
> +	eawk rebar.config \
> +		-v erl_libs="${erl_libs}" -v pn="${pn}" -v pv="${pv}" \
> +		'/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
> +			pattern = "\"(./)?deps/" pn "/include\"";
> +			if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
> +				sub(pattern, "\"" erl_libs "/" pn "-" pv "/include\"");
> +			}
> +			print $0;
> +			next;
> +		}
> +		1
> +	' || die "failed to fix include paths in rebar.config"

OK.


>> +	insinto "${dest}"
>> +	doins -r ebin
>> +	[[ -d include ]] && doins -r include
>> +	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done
>> +	[[ -d priv ]] && cp -pR priv "${ED}${dest}/"
>
> Missing ||die. Just don't do it as one-liner :-P.

You've got me! ;-)


Thanks,
-- 
Amadeusz Żołnowski

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 950 bytes --]

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

* [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-18 22:35 [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar aidecoe
                   ` (2 preceding siblings ...)
  2016-05-21 13:26 ` aidecoe
@ 2016-05-21 23:19 ` aidecoe
  2016-05-21 23:22   ` [gentoo-dev] [PATCH 2/2] Add tests for rebar.eclass aidecoe
  2016-05-22 21:14   ` [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar Michał Górny
  3 siblings, 2 replies; 14+ messages in thread
From: aidecoe @ 2016-05-21 23:19 UTC (permalink / raw
  To: gentoo-dev; +Cc: Amadeusz Żołnowski

From: Amadeusz Żołnowski <aidecoe@gentoo.org>

It is an eclass providing functions to build Erlang/OTP projects using
dev-util/rebar. All packages in upcoming category dev-erlang are going
to use this eclass.
---
 eclass/rebar.eclass | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 223 insertions(+)
 create mode 100644 eclass/rebar.eclass

diff --git a/eclass/rebar.eclass b/eclass/rebar.eclass
new file mode 100644
index 0000000..1a4eaba
--- /dev/null
+++ b/eclass/rebar.eclass
@@ -0,0 +1,223 @@
+# Copyright 1999-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+# @ECLASS: rebar.eclass
+# @MAINTAINER:
+# Amadeusz Żołnowski <aidecoe@gentoo.org>
+# @AUTHOR:
+# Amadeusz Żołnowski <aidecoe@gentoo.org>
+# @BLURB: Build Erlang/OTP projects using dev-util/rebar.
+# @DESCRIPTION:
+# An eclass providing functions to build Erlang/OTP projects using
+# dev-util/rebar.
+#
+# rebar is a tool which tries to resolve dependencies itself which is by
+# cloning remote git repositories. Dependant 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:-0}" in
+	0|1|2|3|4|5)
+		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
+		;;
+	6)
+		;;
+	*)
+		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
+		;;
+esac
+
+EXPORT_FUNCTIONS src_prepare src_compile src_install
+
+RDEPEND="dev-lang/erlang"
+DEPEND="${RDEPEND}
+	dev-util/rebar
+	>=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>
+# @RETURN: full path with EPREFIX to a Erlang package/project on success,
+# code 1 when dependency is not found and code 2 if multiple versions of
+# dependency are 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: erebar
+# @USAGE: <targets>
+# @DESCRIPTION:
+# Run rebar with verbose flag. Die on failure.
+erebar() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	(( $# > 0 )) || die "erebar: at least one target is required"
+
+	local -x ERL_LIBS="${EPREFIX}$(get_erl_libs)"
+	rebar -v skip_deps=true "$@" || die "rebar $@ failed"
+}
+
+# @FUNCTION: rebar_fix_include_path
+# @USAGE: <project_name>
+# @DESCRIPTION:
+# Fix path in rebar.config to 'include' directory of dependant project/package,
+# so it points to installation in system Erlang lib rather than relative 'deps'
+# directory.
+#
+# The function dies on failure.
+rebar_fix_include_path() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local pn="$1"
+	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
+# @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.
+#
+# The function dies on failure.
+rebar_remove_deps() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	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 in 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'.
+rebar_src_prepare() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	default
+	rebar_set_vsn
+	[[ -f rebar.config ]] && rebar_remove_deps
+}
+
+# @FUNCTION: rebar_src_configure
+# @DESCRIPTION:
+# Configure with ERL_LIBS set.
+rebar_src_configure() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local -x ERL_LIBS="${EPREFIX}$(get_erl_libs)"
+	default
+}
+
+# @FUNCTION: rebar_src_compile
+# @DESCRIPTION:
+# Compile project with rebar.
+rebar_src_compile() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	erebar compile
+}
+
+# @FUNCTION: rebar_src_install
+# @DESCRIPTION:
+# Install BEAM files, include headers, executables and native libraries.
+# Install standard docs like README or defined in DOCS variable.
+#
+# Function expects that project conforms to Erlang/OTP structure.
+rebar_src_install() {
+	debug-print-function ${FUNCNAME} "${@}"
+
+	local bin
+	local dest="$(get_erl_libs)/${P}"
+
+	insinto "${dest}"
+	doins -r ebin
+	[[ -d include ]] && doins -r include
+	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done
+
+	if [[ -d priv ]]; then
+		cp -pR priv "${ED}${dest}/" || die "failed to install priv/"
+	fi
+
+	einstalldocs
+}
-- 
2.8.2



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

* [gentoo-dev] [PATCH 2/2] Add tests for rebar.eclass
  2016-05-21 23:19 ` aidecoe
@ 2016-05-21 23:22   ` aidecoe
  2016-05-22 21:14   ` [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar Michał Górny
  1 sibling, 0 replies; 14+ messages in thread
From: aidecoe @ 2016-05-21 23:22 UTC (permalink / raw
  To: gentoo-dev; +Cc: Amadeusz Żołnowski

From: Amadeusz Żołnowski <aidecoe@gentoo.org>

---
 eclass/tests/rebar_fix_include_path.sh | 159 +++++++++++++++++++++++++++++++++
 eclass/tests/rebar_remove_deps.sh      |  99 ++++++++++++++++++++
 eclass/tests/rebar_set_vsn.sh          | 115 ++++++++++++++++++++++++
 3 files changed, 373 insertions(+)
 create mode 100755 eclass/tests/rebar_fix_include_path.sh
 create mode 100755 eclass/tests/rebar_remove_deps.sh
 create mode 100755 eclass/tests/rebar_set_vsn.sh

diff --git a/eclass/tests/rebar_fix_include_path.sh b/eclass/tests/rebar_fix_include_path.sh
new file mode 100755
index 0000000..9047f8d
--- /dev/null
+++ b/eclass/tests/rebar_fix_include_path.sh
@@ -0,0 +1,159 @@
+#!/bin/bash
+# Copyright 1999-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+source tests-common.sh
+
+EAPI=6
+
+inherit rebar
+
+EPREFIX="${tmpdir}/fakeroot"
+S="${WORKDIR}/${P}"
+
+setup() {
+	mkdir -p "${S}" || die
+
+	for pkg in foo-0.1.0 bar-0.1.0; do
+		mkdir -p "${EPREFIX}$(get_erl_libs)/${pkg}/include" || die
+	done
+
+	cat <<EOF >"${S}/typical.config" || die
+%%% Comment
+
+{erl_opts, [debug_info, {src_dirs, ["src"]},
+			{i, "include"},
+			{i, "deps/foo/include"},
+			{i, "../foo/include"}]}.
+
+{port_env, [{"CFLAGS", "\$CFLAGS"}, {"LDFLAGS", "\$LDFLAGS"}]}.
+EOF
+
+	cat <<EOF >"${S}/typical.config.expected" || die
+%%% Comment
+
+{erl_opts, [debug_info, {src_dirs, ["src"]},
+			{i, "include"},
+			{i, "${EPREFIX}$(get_erl_libs)/foo-0.1.0/include"},
+			{i, "../foo/include"}]}.
+
+{port_env, [{"CFLAGS", "\$CFLAGS"}, {"LDFLAGS", "\$LDFLAGS"}]}.
+EOF
+
+	cat <<EOF >"${S}/inc_one_line.config" || die
+%%% Comment
+
+{erl_opts, [debug_info, {src_dirs, ["src"]}, {i, "include"}, {i, "deps/foo/include"}, {i, "../foo/include"}]}.
+
+{port_env, [{"CFLAGS", "\$CFLAGS"}, {"LDFLAGS", "\$LDFLAGS"}]}.
+EOF
+
+	cat <<EOF >"${S}/inc_one_line.config.expected" || die
+%%% Comment
+
+{erl_opts, [debug_info, {src_dirs, ["src"]}, {i, "include"}, {i, "${EPREFIX}$(get_erl_libs)/foo-0.1.0/include"}, {i, "../foo/include"}]}.
+
+{port_env, [{"CFLAGS", "\$CFLAGS"}, {"LDFLAGS", "\$LDFLAGS"}]}.
+EOF
+}
+
+test_typical_config() {
+	local diff_rc
+	local unit_rc
+
+	# Prepare
+	cd "${S}" || die
+	cp typical.config rebar.config || die
+
+	# Run unit
+	(rebar_fix_include_path foo)
+	unit_rc=$?
+
+	# Test result
+	diff rebar.config typical.config.expected
+	diff_rc=$?
+
+	[[ ${unit_rc}${diff_rc} = 00 ]]
+}
+
+test_multiple_versions() {
+	local diff_rc
+	local unit_rc
+
+	# Prepare
+	cd "${S}" || die
+	cp typical.config rebar.config || die
+	mkdir -p "${EPREFIX}$(get_erl_libs)/foo-1.0.0/include" || die
+
+	# Run unit
+	(rebar_fix_include_path foo 2>/dev/null)
+	unit_rc=$?
+
+	# Test result
+	diff rebar.config typical.config
+	diff_rc=$?
+
+	# Clean up
+	rm -r "${EPREFIX}$(get_erl_libs)/foo-1.0.0" || die
+
+	[[ ${unit_rc}${diff_rc} = 10 ]]
+}
+
+test_not_found() {
+	local diff_rc
+	local unit_rc
+
+	# Prepare
+	cd "${S}" || die
+	cp typical.config rebar.config || die
+
+	# Run unit
+	(rebar_fix_include_path fo 2>/dev/null)
+	unit_rc=$?
+
+	# Test result
+	diff rebar.config typical.config
+	diff_rc=$?
+
+	[[ ${unit_rc}${diff_rc} = 10 ]]
+}
+
+test_includes_in_one_line() {
+	local diff_rc
+	local unit_rc
+
+	# Prepare
+	cd "${S}" || die
+	cp inc_one_line.config rebar.config || die
+
+	# Run unit
+	(rebar_fix_include_path foo)
+	unit_rc=$?
+
+	# Test result
+	diff rebar.config inc_one_line.config.expected
+	diff_rc=$?
+
+	[[ ${unit_rc}${diff_rc} = 00 ]]
+}
+
+setup
+
+tbegin "rebar_fix_include_path deals with typical config"
+test_typical_config
+tend $?
+
+tbegin "rebar_fix_include_path fails on multiple versions of dependency"
+test_multiple_versions
+tend $?
+
+tbegin "rebar_fix_include_path fails if dependency is not found"
+test_not_found
+tend $?
+
+tbegin "rebar_fix_include_path deals with all includes in one line"
+test_includes_in_one_line
+tend $?
+
+texit
diff --git a/eclass/tests/rebar_remove_deps.sh b/eclass/tests/rebar_remove_deps.sh
new file mode 100755
index 0000000..05207a7
--- /dev/null
+++ b/eclass/tests/rebar_remove_deps.sh
@@ -0,0 +1,99 @@
+#!/bin/bash
+# Copyright 1999-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+source tests-common.sh
+
+EAPI=6
+
+inherit rebar
+
+EPREFIX="${tmpdir}/fakeroot"
+S="${WORKDIR}/${P}"
+
+setup() {
+	mkdir -p "${S}" || die
+
+	cat <<EOF >"${S}/rebar.config.expected" || die
+%%% Comment
+
+{port_specs, [{"priv/lib/esip_drv.so", ["c_src/esip_codec.c"]}]}.
+
+{deps, []}.
+
+{clean_files, ["c_src/esip_codec.gcda", "c_src/esip_codec.gcno"]}.
+EOF
+
+	cat <<EOF >"${S}/typical.config" || die
+%%% Comment
+
+{port_specs, [{"priv/lib/esip_drv.so", ["c_src/esip_codec.c"]}]}.
+
+{deps, [{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.3"}}},
+	{fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.3"}}},
+	{p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.3"}}}]}.
+
+{clean_files, ["c_src/esip_codec.gcda", "c_src/esip_codec.gcno"]}.
+EOF
+
+	cat <<EOF >"${S}/deps_one_line.config" || die
+%%% Comment
+
+{port_specs, [{"priv/lib/esip_drv.so", ["c_src/esip_codec.c"]}]}.
+
+{deps, [{stun, ".*", {git, "https://github.com/processone/stun", {tag, "1.0.3"}}}, {fast_tls, ".*", {git, "https://github.com/processone/fast_tls", {tag, "1.0.3"}}}, {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.3"}}}]}.
+
+{clean_files, ["c_src/esip_codec.gcda", "c_src/esip_codec.gcno"]}.
+EOF
+}
+
+test_typical_config() {
+	local diff_rc
+	local unit_rc
+
+	# Prepare
+	cd "${S}" || die
+	cp typical.config rebar.config || die
+
+	# Run unit
+	(rebar_remove_deps)
+	unit_rc=$?
+
+	# Test result
+	diff rebar.config rebar.config.expected
+	diff_rc=$?
+
+	[[ ${unit_rc}${diff_rc} = 00 ]]
+}
+
+test_deps_in_one_line() {
+	local diff_rc
+	local unit_rc
+
+	# Prepare
+	cd "${S}" || die
+	cp deps_one_line.config rebar.config || die
+
+	# Run unit
+	(rebar_remove_deps)
+	unit_rc=$?
+
+	# Test result
+	diff rebar.config rebar.config.expected
+	diff_rc=$?
+
+	[[ ${unit_rc}${diff_rc} = 00 ]]
+}
+
+setup
+
+tbegin "rebar_remove_deps deals with typical config"
+test_typical_config
+tend $?
+
+tbegin "rebar_remove_deps deals with all deps in one line"
+test_deps_in_one_line
+tend $?
+
+texit
diff --git a/eclass/tests/rebar_set_vsn.sh b/eclass/tests/rebar_set_vsn.sh
new file mode 100755
index 0000000..2a9f5bc
--- /dev/null
+++ b/eclass/tests/rebar_set_vsn.sh
@@ -0,0 +1,115 @@
+#!/bin/bash
+# Copyright 1999-2016 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# $Id$
+
+source tests-common.sh
+
+EAPI=6
+
+inherit rebar
+
+EPREFIX="${tmpdir}/fakeroot"
+S="${WORKDIR}/${P}"
+
+setup() {
+	mkdir -p "${S}/src" || die
+
+	cat <<EOF >"${S}/app.src.expected" || die
+%%% Comment
+
+{application, esip,
+ [{description, "ProcessOne SIP server component in Erlang"},
+  {vsn, "0"},
+  {modules, []},
+  {registered, []},
+EOF
+
+	cat <<EOF >"${S}/app.src" || die
+%%% Comment
+
+{application, esip,
+ [{description, "ProcessOne SIP server component in Erlang"},
+  {vsn, git},
+  {modules, []},
+  {registered, []},
+EOF
+}
+
+test_typical_app_src() {
+	local diff_rc
+	local unit_rc
+
+	# Prepare
+	cd "${S}" || die
+	cp app.src "src/${PN}.app.src" || die
+
+	# Run unit
+	(rebar_set_vsn)
+	unit_rc=$?
+
+	# Test result
+	diff "src/${PN}.app.src" app.src.expected
+	diff_rc=$?
+
+	[[ ${unit_rc}${diff_rc} = 00 ]]
+}
+
+test_app_src_missing() {
+	local unit_rc
+
+	# Prepare
+	cd "${S}" || die
+	rm -f "src/${PN}.app.src" || die
+
+	# Run unit
+	(rebar_set_vsn 2>/dev/null)
+	unit_rc=$?
+
+	[[ ${unit_rc} = 1 ]]
+}
+
+test_set_custom_version() {
+	local diff_rc
+	local unit_rc
+
+	# Prepare
+	cd "${S}" || die
+	cp app.src "src/${PN}.app.src" || die
+	cat <<EOF >"${S}/custom_app.src.expected" || die
+%%% Comment
+
+{application, esip,
+ [{description, "ProcessOne SIP server component in Erlang"},
+  {vsn, "1.2.3"},
+  {modules, []},
+  {registered, []},
+EOF
+
+	# Run unit
+	(rebar_set_vsn 1.2.3)
+	unit_rc=$?
+
+	# Test result
+	diff "src/${PN}.app.src" custom_app.src.expected
+	diff_rc=$?
+
+	[[ ${unit_rc}${diff_rc} = 00 ]]
+}
+
+
+setup
+
+tbegin "rebar_set_vsn deals with typical app.src"
+test_typical_app_src
+tend $?
+
+tbegin "rebar_set_vsn fails when app.src is missing"
+test_app_src_missing
+tend $?
+
+tbegin "rebar_set_vsn sets custom version in app.src"
+test_set_custom_version
+tend $?
+
+texit
-- 
2.8.2



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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-21 23:19 ` aidecoe
  2016-05-21 23:22   ` [gentoo-dev] [PATCH 2/2] Add tests for rebar.eclass aidecoe
@ 2016-05-22 21:14   ` Michał Górny
  2016-05-22 22:07     ` Amadeusz Żołnowski
  1 sibling, 1 reply; 14+ messages in thread
From: Michał Górny @ 2016-05-22 21:14 UTC (permalink / raw
  To: aidecoe; +Cc: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 7772 bytes --]

On Sun, 22 May 2016 00:19:49 +0100
aidecoe@gentoo.org wrote:

> From: Amadeusz Żołnowski <aidecoe@gentoo.org>
> 
> It is an eclass providing functions to build Erlang/OTP projects using
> dev-util/rebar. All packages in upcoming category dev-erlang are going
> to use this eclass.
> ---
>  eclass/rebar.eclass | 223 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 223 insertions(+)
>  create mode 100644 eclass/rebar.eclass
> 
> diff --git a/eclass/rebar.eclass b/eclass/rebar.eclass
> new file mode 100644
> index 0000000..1a4eaba
> --- /dev/null
> +++ b/eclass/rebar.eclass
> @@ -0,0 +1,223 @@
> +# Copyright 1999-2016 Gentoo Foundation
> +# Distributed under the terms of the GNU General Public License v2
> +# $Id$
> +
> +# @ECLASS: rebar.eclass
> +# @MAINTAINER:
> +# Amadeusz Żołnowski <aidecoe@gentoo.org>
> +# @AUTHOR:
> +# Amadeusz Żołnowski <aidecoe@gentoo.org>
> +# @BLURB: Build Erlang/OTP projects using dev-util/rebar.
> +# @DESCRIPTION:
> +# An eclass providing functions to build Erlang/OTP projects using
> +# dev-util/rebar.
> +#
> +# rebar is a tool which tries to resolve dependencies itself which is by
> +# cloning remote git repositories. Dependant 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:-0}" in
> +	0|1|2|3|4|5)
> +		die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
> +		;;
> +	6)
> +		;;
> +	*)
> +		die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
> +		;;
> +esac
> +
> +EXPORT_FUNCTIONS src_prepare src_compile src_install
> +
> +RDEPEND="dev-lang/erlang"
> +DEPEND="${RDEPEND}
> +	dev-util/rebar
> +	>=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>
> +# @RETURN: full path with EPREFIX to a Erlang package/project on success,
> +# code 1 when dependency is not found and code 2 if multiple versions of
> +# dependency are 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: erebar
> +# @USAGE: <targets>
> +# @DESCRIPTION:
> +# Run rebar with verbose flag. Die on failure.
> +erebar() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	(( $# > 0 )) || die "erebar: at least one target is required"
> +
> +	local -x ERL_LIBS="${EPREFIX}$(get_erl_libs)"
> +	rebar -v skip_deps=true "$@" || die "rebar $@ failed"

Maybe 'die -n', for consistency with emake?

> +}
> +
> +# @FUNCTION: rebar_fix_include_path
> +# @USAGE: <project_name>
> +# @DESCRIPTION:
> +# Fix path in rebar.config to 'include' directory of dependant project/package,
> +# so it points to installation in system Erlang lib rather than relative 'deps'
> +# directory.
> +#
> +# The function dies on failure.
> +rebar_fix_include_path() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	local pn="$1"
> +	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
> +# @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.
> +#
> +# The function dies on failure.
> +rebar_remove_deps() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	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 in compiling dependencies. Set version in project

I think this sentence is incorrect.

> +# description file if it's not set.
> +#
> +# Existence of rebar.config is optional, but file description file must exist
> +# at 'src/${PN}.app.src'.
> +rebar_src_prepare() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	default
> +	rebar_set_vsn
> +	[[ -f rebar.config ]] && rebar_remove_deps
> +}
> +
> +# @FUNCTION: rebar_src_configure
> +# @DESCRIPTION:
> +# Configure with ERL_LIBS set.
> +rebar_src_configure() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	local -x ERL_LIBS="${EPREFIX}$(get_erl_libs)"
> +	default
> +}
> +
> +# @FUNCTION: rebar_src_compile
> +# @DESCRIPTION:
> +# Compile project with rebar.
> +rebar_src_compile() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	erebar compile
> +}
> +
> +# @FUNCTION: rebar_src_install
> +# @DESCRIPTION:
> +# Install BEAM files, include headers, executables and native libraries.
> +# Install standard docs like README or defined in DOCS variable.
> +#
> +# Function expects that project conforms to Erlang/OTP structure.
> +rebar_src_install() {
> +	debug-print-function ${FUNCNAME} "${@}"
> +
> +	local bin
> +	local dest="$(get_erl_libs)/${P}"
> +
> +	insinto "${dest}"
> +	doins -r ebin
> +	[[ -d include ]] && doins -r include
> +	[[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done
> +
> +	if [[ -d priv ]]; then
> +		cp -pR priv "${ED}${dest}/" || die "failed to install priv/"
> +	fi
> +
> +	einstalldocs
> +}

I think I have no further comments, so the two things above considered,
looks good to go.

-- 
Best regards,
Michał Górny
<http://dev.gentoo.org/~mgorny/>

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 949 bytes --]

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

* Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
  2016-05-22 21:14   ` [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar Michał Górny
@ 2016-05-22 22:07     ` Amadeusz Żołnowski
  0 siblings, 0 replies; 14+ messages in thread
From: Amadeusz Żołnowski @ 2016-05-22 22:07 UTC (permalink / raw
  To: Michał Górny; +Cc: gentoo-dev

[-- Attachment #1: Type: text/plain, Size: 967 bytes --]

Michał Górny <mgorny@gentoo.org> writes:
>> +# @FUNCTION: erebar
>> +# @USAGE: <targets>
>> +# @DESCRIPTION:
>> +# Run rebar with verbose flag. Die on failure.
>> +erebar() {
>> +	debug-print-function ${FUNCNAME} "${@}"
>> +
>> +	(( $# > 0 )) || die "erebar: at least one target is required"
>> +
>> +	local -x ERL_LIBS="${EPREFIX}$(get_erl_libs)"
>> +	rebar -v skip_deps=true "$@" || die "rebar $@ failed"
>
> Maybe 'die -n', for consistency with emake?

Yes, just for consitency...

>> +# @FUNCTION: rebar_src_prepare
>> +# @DESCRIPTION:
>> +# Prevent rebar from fetching in compiling dependencies. Set version in project
>
> I think this sentence is incorrect.

Yes, "in" -> "and". Thanks for catching this!

> I think I have no further comments, so the two things above
> considered, looks good to go.

Thank you for review!

I have pushed eclass along with tests. Feel free to comment on tests
later.

-- Amadeusz Żołnowski

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 950 bytes --]

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

end of thread, other threads:[~2016-05-22 22:08 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-05-18 22:35 [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar aidecoe
2016-05-18 23:26 ` Peter Stuge
2016-05-20 23:09   ` Amadeusz Żołnowski
2016-05-19  4:39 ` Michał Górny
2016-05-20 23:06   ` Amadeusz Żołnowski
2016-05-21  7:00     ` Michał Górny
2016-05-21  8:35       ` Amadeusz Żołnowski
2016-05-21 13:26 ` aidecoe
2016-05-21 20:48   ` Michał Górny
2016-05-21 22:11     ` Amadeusz Żołnowski
2016-05-21 23:19 ` aidecoe
2016-05-21 23:22   ` [gentoo-dev] [PATCH 2/2] Add tests for rebar.eclass aidecoe
2016-05-22 21:14   ` [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar Michał Górny
2016-05-22 22:07     ` Amadeusz Żołnowski

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