# # Global config file for buildpkg # # This file is designed to be sourced by pr. package buildscripts # # Variables that *must* be overridden pr. package # They are used to construct paths and more so they # must have sane values # topdir= The toplevel dir name under $buildpkgbase # It is also used pr. default in the pkgname # and it is also used pr. default as the toplevel name inside the sourcetar ($topsrcdir) # version= source version ie. 0.14.2b # pkgver= the package revision, an increasing number is recommended but a date could be used instead # source[0..x] = source filenames - source[0] *must* be defined and contain a legal filename # pr. default we will look for source[0] relative to $srcfiles # A filename that begin with / will be treated as absolute paths # Note! only source[0] will be automatically unpacked # patch[0..x] = patch filenames - if patch[0] is undefined then generic_prep won't attempt to patch the source # pr. default we expect these to be listed relative to $srcdir # filenames that begin with / will be treated as absolute paths # All patching will be done from *within* $srcdir/$topsrcdir directory with patch -p1 # patches must be in uncompressed format # Define tool programs PKGMK=/usr/bin/pkgmk PKGTRANS=/usr/bin/pkgtrans PKGPROTO=/usr/bin/pkgproto STRIP=/usr/ccs/bin/strip UNAME=/usr/bin/uname TAR=/usr/local/bin/tar # GNU tar please! BZIP2=/usr/bin/bzip2 GZIP=/usr/bin/gzip PATCH=/usr/local/bin/patch # GNU patch 2.5 or better please! RM=/usr/bin/rm MKDIR=/usr/bin/mkdir MAKE_PROG=/usr/local/bin/make # GNU make please! FIND=/usr/bin/find # Solaris find - GNU find will require changes to the script XARGS=/usr/bin/xargs CAT=/usr/bin/cat AWK=/usr/bin/nawk # This must be nawk or GNU awk - /usr/bin/awk will *not* work SED=/usr/bin/sed # Define defaults buildpkgbase=${HOME}/buildpkg stagedir=$buildpkgbase/$topdir/stage srcdir=$buildpkgbase/$topdir/src metadir=$buildpkgbase/$topdir/meta distdir=$buildpkgbase/distfiles topsrcdir=$topdir-$version # it may be necessary to override this srcfiles=$buildpkgbase/srcfiles topinstalldir=/usr/local prefix=$topinstalldir pkgname=SB$topdir cpu=sparcv9 os=sol`$UNAME -r` pkgdirdesig=${topinstalldir##/*/} # topinstalldir suffix # Distfiles should be named like this # --.sb--- # ie: libmad-0.14.2b-1.sb-sol5.8-sparcv9-local distfile=$topdir-$version-$pkgver.sb-$os-$cpu-$pkgdirdesig # Define error codes and texts E_MISSING_STAGEDIR=30 E_MISSING_ARGS=31 E_BAD_FILE=32 E_PATCH_FAILED=33 E_BAD_DIR=34 E_BAD_UNPACK=35 E_BAD_COMPRESS=36 E_BAD_CONFIG=37 E_BAD_MAKE=38 E_BAD_CLEANOPTIONS=39 E_BAD_STRIP=40 E_BAD_ARGS=41 error_txt[$E_BAD_FILE]="File not found" error_txt[$E_PATCH_FAILED]="Patch failed" error_txt[$E_BAD_DIR]="Directory not found" error_txt[$E_BAD_UNPACK]="Unable to decompress sourcearchive" error_txt[$E_BAD_COMPRESS]="Unknown compression method" #error_txt[$E_BAD_CONFIG]="configure failed" #error_txt[$E_BAD_MAKE]="make failed" error_txt[$E_MISSING_ARGS]="A required argument was missing" error_txt[$E_BAD_ARGS]="An illegal argument was passed" ##################################################### # Helper functions ##################################################### # error(): exit with errorcode and possibly a message # params: $1 = errorcode $2 = name of caller error() { if [ -n "${error_txt[$1]}" ]; then echo "$2: ${error_txt[$1]}" fi exit $1 } # setdir(): switch to a directory, but check destination first # params: $1=dir to cd to [source|stage] can be used as shortcuts # Switches to the directory in $1 but first checks if the destination exists setdir() { local dir=$1 case $dir in 'source') dir="$srcdir/$topsrcdir";; 'stage') dir="$stagedir";; esac echo "Switching to $dir" if [ -z "$dir" ]; then error $E_BAD_DIR setdir fi if [ -d "$dir" ]; then cd "$dir" else error $E_BAD_DIR setdir fi } # # patch(): patch unpacked source # params: $1 = patch number (arrayindex) $2 = patch params (defaults to -p1) # It will verify the existence of the patch file passed to it and # exit gracefully if it cannot be found. # An empty $2 argument will be treated as undefined and mapped to -p1 patch() { local pnum=$1 local arg2=$2 local pparam=${arg2:-"-p1"} setdir source if [ ! -z ${patch[$pnum]} ]; then # They didn't give us an empty string if [ "${patch[$pnum]:0:1}" != "/" ]; then # We have a relative pathname # expand to absolute patch[$pnum]=$srcdir/${patch[$pnum]} fi # We are now sure that $patch[$pnum] contains file with absolute path echo "Processing patch[$pnum] - ${patch[$pnum]}" if [ -r ${patch[$pnum]} ]; then # file is readable $PATCH -Es $2 < ${patch[$pnum]} if [ $? -ne 0 ]; then error $E_PATCH_FAILED patch fi else error $E_BAD_FILE patch fi else echo "Patch $pnum has empty filename" fi } # unpack(): Unpack source # params: $1 = source number (arrayindex) # It will detect filetype and unpack # .tar, .tgz, .gz, .bz2 and .Z supported unpack() { local snum=$1 setdir $srcdir if [ "${source[$snum]:0:1}" != "/" ]; then # We have a relative pathname # expand to absolute source[$snum]=$srcfiles/${source[$snum]} fi # We are now sure that ${source[$snum]} contains file with absolute path echo "Unpacking ${source[$snum]}" if [ -r ${source[$snum]} ]; then # file is readable local absfilename=${source[$snum]} local filename=${absfilename##/*/} # Strip down to the filename local suffix=${filename##*.} # Strip down to filename suffix (strip down to the last .) # Determine filetype and unpack case $suffix in 'tar') $TAR -xf ${source[$snum]};; 'gz') $GZIP -dc ${source[$snum]} | $TAR -xf -;; 'bz2') $BZIP2 -dc ${source[$snum]} | $TAR -xf -;; 'Z') $GZIP -dc ${source[$snum]} | $TAR -xf -;; 'tgz') $GZIP -dc ${source[$snum]} | $TAR -xf -;; *) error $E_BAD_COMPRESS unpack esac if [ $? -ne 0 ]; then error $E_BAD_UNPACK unpack fi else error $E_BAD_FILE unpack fi } # clean(): Scrub build environment # params: $1=stage|source|distclean clean() { case $1 in 'source') if [ -d "$srcdir/$topsrcdir" ]; then $RM -rf $srcdir/$topsrcdir else echo "No unpacked source to scrub" fi ;; 'stage') if [ -d $stagedir -a "$stagedir" != "/" ]; then $RM -rf $stagedir # This is very dangerous! $MKDIR $stagedir else error $E_BAD_DIR clean fi ;; 'meta') $RM -f $metadir/prototype* $RM -f $metadir/pkginfo $RM -rf $buildpkgbase/$topdir/$pkgname ;; 'distclean') clean source clean stage clean meta ;; *) error $E_BAD_CLEANOPTION clean esac } # strip(): strip binaries in stagedir # params: none # Automatically switches to $stagedir # On exit cwd is $stagedir strip() { setdir stage $FIND . -type f -perm -700 | $XARGS $STRIP # if [ $? -ne 0 ]; then # error $E_BAD_STRIP strip # if } # make_pkg(): Create the final package # params: none # make_pkg() { $PKGMK -r `pwd` -d $buildpkgbase/$topdir -o -f $metadir/prototype $PKGTRANS -o -s $buildpkgbase/$topdir $distdir/$distfile $pkgname } # pack_info(): Create the pkginfo file # params: none # Will create the pkginfo file with pkginfo.in as a template # Both the template and the result will be in $metadir # Substitutions will be done on pkgname,version & pkgver # they will be replaced with the value of their variable counterparts pack_info() { $SED -e "s#%%pkgname%%#$pkgname#g" \ -e "s#%%version%%#$version#g" \ -e "s#%%pkgver%%#$pkgver#g" \ $metadir/pkginfo.in > $metadir/pkginfo } # prototype(): Create a prototype file for pkgmk # params: $1 = owner $2 = group $3 = [script|noscript] # $1 & $2 will list the owner and group that is to be applied to all files # pkginfo and depend (if it exists) will automatically be added to prototype file # $3 will define whether or not to automatically include any post/pre scripts found # in $topdir/meta. Pr. default postinstall,preinstall,postremove,preremove are the filenames # it will look for. # $3 can be omitted and in that case prototype will behave as if $3=noscript prototype() { local owner=$1 local group=$2 $FIND . -print|$PKGPROTO > $metadir/prototype.in $CAT $metadir/prototype.in | $AWK -v owner="$owner" -v group="$group" \ '{ $5=owner; $6=group; print; }' > $metadir/prototype add_meta_file pkginfo "$metadir/pkginfo" # If a dependency file is available then use it [ -r $metadir/depend ] && add_meta_file depend "$metadir/depend" case $3 in 'script') [ -r $metadir/preinstall ] && add_meta_file preinstall "$metadir/preinstall" [ -r $metadir/postinstall ] && add_meta_file postinstall "$metadir/postinstall" [ -r $metadir/preremove ] && add_meta_file preremove "$metadir/preremove" [ -r $metadir/postremove ] && add_meta_file postremove "$metadir/postremove" ;; 'noscript') ;; esac } # add_meta_file(): add a metafile entry to the prototype file # params: $1 = keyword $2 = filename # Additions will be done to the file $metadir/prototype add_meta_file() { local arg1=${1-'x'} if [ "$arg1" == "x" ]; then error $E_MISSING_ARGS add_meta_file fi local arg2=${2-'x'} if [ "$arg2" == "x" ]; then error $E_MISSING_ARGS add_meta_file fi if [ -r "$arg2" ]; then echo "i $arg1=$arg2" >> $metadir/prototype else error $E_BAD_FILE add_meta_file fi } ##################################################### # Define generic functions for different build stages ##################################################### # generic_prep(): Unpack source and apply any patches # params: none generic_prep() { clean source unpack 0 # Verify that ${patch[$pnum]} is defined local pver=${patch[0]-'x'} if [ "$pver" == "x" ]; then return # it was undefined else local numpatch=${#patch[@]} local i=0 # Argh! - The C-style for loop doesn't work in bash-2.0.3 as distributed # with Solaris 8 :( (it works just fine on Redhat Linux 7.3, bash 2.0.5a) # for ((i=0; i < numpatch; i++)) # do # patch $i -p1 # done while [ $i -lt $numpatch ] do patch $i -p1 let i=i+1 done fi } # generic_build(): Take the necessary steps to build already prepared source # params: none generic_build() { setdir source ./configure --prefix=$prefix if [ $? -ne 0 ]; then error $E_BAD_CONFIG generic_build fi $MAKE_PROG if [ $? -ne 0 ]; then error $E_BAD_MAKE generic_build fi } # generic_install(): Install already built source # params: $1 = destvar # destvar is the variable that make should override to install into the staging # area. default is DESTDIR, possible common alternatives are prefix and PREFIX generic_install() { local destvar=DESTDIR local arg1=${1-'x'} if [ "$arg1" != "x" ]; then destvar=$arg1 # $1 was defined fi clean stage setdir source $MAKE_PROG $destvar=$stagedir install if [ $? -ne 0 ]; then error $E_BAD_MAKE generic_install fi strip } # generic_pack(): Build package using files from 'install' stage # params: $1 - indicating whether or not the root is complete as described below # We expect generic_install to have made $stagedir the "root" dir # in that all paths below will be complete (ie. /usr/local/bin and not # just bin) *unless* $1=shortroot. generic_pack() { clean meta # Verify if $1 is defined local arg1=${1-'x'} case $arg1 in 'x') setdir "$stagedir$prefix" # arg1 was undefined ;; 'shortroot') setdir "$stagedir" ;; '*') error $E_BAD_ARGS generic_pack esac pack_info prototype root bin script make_pkg }