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