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