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

Contents of /eclass/multibuild.eclass

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.17 - (show annotations) (download)
Tue Apr 15 15:54:13 2014 UTC (4 months, 2 weeks ago) by mgorny
Branch: MAIN
Changes since 1.16: +23 -13 lines
multibuild_merge_root: re-introduce userland_BSD tar fallback, bug #507626.

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

  ViewVC Help
Powered by ViewVC 1.1.20