/[gentoo-x86]/eclass/multibuild.eclass
Gentoo

Contents of /eclass/multibuild.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.18 - (show annotations) (download)
Sat May 10 21:36:49 2014 UTC (4 months, 1 week ago) by mgorny
Branch: MAIN
CVS Tags: HEAD
Changes since 1.17: +1 -3 lines
Remove the coreutils dependency since the old copying code has been replaced by a more portable function. Bug #509984.

1 # Copyright 1999-2014 Gentoo Foundation
2 # Distributed under the terms of the GNU General Public License v2
3 # $Header: /var/cvsroot/gentoo-x86/eclass/multibuild.eclass,v 1.17 2014/04/15 15:54:13 mgorny Exp $
4
5 # @ECLASS: multibuild
6 # @MAINTAINER:
7 # Michał Górny <mgorny@gentoo.org>
8 # @AUTHOR:
9 # Author: Michał Górny <mgorny@gentoo.org>
10 # @BLURB: A generic eclass for building multiple variants of packages.
11 # @DESCRIPTION:
12 # The multibuild eclass aims to provide a generic framework for building
13 # multiple 'variants' of a package (e.g. multilib, Python
14 # implementations).
15
16 case "${EAPI:-0}" in
17 0|1|2|3)
18 die "Unsupported EAPI=${EAPI:-0} (too old) for ${ECLASS}"
19 ;;
20 4|5)
21 ;;
22 *)
23 die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}"
24 ;;
25 esac
26
27 if [[ ! ${_MULTIBUILD} ]]; then
28
29 inherit multiprocessing
30
31 # @ECLASS-VARIABLE: MULTIBUILD_VARIANTS
32 # @DESCRIPTION:
33 # An array specifying all enabled variants which multibuild_foreach*
34 # can execute the process for.
35 #
36 # In ebuild, it can be set in global scope. Eclasses should set it
37 # locally in function scope to support nesting properly.
38 #
39 # Example:
40 # @CODE
41 # python_foreach_impl() {
42 # local MULTIBUILD_VARIANTS=( python{2_5,2_6,2_7} ... )
43 # multibuild_foreach_variant python_compile
44 # }
45 # @CODE
46
47 # @ECLASS-VARIABLE: MULTIBUILD_VARIANT
48 # @DESCRIPTION:
49 # The current variant which the function was executed for.
50 #
51 # Example value:
52 # @CODE
53 # python2_6
54 # @CODE
55
56 # @ECLASS-VARIABLE: MULTIBUILD_ID
57 # @DESCRIPTION:
58 # The unique identifier for a multibuild run. In a simple run, it is
59 # equal to MULTIBUILD_VARIANT. In a nested multibuild environment, it
60 # contains the complete selection tree.
61 #
62 # It can be used to create variant-unique directories and files.
63 #
64 # Example value:
65 # @CODE
66 # amd64-double
67 # @CODE
68
69 # @ECLASS-VARIABLE: BUILD_DIR
70 # @DESCRIPTION:
71 # The current build directory. In global scope, it is supposed
72 # to contain an 'initial' build directory. If unset, ${S} is used.
73 #
74 # multibuild_foreach_variant() sets BUILD_DIR locally
75 # to variant-specific build directories based on the initial value
76 # of BUILD_DIR.
77 #
78 # Example value:
79 # @CODE
80 # ${WORKDIR}/foo-1.3-python2_6
81 # @CODE
82
83 # @FUNCTION: multibuild_foreach_variant
84 # @USAGE: [<argv>...]
85 # @DESCRIPTION:
86 # Run the passed command repeatedly for each of the enabled package
87 # variants.
88 #
89 # Each of the runs will have variant-specific BUILD_DIR set, and output
90 # teed to a separate log in ${T}.
91 #
92 # The function returns 0 if all commands return 0, or the first non-zero
93 # exit status otherwise. However, it performs all the invocations
94 # nevertheless. It is preferred to call 'die' inside of the passed
95 # function.
96 multibuild_foreach_variant() {
97 debug-print-function ${FUNCNAME} "${@}"
98
99 [[ ${MULTIBUILD_VARIANTS} ]] \
100 || die "MULTIBUILD_VARIANTS need to be set"
101
102 local bdir=${BUILD_DIR:-${S}}
103
104 # Avoid writing outside WORKDIR if S=${WORKDIR}.
105 [[ ${bdir%%/} == ${WORKDIR%%/} ]] && bdir=${WORKDIR}/build
106
107 local prev_id=${MULTIBUILD_ID:+${MULTIBUILD_ID}-}
108 local ret=0 lret=0 v
109
110 debug-print "${FUNCNAME}: initial build_dir = ${bdir}"
111
112 for v in "${MULTIBUILD_VARIANTS[@]}"; do
113 local MULTIBUILD_VARIANT=${v}
114 local MULTIBUILD_ID=${prev_id}${v}
115 local BUILD_DIR=${bdir%%/}-${v}
116
117 _multibuild_run() {
118 # find the first non-private command
119 local i=1
120 while [[ ${!i} == _* ]]; do
121 (( i += 1 ))
122 done
123
124 [[ ${i} -le ${#} ]] && einfo "${v}: running ${@:${i}}"
125 "${@}"
126 }
127
128 _multibuild_run "${@}" \
129 > >(exec tee -a "${T}/build-${MULTIBUILD_ID}.log") 2>&1
130 lret=${?}
131 done
132 [[ ${ret} -eq 0 && ${lret} -ne 0 ]] && ret=${lret}
133
134 return ${ret}
135 }
136
137 # @FUNCTION: multibuild_parallel_foreach_variant
138 # @USAGE: [<argv>...]
139 # @DESCRIPTION:
140 # Run the passed command repeatedly for each of the enabled package
141 # variants alike multibuild_foreach_variant. Multiple invocations of the command
142 # will be performed in parallel, up to MULTIBUILD_JOBS tasks.
143 #
144 # The function returns 0 if all commands return 0, or the first non-zero
145 # exit status otherwise. However, it performs all the invocations
146 # nevertheless. It is preferred to call 'die' inside of the passed
147 # function.
148 multibuild_parallel_foreach_variant() {
149 debug-print-function ${FUNCNAME} "${@}"
150
151 local ret lret
152
153 _multibuild_parallel() {
154 (
155 multijob_child_init
156 "${@}"
157 ) &
158 multijob_post_fork
159 }
160
161 local opts
162 if [[ ${MULTIBUILD_JOBS} ]]; then
163 opts=-j${MULTIBUILD_JOBS}
164 else
165 opts=${MAKEOPTS}
166 fi
167
168 multijob_init "${opts}"
169 multibuild_foreach_variant _multibuild_parallel "${@}"
170 ret=${?}
171 multijob_finish
172 lret=${?}
173
174 [[ ${ret} -eq 0 ]] && ret=${lret}
175 return ${ret}
176 }
177
178 # @FUNCTION: multibuild_for_best_variant
179 # @USAGE: [<argv>...]
180 # @DESCRIPTION:
181 # Run the passed command once, for the best of the enabled package
182 # variants.
183 #
184 # The run will have a proper, variant-specificBUILD_DIR set, and output
185 # teed to a separate log in ${T}.
186 #
187 # The function returns command exit status.
188 multibuild_for_best_variant() {
189 debug-print-function ${FUNCNAME} "${@}"
190
191 [[ ${MULTIBUILD_VARIANTS} ]] \
192 || die "MULTIBUILD_VARIANTS need to be set"
193
194 # bash-4.1 can't handle negative subscripts
195 local MULTIBUILD_VARIANTS=(
196 "${MULTIBUILD_VARIANTS[$(( ${#MULTIBUILD_VARIANTS[@]} - 1 ))]}"
197 )
198 multibuild_foreach_variant "${@}"
199 }
200
201 # @FUNCTION: multibuild_copy_sources
202 # @DESCRIPTION:
203 # Create per-variant copies of source tree. The source tree is assumed
204 # to be in ${BUILD_DIR}, or ${S} if the former is unset. The copies will
205 # be placed in directories matching BUILD_DIRs used by
206 # multibuild_foreach().
207 multibuild_copy_sources() {
208 debug-print-function ${FUNCNAME} "${@}"
209
210 local _MULTIBUILD_INITIAL_BUILD_DIR=${BUILD_DIR:-${S}}
211
212 einfo "Will copy sources from ${_MULTIBUILD_INITIAL_BUILD_DIR}"
213
214 local cp_args=()
215 if cp --reflink=auto --version &>/dev/null; then
216 # enable reflinking if possible to make this faster
217 cp_args+=( --reflink=auto )
218 fi
219
220 _multibuild_create_source_copy() {
221 einfo "${MULTIBUILD_VARIANT}: copying to ${BUILD_DIR}"
222 cp -pr "${cp_args[@]}" \
223 "${_MULTIBUILD_INITIAL_BUILD_DIR}" "${BUILD_DIR}" || die
224 }
225
226 multibuild_foreach_variant _multibuild_create_source_copy
227 }
228
229 # @FUNCTION: run_in_build_dir
230 # @USAGE: <argv>...
231 # @DESCRIPTION:
232 # Run the given command in the directory pointed by BUILD_DIR.
233 run_in_build_dir() {
234 debug-print-function ${FUNCNAME} "${@}"
235 local ret
236
237 [[ ${#} -ne 0 ]] || die "${FUNCNAME}: no command specified."
238 [[ ${BUILD_DIR} ]] || die "${FUNCNAME}: BUILD_DIR not set."
239
240 pushd "${BUILD_DIR}" >/dev/null || die
241 "${@}"
242 ret=${?}
243 popd >/dev/null || die
244
245 return ${ret}
246 }
247
248 # @FUNCTION: multibuild_merge_root
249 # @USAGE: <src-root> <dest-root>
250 # @DESCRIPTION:
251 # Merge the directory tree (fake root) from <src-root> to <dest-root>
252 # (the real root). Both directories have to be real, absolute paths
253 # (i.e. including ${D}). Source root will be removed.
254 #
255 # This functions uses locking to support merging during parallel
256 # installs.
257 multibuild_merge_root() {
258 local src=${1}
259 local dest=${2}
260
261 local lockfile=${T}/.multibuild_merge_lock
262 local lockfile_l=${lockfile}.${BASHPID}
263 local ret
264
265 # Lock the install tree for merge. The touch+ln method ensures race
266 # condition-free locking with maximum portability.
267 touch "${lockfile_l}" || die
268 until ln "${lockfile_l}" "${lockfile}" &>/dev/null; do
269 sleep 1
270 done
271 rm "${lockfile_l}" || die
272
273 if use userland_BSD; then
274 # Most of BSD variants fail to copy broken symlinks, #447370
275 # also, they do not support --version
276
277 tar -C "${src}" -f - -c . \
278 | tar -x -f - -C "${dest}"
279 [[ ${PIPESTATUS[*]} == '0 0' ]]
280 ret=${?}
281 else
282 local cp_args=()
283
284 if cp -a --version &>/dev/null; then
285 cp_args+=( -a )
286 else
287 cp_args+=( -P -R -p )
288 fi
289
290 if cp --reflink=auto --version &>/dev/null; then
291 # enable reflinking if possible to make this faster
292 cp_args+=( --reflink=auto )
293 fi
294
295 cp "${cp_args[@]}" "${src}"/. "${dest}"/
296 ret=${?}
297 fi
298
299 # Remove the lock.
300 rm "${lockfile}" || die
301
302 if [[ ${ret} -ne 0 ]]; then
303 die "${MULTIBUILD_VARIANT:-(unknown)}: merging image failed."
304 fi
305
306 rm -rf "${src}"
307 }
308
309 _MULTIBUILD=1
310 fi

  ViewVC Help
Powered by ViewVC 1.1.20