Gentoo Archives: gentoo-dev

From: "Michał Górny" <mgorny@g.o>
To: aidecoe@g.o
Cc: gentoo-dev@l.g.o
Subject: Re: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar
Date: Thu, 19 May 2016 04:39:27
Message-Id: 20160519063909.651a07e8.mgorny@gentoo.org
In Reply to: [gentoo-dev] [PATCH] rebar.eclass: Build Erlang/OTP projects using dev-util/rebar by aidecoe@gentoo.org
1 On Wed, 18 May 2016 23:35:18 +0100
2 aidecoe@g.o wrote:
3
4 > From: Amadeusz Żołnowski <aidecoe@g.o>
5 >
6 > It is an eclass providing functions to build Erlang/OTP projects using
7 > dev-util/rebar. All packages in upcoming category dev-erlang are going
8 > to use this eclass.
9 > ---
10 > eclass/rebar.eclass | 220 ++++++++++++++++++++++++++++++++++++++++++++++++++++
11 > 1 file changed, 220 insertions(+)
12 > create mode 100644 eclass/rebar.eclass
13 >
14 > diff --git a/eclass/rebar.eclass b/eclass/rebar.eclass
15 > new file mode 100644
16 > index 0000000..e1ac52f
17 > --- /dev/null
18 > +++ b/eclass/rebar.eclass
19 > @@ -0,0 +1,220 @@
20 > +# Copyright 1999-2016 Gentoo Foundation
21 > +# Distributed under the terms of the GNU General Public License v2
22 > +# $Id$
23 > +
24 > +# @ECLASS: rebar.eclass
25 > +# @MAINTAINER:
26 > +# Amadeusz Żołnowski <aidecoe@g.o>
27 > +# @AUTHOR:
28 > +# Amadeusz Żołnowski <aidecoe@g.o>
29 > +# @BLURB: Build Erlang/OTP projects using dev-util/rebar.
30 > +# @DESCRIPTION:
31 > +# An eclass providing functions to build Erlang/OTP projects using
32 > +# dev-util/rebar.
33 > +#
34 > +# rebar is a tool which tries to resolve dependencies itself which is by
35 > +# cloning remote git repositories. Dependant projects are usually expected to
36 > +# be in sub-directory 'deps' rather than looking at system Erlang lib
37 > +# directory. Projects relying on rebar usually don't have 'install' make
38 > +# targets. The eclass workarounds some of these problems. It handles
39 > +# installation in a generic way for Erlang/OTP structured projects.
40 > +
41 > +case "${EAPI:-0}" in
42 > + 0|1|2|3|4)
43 > + die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
44 > + ;;
45 > + 5|6)
46 > + ;;
47 > + *)
48 > + die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
49 > + ;;
50 > +esac
51 > +
52 > +[[ ${EAPI} = 5 ]] && inherit eutils
53 > +
54 > +EXPORT_FUNCTIONS src_prepare src_compile src_install
55 > +
56 > +RDEPEND="dev-lang/erlang"
57 > +DEPEND="${RDEPEND}
58 > + dev-util/rebar"
59 > +
60 > +# @FUNCTION: get_erl_libs
61 > +# @RETURN: the path to Erlang lib directory
62 > +# @DESCRIPTION:
63 > +# Get the full path without EPREFIX to Erlang lib directory.
64 > +get_erl_libs() {
65 > + echo "/usr/$(get_libdir)/erlang/lib"
66
67 Missing multilib inherit for EAPI 5.
68
69 > +}
70 > +
71 > +# @VARIABLE: ERL_LIBS
72 > +# @DESCRIPTION:
73 > +# Full path with EPREFIX to Erlang lib directory. Some rebar scripts expect it.
74 > +export ERL_LIBS="${EPREFIX}$(get_erl_libs)"
75
76 I think calling get_libdir in global scope is forbidden. You should
77 really export this somewhere in phase function.
78
79 > +
80 > +# @FUNCTION: _find_dep_version
81
82 Namespace it, please. Just in case.
83
84 > +# @INTERNAL
85 > +# @USAGE: <project_name>
86 > +# @RETURN: full path with EPREFIX to a Erlang package/project
87 > +# @DESCRIPTION:
88 > +# Find a Erlang package/project by name in Erlang lib directory. Project
89 > +# directory is usually suffixed with version. First match to <project_name> or
90 > +# <project_name>-* is returned.
91 > +_find_dep_version() {
92 > + local pn="$1"
93 > + local p
94 > +
95 > + pushd "${EPREFIX}$(get_erl_libs)" >/dev/null
96
97 || die
98
99 > + for p in ${pn} ${pn}-*; do
100 > + if [[ -d ${p} ]]; then
101 > + echo "${p#${pn}-}"
102 > + return 0
103 > + fi
104 > + done
105 > + popd >/dev/null
106
107 || die
108
109 > +
110 > + return 1
111 > +}
112 > +
113 > +# @FUNCTION: eawk
114 > +# @USAGE: <file> <args>
115 > +# @DESCRIPTION:
116 > +# Edit file <file> in place with awk. Pass all arguments following <file> to
117 > +# awk.
118 > +eawk() {
119 > + local f="$1"; shift
120 > + local tmpf="$(emktemp)"
121
122 Missing eutils inherit for EAPI 6.
123
124 > +
125 > + cat "${f}" >"${tmpf}" || return 1
126 > + awk "$@" "${tmpf}" >"${f}"
127 > +}
128 > +
129 > +# @FUNCTION: erebar
130 > +# @USAGE: <target>
131 > +# @DESCRIPTION:
132 > +# Run rebar with verbose flag. Die on failure.
133 > +erebar() {
134 > + debug-print-function ${FUNCNAME} "${@}"
135 > +
136 > + rebar -v skip_deps=true "$1" || die "rebar $1 failed"
137 > +}
138
139 Any reason it doesn't pass all the parameters? This inconsistency with
140 emake etc. could be mildly confusing, esp. that you don't check for
141 wrong argc.
142
143 > +
144 > +# @FUNCTION: rebar_fix_include_path
145 > +# @USAGE: <project_name> [<rebar_config>]
146 > +# @DESCRIPTION:
147 > +# Fix path in rebar.config to 'include' directory of dependant project/package,
148 > +# so it points to installation in system Erlang lib rather than relative 'deps'
149 > +# directory.
150 > +#
151 > +# <rebar_config> is optional. Default is 'rebar.config'.
152
153 Is it likely that you would be passing different values to it? Maybe it
154 would be reasonable to make this an eclass variable.
155
156 > +#
157 > +# The function dies on failure.
158 > +rebar_fix_include_path() {
159 > + debug-print-function ${FUNCNAME} "${@}"
160 > +
161 > + local pn="$1"
162 > + local rebar_config="${2:-rebar.config}"
163 > + local erl_libs="${EPREFIX}$(get_erl_libs)"
164 > + local pv="$(_find_dep_version "${pn}")"
165 > +
166 > + eawk "${rebar_config}" \
167 > + -v erl_libs="${erl_libs}" -v pn="${pn}" -v pv="${pv}" \
168 > + '/^{[[:space:]]*erl_opts[[:space:]]*,/, /}[[:space:]]*\.$/ {
169 > + pattern = "\"(./)?deps/" pn "/include\"";
170 > + if (match($0, "{i,[[:space:]]*" pattern "[[:space:]]*}")) {
171 > + sub(pattern, "\"" erl_libs "/" pn "-" pv "/include\"");
172 > + }
173 > + print $0;
174 > + next;
175 > +}
176 > +1
177 > +' || die "failed to fix include paths in ${rebar_config}"
178
179 I suggest you indent this a bit more since it feels like you start at
180 two tabs and finish at zero.
181
182 > +}
183 > +
184 > +# @FUNCTION: rebar_remove_deps
185 > +# @USAGE: [<rebar_config>]
186 > +# @DESCRIPTION:
187 > +# Remove dependencies list from rebar.config and deceive build rules that any
188 > +# dependencies are already fetched and built. Otherwise rebar tries to fetch
189 > +# dependencies and compile them.
190 > +#
191 > +# <rebar_config> is optional. Default is 'rebar.config'.
192 > +#
193 > +# The function dies on failure.
194 > +rebar_remove_deps() {
195 > + debug-print-function ${FUNCNAME} "${@}"
196 > +
197 > + local rebar_config="${1:-rebar.config}"
198 > +
199 > + mkdir -p "${S}/deps" && :>"${S}/deps/.got" && :>"${S}/deps/.built" || die
200 > + eawk "${rebar_config}" \
201 > + '/^{[[:space:]]*deps[[:space:]]*,/, /}[[:space:]]*\.$/ {
202 > + if ($0 ~ /}[[:space:]]*\.$/) {
203 > + print "{deps, []}.";
204 > + }
205 > + next;
206 > +}
207 > +1
208 > +' || die "failed to remove deps from ${rebar_config}"
209 > +}
210 > +
211 > +# @FUNCTION: rebar_set_vsn
212 > +# @USAGE: [<version>]
213 > +# @DESCRIPTION:
214 > +# Set version in project description file if it's not set.
215 > +#
216 > +# <version> is optional. Default is PV stripped from version suffix.
217 > +#
218 > +# The function dies on failure.
219 > +rebar_set_vsn() {
220 > + debug-print-function ${FUNCNAME} "${@}"
221 > +
222 > + local version="${1:-${PV%_*}}"
223 > +
224 > + sed -e "s/vsn, git/vsn, \"${version}\"/" \
225 > + -i "${S}/src/${PN}.app.src" \
226 > + || die "failed to set version in src/${PN}.app.src"
227 > +}
228 > +
229 > +# @FUNCTION: rebar_src_prepare
230 > +# @DESCRIPTION:
231 > +# Prevent rebar from fetching in compiling dependencies. Set version in project
232 > +# description file if it's not set.
233 > +#
234 > +# Existence of rebar.config is optional, but file description file must exist
235 > +# at 'src/${PN}.app.src'.
236
237 Wouldn't it be reasonable to make this configurable? Of course, it
238 might be better to leave it for a possible future extension when
239 it becomes necessary.
240
241 > +rebar_src_prepare() {
242 > + debug-print-function ${FUNCNAME} "${@}"
243 > +
244 > + rebar_set_vsn
245 > + [[ -f rebar.config ]] && rebar_remove_deps
246 > +}
247
248 You're missing obligatory default call for EAPI 6. You should really
249 test stuff before submitting it.
250
251 > +
252 > +# @FUNCTION: rebar_src_compile
253 > +# @DESCRIPTION:
254 > +# Compile project with rebar.
255 > +rebar_src_compile() {
256 > + debug-print-function ${FUNCNAME} "${@}"
257 > +
258 > + erebar compile
259 > +}
260 > +
261 > +# @FUNCTION: rebar_src_install
262 > +# @DESCRIPTION:
263 > +# Install BEAM files, include headers, executables and native libraries.
264 > +# Install standard docs like README or defined in DOCS variable. Optionally
265
266 Optionally what? It looks like an unfinished sentence.
267
268 > +#
269 > +# Function expects that project conforms to Erlang/OTP structure.
270 > +rebar_src_install() {
271 > + debug-print-function ${FUNCNAME} "${@}"
272 > +
273 > + local bin
274 > + local dest="$(get_erl_libs)/${P}"
275 > +
276 > + insinto "${dest}"
277 > + doins -r ebin
278 > + [[ -d include ]] && doins -r include
279 > + [[ -d bin ]] && for bin in bin/*; do dobin "$bin"; done
280
281 Please don't do inlines like this.
282
283 > + [[ -d priv ]] && cp -pR priv "${ED}${dest}/"
284
285 This is about preserving executable bits, correct?
286
287 > +
288 > + einstalldocs
289 > +}
290
291
292
293 --
294 Best regards,
295 Michał Górny
296 <http://dev.gentoo.org/~mgorny/>

Replies