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