Whamcloud - gitweb
- landing of b_hd_cleanup_merge to HEAD.
[fs/lustre-release.git] / lustre / scripts / lbuild
1 #!/bin/sh
2
3 TOPDIR=$PWD
4
5 # CVSROOT is inherited from the environment
6 KERNELDIR=
7 LUSTRE=
8 PUBLISH=0
9 RELEASE=0
10 DO_SRC=1
11 TAG=
12 TARGET=
13 TARGET_ARCHS=
14 CONFIGURE_FLAGS=
15 EXTRA_VERSION=
16
17 # from target file
18 KERNEL=
19 SERIES=
20 CONFIG=
21 VERSION=
22
23 RHBUILD=0
24 LINUX26=0
25 SUSEBUILD=0
26
27 BASE_ARCH=
28 BIGMEM_ARCHS=
29 BOOT_ARCHS=
30 JENSEN_ARCHS=
31 SMP_ARCHS=
32 UP_ARCHS=
33
34 DATE=$(date)
35
36 USE_DATESTAMP=1
37 RPMBUILD=
38
39 cleanup()
40 {
41     true
42 }
43
44 fatal()
45 {
46     cleanup
47     [ "$2" ] && echo
48     [ "$2" ] && echo "${0##*/}: $2"
49     exit $1
50 }
51
52 publishing()
53 {
54     (( $PUBLISH )) || return 0
55 }
56
57 is_release()
58 {
59     (( $RELEASE )) || return 0
60 }
61
62 list_targets()
63 {
64     echo -n "Available targets:"
65     for target in $TOPDIR/lustre/kernel_patches/targets/*.target ; do
66         target_file=${target##*/}
67         echo -n " ${target_file%%.target}"
68     done
69     echo
70 }
71
72 usage()
73 {
74     cat <<EOF
75 Usage: ${0##*/} [OPTION]... [-- <lustre configure options>]
76
77   -d CVSROOT
78     Specifies the CVS Root to use when pulling files from CVS.  The
79     environment variable \$CVSROOT is used if this option is not
80     present.
81
82   --extraversion=EXTRAVERSION
83     Text to use for the rpm release and kernel extraversion.
84
85   --kerneldir=KERNELDIR
86     Directory containing Linux source tarballs referenced by target
87     files.
88
89   --lustre=LUSTRE
90     Path to an existing lustre source tarball to use instead of
91     pulling from CVS.
92
93   --nosrc
94     Do not build a .src.rpm, a full kernel patch, or a patched kernel
95     tarball.
96
97   --publish
98     Publish the packages, patches, and tarballs on the ftp server.
99
100   --release
101     Specifies that the files generated do not include timestamps, and
102     that this is an official release.
103
104   --tag=TAG
105     A CVS branch/tag name to build from when pulling from CVS.
106
107   --target=TARGET
108     The name of the target to build.  The available targets are listed
109     below.
110
111   --target-archs=TARGET_ARCHS
112     A (space delimited) list of architectures to build.  By default,
113     all of the archs supported by the TARGET will be built, in
114     addition to a .src.rpm.  This option can limit those, for machines
115     that can only build certain archs or if you only want a certain
116     arch built (for testing, or a one-off kernel).
117
118     Also note that by using a non-"base" arch (eg, i386) only kernels
119     will be built - there will be no lustre-lite-utils package.
120
121   --disable-datestamp
122     Prevents the datestamp flag (-D) from being passed to cvs for 
123     checkouts. This is a workaround for a problem encountered when 
124     using lbuild with tinderbox.
125
126 EOF
127
128 #   list_targets
129
130     fatal "$1" "$2"
131 }
132
133 check_options()
134 {
135     if [ "$LUSTRE" ] ; then
136         [ -r "$LUSTRE" ] || \
137             usage 1 "Could not find Lustre source tarball '$LUSTRE'."
138     else
139         [ "$CVSROOT" ] || \
140             usage 1 "Either specify a CVS Root with -d, or a Lustre source tarball with --lustre."
141         [ "$TAG" ] || \
142             usage 1 "A branch/tag name must be specified with --tag when not building from a tarball."
143     fi
144
145     [ "$KERNELDIR" ] || \
146         usage 1 "A kernel directory must be specified with --kerneldir."
147
148     [ -d "$KERNELDIR" ] || \
149         usage 1 "$KERNELDIR is not a directory."
150
151     if ! (( $RELEASE )) ; then
152         [ "$TAG" ] || \
153             usage 1 "When building a snapshot, a tag name must be used."
154     fi
155
156     TIMESTAMP=$(date -d "$DATE" "+%Y%m%d%H%M")
157
158     [ "$TARGET" ] || usage 1 "A target must be specified with --target."
159 #    TARGET_FILE="$TOPDIR/kernel_patches/targets/$TARGET.target"
160 #    [ -r "$TARGET_FILE" ] || \
161 #       usage 1 "Target '$TARGET' was not found."
162
163     RPMBUILD=$(which rpmbuild 2>/dev/null | head -1)
164     if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
165         RPMBUILD=$(which rpm 2>/dev/null | head -1)
166         if [ ! "$RPMBUILD" -o "$RPMBUILD" == "" ]; then
167             usage 1 "Could not find binary for making rpms (tried rpmbuild and rpm)."
168         fi
169     fi
170 }
171
172 uniqify()
173 {
174     echo $(echo "$*" | xargs -n 1 | sort -u)
175 }
176
177 load_target()
178 {
179     EXTRA_VERSION_save="$EXTRA_VERSION"
180     TARGET_FILE="$TOPDIR/lustre/kernel_patches/targets/$TARGET.target"
181     [ -r "$TARGET_FILE" ] || \
182         fatal 1 "Target $TARGET was not found."
183
184     echo "Loading target config file $TARGET.target..." 
185
186     . "$TARGET_FILE"
187
188     [ "$KERNEL"  ] || fatal 1 "Target $TARGET did not specify a kernel."
189     [ "$SERIES"  ] || fatal 1 "Target $TARGET did not specify a kernel patch series."
190 #    [ "$CONFIG"  ] || fatal 1 "Target $TARGET did not specify a kernel config."
191     [ "$VERSION" ] || fatal 1 "Target $TARGET did not specify a kernel version."
192
193     if [ "$KERNELDIR" ] ; then
194         KERNEL_FILE="$KERNELDIR/$KERNEL"
195         [ -r "$KERNELDIR/$KERNEL" ] || \
196             fatal 1 "Target $TARGET's kernel file $KERNEL not found in kernel directory $KERNELDIR."
197     fi
198
199     SERIES_FILE="$TOPDIR/lustre/kernel_patches/series/$SERIES"
200     [ -r "$SERIES_FILE" ] || \
201         fatal 1 "Target $TARGET's series $SERIES missing from $TOPDIR/lustre/kernel_patches/series."
202
203     CONFIG_FILE="$TOPDIR/lustre/kernel_patches/kernel_configs/$CONFIG"
204     [ -r "$CONFIG_FILE" ] || \
205         fatal 1 "Target $TARGET's config file $CONFIG missing from $TOPDIR/lustre/kernel_patches/kernel_configs/."
206
207     if [ "$EXTRA_VERSION_save" ] ; then
208         EXTRA_VERSION="$EXTRA_VERSION_save"
209     elif ! (( $RELEASE )) ; then
210         EXTRA_VERSION="${EXTRA_VERSION}-${TAG}.${TIMESTAMP}"
211     fi
212     # EXTRA_VERSION=${EXTRA_VERSION//-/_}
213
214     ALL_ARCHS="$BASE_ARCHS $BIGMEM_ARCHS $BOOT_ARCHS $JENSEN_ARCHS $SMP_ARCHS $UP_ARCHS"
215
216     BUILD_ARCHS=
217     for arch in $(uniqify "$ALL_ARCHS") ; do
218         if [ -z "$TARGET_ARCHS" ] || echo "$TARGET_ARCHS" | grep "$arch" >/dev/null 2>/dev/null ; then
219             BUILD_ARCHS="$BUILD_ARCHS $arch"
220         fi
221     done
222     [ "$BUILD_ARCHS" ] || usage 1 "No available target archs to build."
223     echo "Building for: $BUILD_ARCHS"
224 }
225
226 tarflags()
227 {
228     case "$1" in
229         '')
230             fatal 1 "tarflags(): File name argument missing."
231             ;;
232         *.tar.gz)
233             echo 'zxf'
234             ;;
235         *.tar.bz2)
236             echo 'jxf'
237             ;;
238         *)
239             fatal 1 "tarflags(): Unrecognized tar extension in file: $1"
240             ;;
241     esac
242 }
243
244 untar()
245 {
246     echo "Untarring ${1##*/}..."
247     tar $(tarflags "$1") "$1"
248 }
249
250 unpack_lustre()
251 {
252     DIRNAME="lustre-$TAG-$TIMESTAMP"
253     if [ "$LUSTRE" ] ; then
254         untar "$LUSTRE"
255         [ -d lustre ] || ln -sf lustre* lustre
256     else
257         if [ "$USE_DATESTAMP" ]; then
258             DATESTAMP="-D '$DATE'"
259         else
260             DATESTAMP=""
261         fi          
262
263         cvs -d "$CVSROOT" -qz3 co $DATESTAMP -r "$TAG" -d "$DIRNAME" lustre || \
264             fatal 1 "There was an error checking out Lustre from CVS."
265         echo "Creating lustre tarball..."
266         tar zcf "$DIRNAME.tar.gz" "$DIRNAME" \
267             --exclude "CVS" --exclude "*~" --exclude ".cvsignore" || \
268             fatal 1 "Could not create Lustre tarball."
269         LUSTRE="$PWD/$DIRNAME.tar.gz"
270         ln -sf "$DIRNAME" lustre
271     fi
272 }
273
274 unpack_linux()
275 {
276     untar "$KERNEL_FILE"
277     [ -d linux ] || ln -sf linux* linux
278 }
279
280 patch_linux()
281 {
282     FULL_PATCH="$PWD/lustre-kernel-${TARGET}-${EXTRA_VERSION}.patch"
283     [ -f "$FULL_PATCH" ] && rm -f "$FULL_PATCH"
284     pushd linux >/dev/null
285     echo -n "Applying patches:"
286     for patch in $(<"$SERIES_FILE") ; do
287         echo -n " $patch"
288         PATCH_FILE="$TOPDIR/lustre/kernel_patches/patches/$patch"
289         [ -r "$PATCH_FILE" ] || \
290             fatal 1 "Patch $patch does not exist in Lustre tree."
291         cat "$PATCH_FILE" >> "$FULL_PATCH" || \
292             fatal 1 "Error adding patch $patch to full patch."
293         patch -s -p1 < "$PATCH_FILE" || fatal 1 "Error applying patch $patch."
294     done
295     echo
296     popd >/dev/null
297     echo "Full patch has been saved in ${FULL_PATCH##*/}."
298     echo "Replacing .config files..."
299     [ -d linux/configs ] || mkdir linux/configs || \
300         fatal 1 "Error creating configs directory."
301     rm -f linux/configs/*
302     cp -v lustre/kernel_patches/kernel_configs/kernel-${VERSION}-${TARGET}*.config linux/configs/ || \
303        fatal 1 "Error copying in kernel configs."
304 }
305
306 pack_linux()
307 {
308     TARBALL="$(readlink linux)-$EXTRA_VERSION.tar.gz"
309     echo "Creating patched linux tarball $TARBALL..."
310     tar zcf "$TARBALL" "$(readlink linux)" \
311         --exclude "CVS" --exclude ".cvsignore" || \
312         --exclude "*.orig" --exclude "*~" --exclude "*.rej" || \
313         fatal 1 "Error creating patched Linux tarball."
314 }
315
316 clean_linux()
317 {
318     [ -d linux ] || return 0
319     echo "Cleaning linux..."
320     [ -L linux ] && rm -rf $(readlink linux)
321     rm -rf linux
322 }
323
324 prep_build()
325 {
326     # make .spec file
327     sed -e "s/@KERNEL_VERSION@/$VERSION/g" \
328         -e "s/@KERNEL_EXTRA_VERSION@/$EXTRA_VERSION/g" \
329         -e "s^@KERNEL_RELEASE@^${EXTRA_VERSION//-/_}^g" \
330         -e "s/@KERNEL_SOURCE@/$KERNEL/g" \
331         -e "s/@LUSTRE_SOURCE@/${LUSTRE##*/}/g" \
332         -e "s/@LUSTRE_TARGET@/$TARGET/g" \
333         -e "s#@CONFIGURE_FLAGS@#$CONFIGURE_FLAGS#g" \
334         -e "s/@BASE_ARCHS@/$BASE_ARCHS/g" \
335         -e "s/@BIGMEM_ARCHS@/$BIGMEM_ARCHS/g" \
336         -e "s/@BOOT_ARCHS@/$BOOT_ARCHS/g" \
337         -e "s/@JENSEN_ARCHS@/$BOOT_ARCHS/g" \
338         -e "s/@SMP_ARCHS@/$SMP_ARCHS/g" \
339         -e "s/@UP_ARCHS@/$UP_ARCHS/g" \
340         -e "s/@RHBUILD@/$RHBUILD/g" \
341         -e "s/@LINUX26@/$LINUX26/g" \
342         -e "s/@SUSEBUILD@/$SUSEBUILD/g" \
343         < $TOPDIR/lustre/scripts/lustre-kernel-2.4.spec.in \
344         > lustre-kernel-2.4.spec
345     [ -d SRPMS ] || mkdir SRPMS
346     [ -d RPMS ] || mkdir RPMS
347     [ -d BUILD ] || mkdir BUILD
348     [ -d SOURCES ] || mkdir SOURCES
349     cp $TOPDIR/lustre/scripts/linux-rhconfig.h SOURCES
350     cp $TOPDIR/lustre/scripts/linux-merge-config.awk SOURCES
351     cp $TOPDIR/lustre/scripts/linux-merge-modules.awk SOURCES
352     cp "$LUSTRE" "$KERNEL_FILE" SOURCES
353 }
354
355 clean_lustre()
356 {
357     [ -d lustre ] || return 0
358     echo "Cleaning lustre..."
359     [ -L lustre ] && rm -rf $(readlink lustre)
360     rm -rf lustre
361 }
362
363 build()
364 {
365     echo "Building rpms for: $BUILD_ARCHS..."
366     targets=
367     for arch in $BUILD_ARCHS ; do
368         targets="--target $arch $targets"
369     done
370
371     $RPMBUILD $targets -bb lustre-kernel-2.4.spec \
372         --define "_topdir $TOPDIR" || \
373         fatal 1 "Error building rpms for $arch."
374
375     (( $DO_SRC )) && $RPMBUILD -bs lustre-kernel-2.4.spec \
376         --define "_topdir $TOPDIR" || \
377         fatal 1 "Error building .src.rpm."
378 }
379
380 publish()
381 {
382     publishing || return 0
383 }
384
385 [ -r ~/.lbuildrc ] && . ~/.lbuildrc
386
387 options=$(getopt -o d:D:h -l extraversion:,kerneldir:,lustre:,nosrc,publish,release,tag:,target:,target-archs:,disable-datestamp -- "$@")
388
389 eval set -- "$options"
390     
391 while [ "$1" ] ; do
392     case "$1" in
393         '')
394             usage 1
395             ;;
396         -d)
397             CVSROOT=$2
398             shift 2
399             ;;
400         -D)
401             DATE=$2
402             shift 2
403             ;;
404         --extraversion)
405             EXTRA_VERSION=$2
406             shift 2
407             ;;
408         --help | -h)
409             usage 0
410             ;;
411         --kerneldir)
412             KERNELDIR=$2
413             shift 2
414             ;;
415         --lustre)
416             LUSTRE=$2
417             shift 2
418             ;;
419         --nosrc)
420             DO_SRC=0
421             shift 1
422             ;;
423         --publish)
424             PUBLISH=1
425             shift
426             ;;
427         --release)
428             RELEASE=1
429             shift
430             ;;
431         --tag)
432             TAG=$2
433             shift 2
434             ;;
435         --target)
436             TARGET=$2
437             shift 2
438             ;;
439         --target-archs)
440             TARGET_ARCHS=$2
441             shift 2
442             ;;
443         --disable-datestamp)
444             USE_DATESTAMP=
445             shift
446             ;;
447         --)
448             shift
449             CONFIGURE_FLAGS=$@
450             break
451             ;; 
452         *)
453             usage 1 "Unrecognized option: $1"
454             ;;
455     esac
456 done
457
458 check_options
459
460 unpack_lustre
461 load_target
462
463 if (( $DO_SRC )) ; then
464     unpack_linux
465     patch_linux
466     pack_linux
467     clean_linux
468 fi
469
470 # prep_build needs the .spec.in from the lustre source
471 prep_build
472 clean_lustre
473
474 build
475 publish