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