Gentoo Archives: gentoo-dev

From: Georgy Yakovlev <gyakovlev@g.o>
To: gentoo-dev@l.g.o
Cc: Georgy Yakovlev <gyakovlev@g.o>
Subject: [gentoo-dev] [PATCH 2/2] cargo.eclass: make CRATES an eclass variable
Date: Fri, 02 Jul 2021 00:51:51
Message-Id: 20210702005107.3582488-2-gyakovlev@gentoo.org
In Reply to: [gentoo-dev] [PATCH 1/2] cargo.eclass: support EAPI=8, misc changes by Georgy Yakovlev
1 it's needed to be present in all ebuilds for
2 crate auditing tools to work properly.
3
4 Signed-off-by: Georgy Yakovlev <gyakovlev@g.o>
5 ---
6 eclass/cargo.eclass | 17 +++++++++++++++++
7 1 file changed, 17 insertions(+)
8
9 diff --git a/eclass/cargo.eclass b/eclass/cargo.eclass
10 index 9923b1c9deb2..50237d302ce6 100644
11 --- a/eclass/cargo.eclass
12 +++ b/eclass/cargo.eclass
13 @@ -1,409 +1,426 @@
14 # Copyright 1999-2021 Gentoo Authors
15 # Distributed under the terms of the GNU General Public License v2
16
17 # @ECLASS: cargo.eclass
18 # @MAINTAINER:
19 # rust@g.o
20 # @AUTHOR:
21 # Doug Goldstein <cardoe@g.o>
22 # Georgy Yakovlev <gyakovlev@×××××××.org>
23 # @SUPPORTED_EAPIS: 7 8
24 # @BLURB: common functions and variables for cargo builds
25
26 if [[ -z ${_CARGO_ECLASS} ]]; then
27 _CARGO_ECLASS=1
28
29 # check and document RUST_DEPEND and options we need below in case conditions.
30 # https://github.com/rust-lang/cargo/blob/master/CHANGELOG.md
31 RUST_DEPEND="virtual/rust"
32
33 case "${EAPI:-0}" in
34 0|1|2|3|4|5|6)
35 die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
36 ;;
37 7)
38 # 1.37 added 'cargo vendor' subcommand and net.offline config knob
39 RUST_DEPEND=">=virtual/rust-1.37.0"
40 ;;
41
42 8)
43 # 1.39 added --workspace
44 # 1.46 added --target dir
45 # 1.48 added term.progress config option
46 # 1.51 added split-debuginfo profile option
47 # 1.52 may need setting RUSTC_BOOTSTRAP envvar for some crates
48 # 1.53 added cargo update --offline, can be used to update vulnerable crates from pre-fetched registry without editing toml
49 RUST_DEPEND=">=virtual/rust-1.53"
50 ;;
51 *)
52 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
53 ;;
54 esac
55
56 inherit multiprocessing toolchain-funcs
57
58 if [[ ! ${CARGO_OPTIONAL} ]]; then
59 BDEPEND="${RUST_DEPEND}"
60 EXPORT_FUNCTIONS src_unpack src_configure src_compile src_install src_test
61 fi
62
63 IUSE="${IUSE} debug"
64
65 ECARGO_HOME="${WORKDIR}/cargo_home"
66 ECARGO_VENDOR="${ECARGO_HOME}/gentoo"
67
68 +# @ECLASS-VARIABLE: CRATES
69 +# @DEFAULT_UNSET
70 +# @DESCRIPTION:
71 +# bash string containing all crates package wants to download
72 +# used by cargo_crate_uris()
73 +# Example:
74 +# @CODE
75 +# CRATES="
76 +# metal-1.2.3
77 +# bar-4.5.6
78 +# iron_oxide-0.0.1
79 +# "
80 +# inherit cargo
81 +# ...
82 +# SRC_URI="$(cargo_crate_uris ${CRATES})"
83 +# @CODE
84 +
85 # @ECLASS-VARIABLE: CARGO_OPTIONAL
86 # @DEFAULT_UNSET
87 # @PRE_INHERIT
88 # @DESCRIPTION:
89 # If set to a non-null value, before inherit cargo part of the ebuild will
90 # be considered optional. No dependencies will be added and no phase
91 # functions will be exported.
92 #
93 # If you enable CARGO_OPTIONAL, you have to set BDEPEND on virtual/rust
94 # for your package and call at least cargo_gen_config manually before using
95 # other src_ functions of this eclass.
96 # note that cargo_gen_config is automatically called by cargo_src_unpack.
97
98 # @ECLASS_VARIABLE: myfeatures
99 # @DEFAULT_UNSET
100 # @DESCRIPTION:
101 # Optional cargo features defined as bash array.
102 # Should be defined before calling cargo_src_configure().
103 #
104 # Example package that has x11 and wayland as features, and disables default.
105 # @CODE
106 # src_configure() {
107 # local myfeatures=(
108 # $(usex X x11 '')
109 # $(usev wayland)
110 # )
111 # cargo_src_configure --no-default-features
112 # }
113 # @CODE
114
115 # @ECLASS-VARIABLE: ECARGO_REGISTRY_DIR
116 # @USER_VARIABLE
117 # @DEFAULT_UNSET
118 # @DESCRIPTION:
119 # Storage directory for cargo registry.
120 # Used by cargo_live_src_unpack to cache downloads.
121 # This is intended to be set by users.
122 # Ebuilds must not set it.
123 #
124 # Defaults to "${DISTDIR}/cargo-registry" it not set.
125
126 # @ECLASS-VARIABLE: ECARGO_OFFLINE
127 # @USER_VARIABLE
128 # @DEFAULT_UNSET
129 # @DESCRIPTION:
130 # If non-empty, this variable prevents online operations in
131 # cargo_live_src_unpack.
132 # Inherits value of EVCS_OFFLINE if not set explicitly.
133
134 # @ECLASS-VARIABLE: EVCS_UMASK
135 # @USER_VARIABLE
136 # @DEFAULT_UNSET
137 # @DESCRIPTION:
138 # Set this variable to a custom umask. This is intended to be set by
139 # users. By setting this to something like 002, it can make life easier
140 # for people who use cargo in a home directory, but are in the portage
141 # group, and then switch over to building with FEATURES=userpriv.
142 # Or vice-versa.
143
144 # @FUNCTION: cargo_crate_uris
145 # @DESCRIPTION:
146 # Generates the URIs to put in SRC_URI to help fetch dependencies.
147 cargo_crate_uris() {
148 local -r regex='^([a-zA-Z0-9_\-]+)-([0-9]+\.[0-9]+\.[0-9]+.*)$'
149 local crate
150 for crate in "$@"; do
151 local name version url
152 [[ $crate =~ $regex ]] || die "Could not parse name and version from crate: $crate"
153 name="${BASH_REMATCH[1]}"
154 version="${BASH_REMATCH[2]}"
155 url="https://crates.io/api/v1/crates/${name}/${version}/download -> ${crate}.crate"
156 echo "${url}"
157 done
158 }
159
160 # @FUNCTION: cargo_gen_config
161 # @DESCRIPTION:
162 # Generate the $CARGO_HOME/config necessary to use our local registry and settings.
163 # Cargo can also be configured through environment variables in addition to the TOML syntax below.
164 # For each configuration key below of the form foo.bar the environment variable CARGO_FOO_BAR
165 # can also be used to define the value.
166 # Environment variables will take precedence over TOML configuration,
167 # and currently only integer, boolean, and string keys are supported.
168 # For example the build.jobs key can also be defined by CARGO_BUILD_JOBS.
169 # Or setting CARGO_TERM_VERBOSE=false in make.conf will make build quieter.
170 cargo_gen_config() {
171 debug-print-function ${FUNCNAME} "$@"
172
173 mkdir -p "${ECARGO_HOME}" || die
174
175 cat > "${ECARGO_HOME}/config" <<- _EOF_ || die "Failed to create cargo config"
176 [source.gentoo]
177 directory = "${ECARGO_VENDOR}"
178
179 [source.crates-io]
180 replace-with = "gentoo"
181 local-registry = "/nonexistant"
182
183 [net]
184 offline = true
185
186 [build]
187 jobs = $(makeopts_jobs)
188 incremental = false
189
190 [term]
191 verbose = true
192 $([[ "${NOCOLOR}" = true || "${NOCOLOR}" = yes ]] && echo "color = 'never'")
193 _EOF_
194
195 export CARGO_HOME="${ECARGO_HOME}"
196 _CARGO_GEN_CONFIG_HAS_RUN=1
197 }
198
199 # @FUNCTION: cargo_src_unpack
200 # @DESCRIPTION:
201 # Unpacks the package and the cargo registry
202 cargo_src_unpack() {
203 debug-print-function ${FUNCNAME} "$@"
204
205 mkdir -p "${ECARGO_VENDOR}" || die
206 mkdir -p "${S}" || die
207
208 local archive shasum pkg
209 for archive in ${A}; do
210 case "${archive}" in
211 *.crate)
212 ebegin "Loading ${archive} into Cargo registry"
213 tar -xf "${DISTDIR}"/${archive} -C "${ECARGO_VENDOR}/" || die
214 # generate sha256sum of the crate itself as cargo needs this
215 shasum=$(sha256sum "${DISTDIR}"/${archive} | cut -d ' ' -f 1)
216 pkg=$(basename ${archive} .crate)
217 cat <<- EOF > ${ECARGO_VENDOR}/${pkg}/.cargo-checksum.json
218 {
219 "package": "${shasum}",
220 "files": {}
221 }
222 EOF
223 # if this is our target package we need it in ${WORKDIR} too
224 # to make ${S} (and handle any revisions too)
225 if [[ ${P} == ${pkg}* ]]; then
226 tar -xf "${DISTDIR}"/${archive} -C "${WORKDIR}" || die
227 fi
228 eend $?
229 ;;
230 *)
231 unpack ${archive}
232 ;;
233 esac
234 done
235
236 cargo_gen_config
237 }
238
239 # @FUNCTION: cargo_live_src_unpack
240 # @DESCRIPTION:
241 # Runs 'cargo fetch' and vendors downloaded crates for offline use, used in live ebuilds
242 cargo_live_src_unpack() {
243 debug-print-function ${FUNCNAME} "$@"
244
245 [[ "${PV}" == *9999* ]] || die "${FUNCNAME} only allowed in live/9999 ebuilds"
246 [[ "${EBUILD_PHASE}" == unpack ]] || die "${FUNCNAME} only allowed in src_unpack"
247
248 mkdir -p "${S}" || die
249 mkdir -p "${ECARGO_VENDOR}" || die
250 mkdir -p "${ECARGO_HOME}" || die
251
252 local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}}
253 : ${ECARGO_REGISTRY_DIR:=${distdir}/cargo-registry}
254
255 local offline="${ECARGO_OFFLINE:-${EVCS_OFFLINE}}"
256
257 if [[ ! -d ${ECARGO_REGISTRY_DIR} && ! ${offline} ]]; then
258 (
259 addwrite "${ECARGO_REGISTRY_DIR}"
260 mkdir -p "${ECARGO_REGISTRY_DIR}"
261 ) || die "Unable to create ${ECARGO_REGISTRY_DIR}"
262 fi
263
264 if [[ ${offline} ]]; then
265 local subdir
266 for subdir in cache index src; do
267 if [[ ! -d ${ECARGO_REGISTRY_DIR}/registry/${subdir} ]]; then
268 eerror "Networking activity has been disabled via ECARGO_OFFLINE or EVCS_OFFLINE"
269 eerror "However, no valid cargo registry available at ${ECARGO_REGISTRY_DIR}"
270 die "Unable to proceed with ECARGO_OFFLINE/EVCS_OFFLINE."
271 fi
272 done
273 fi
274
275 if [[ ${EVCS_UMASK} ]]; then
276 local saved_umask=$(umask)
277 umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}"
278 fi
279
280 pushd "${S}" > /dev/null || die
281
282 # Respect user settings befire cargo_gen_config is called.
283 if [[ ! ${CARGO_TERM_COLOR} ]]; then
284 [[ "${NOCOLOR}" = true || "${NOCOLOR}" = yes ]] && export CARGO_TERM_COLOR=never
285 local unset_color=true
286 fi
287 if [[ ! ${CARGO_TERM_VERBOSE} ]]; then
288 export CARGO_TERM_VERBOSE=true
289 local unset_verbose=true
290 fi
291
292 # Let cargo fetch to system-wide location.
293 # It will keep directory organized by itself.
294 addwrite "${ECARGO_REGISTRY_DIR}"
295 export CARGO_HOME="${ECARGO_REGISTRY_DIR}"
296
297 # Absence of quotes around offline arg is intentional, as cargo bails out if it encounters ''
298 einfo "cargo fetch ${offline:+--offline}"
299 cargo fetch ${offline:+--offline} || die #nowarn
300
301 # Let cargo copy all required crates to "${WORKDIR}" for offline use in later phases.
302 einfo "cargo vendor ${offline:+--offline} ${ECARGO_VENDOR}"
303 cargo vendor ${offline:+--offline} "${ECARGO_VENDOR}" || die #nowarn
304
305 # Users may have git checkouts made by cargo.
306 # While cargo vendors the sources, it still needs git checkout to be present.
307 # Copying full dir is an overkill, so just symlink it.
308 if [[ -d ${ECARGO_REGISTRY_DIR}/git ]]; then
309 ln -sv "${ECARGO_REGISTRY_DIR}/git" "${ECARGO_HOME}/git" || die
310 fi
311
312 popd > /dev/null || die
313
314 # Restore settings if needed.
315 [[ ${unset_color} ]] && unset CARGO_TERM_COLOR
316 [[ ${unset_verbose} ]] && unset CARGO_TERM_VERBOSE
317 if [[ ${saved_umask} ]]; then
318 umask "${saved_umask}" || die
319 fi
320
321 # After following calls, cargo will no longer use ${ECARGO_REGISTRY_DIR} as CARGO_HOME
322 # It will be forced into offline mode to prevent network access.
323 # But since we already vendored crates and symlinked git, it has all it needs to build.
324 unset CARGO_HOME
325 cargo_gen_config
326 }
327
328 # @FUNCTION: cargo_src_configure
329 # @DESCRIPTION:
330 # Configure cargo package features and arguments.
331 # Extra positional arguments supplied to this function
332 # will be passed to cargo in all phases.
333 # Make sure all cargo subcommands support flags passed here.
334 #
335 # Example for package that explicitly builds only 'baz' binary and
336 # enables 'barfeature' and optional 'foo' feature.
337 # will pass '--features barfeature --features foo --bin baz'
338 # in src_{compile,test,install}
339 #
340 # @CODE
341 # src_configure() {
342 # local myfeatures=(
343 # barfeature
344 # $(usev foo)
345 # )
346 # cargo_src_configure --bin baz
347 # }
348 # @CODE
349 #
350 # In some cases crates may need '--no-default-features' option,
351 # as there is no way to disable single feature, except disabling all.
352 # It can be passed directly to cargo_src_configure().
353 cargo_src_configure() {
354 debug-print-function ${FUNCNAME} "$@"
355
356 [[ -z ${myfeatures} ]] && declare -a myfeatures=()
357 local myfeaturestype=$(declare -p myfeatures 2>&-)
358 if [[ "${myfeaturestype}" != "declare -a myfeatures="* ]]; then
359 die "myfeatures must be declared as array"
360 fi
361
362 # transform array from simple feature list
363 # to multiple cargo args:
364 # --features feature1 --features feature2 ...
365 # this format is chosen because 2 other methods of
366 # listing features (space OR comma separated) require
367 # more fiddling with strings we'd like to avoid here.
368 myfeatures=( ${myfeatures[@]/#/--features } )
369
370 readonly ECARGO_ARGS=( ${myfeatures[@]} ${@} ${ECARGO_EXTRA_ARGS} )
371
372 [[ ${ECARGO_ARGS[@]} ]] && einfo "Configured with: ${ECARGO_ARGS[@]}"
373 }
374
375 # @FUNCTION: cargo_src_compile
376 # @DESCRIPTION:
377 # Build the package using cargo build
378 cargo_src_compile() {
379 debug-print-function ${FUNCNAME} "$@"
380
381 [[ ${_CARGO_GEN_CONFIG_HAS_RUN} ]] || \
382 die "FATAL: please call cargo_gen_config before using ${FUNCNAME}"
383
384 tc-export AR CC CXX PKG_CONFIG
385
386 set -- cargo build $(usex debug "" --release) ${ECARGO_ARGS[@]} "$@"
387 einfo "${@}"
388 "${@}" || die "cargo build failed"
389 }
390
391 # @FUNCTION: cargo_src_install
392 # @DESCRIPTION:
393 # Installs the binaries generated by cargo
394 # In come case workspaces need alternative --path parameter
395 # default is '--path ./' if nothing specified.
396 # '--path ./somedir' can be passed directly to cargo_src_install()
397 cargo_src_install() {
398 debug-print-function ${FUNCNAME} "$@"
399
400 [[ ${_CARGO_GEN_CONFIG_HAS_RUN} ]] || \
401 die "FATAL: please call cargo_gen_config before using ${FUNCNAME}"
402
403 set -- cargo install $(has --path ${@} || echo --path ./) \
404 --root "${ED}/usr" \
405 $(usex debug --debug "") \
406 ${ECARGO_ARGS[@]} "$@"
407 einfo "${@}"
408 "${@}" || die "cargo install failed"
409
410 rm -f "${ED}/usr/.crates.toml" || die
411 rm -f "${ED}/usr/.crates2.json" || die
412
413 # it turned out to be non-standard dir, so get rid of it future EAPI
414 # and only run for EAPI=7
415 # https://bugs.gentoo.org/715890
416 case ${EAPI:-0} in
417 7)
418 if [ -d "${S}/man" ]; then
419 doman "${S}/man" || return 0
420 fi
421 ;;
422 esac
423 }
424
425 # @FUNCTION: cargo_src_test
426 # @DESCRIPTION:
427 # Test the package using cargo test
428 cargo_src_test() {
429 debug-print-function ${FUNCNAME} "$@"
430
431 [[ ${_CARGO_GEN_CONFIG_HAS_RUN} ]] || \
432 die "FATAL: please call cargo_gen_config before using ${FUNCNAME}"
433
434 set -- cargo test $(usex debug "" --release) ${ECARGO_ARGS[@]} "$@"
435 einfo "${@}"
436 "${@}" || die "cargo test failed"
437 }
438
439 fi
440 --
441 2.32.0