# # Global function library for buildpkg # # This file is designed to be sourced by pr. package buildscripts # # We rely on an environment variable called BUILDPKG_BASE to # define the root of the buildpkg tree # buildpkgbase=${BUILDPKG_BASE-'x'} if [ "$buildpkgbase" == "x" ]; then echo "You *Must* define BUILDPKG_BASE environment variable" exit 1 fi # 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 $patchdir (default $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 STRIP=/usr/bin/strip UNAME=/usr/bin/uname TAR=/usr/local/bin/tar # GNU tar please! VTAR=/usr/bin/tar # vendor supplied tar 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 # vendor supplied 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 - plain /usr/bin/awk will *not* work SED=/usr/bin/sed SORT=/usr/bin/sort CUT=/usr/bin/cut LS=/usr/bin/ls EXPR=/usr/bin/expr MV=/usr/bin/mv MKDIR=/usr/bin/mkdir CP=/usr/bin/cp TEE=/bin/tee CMP=/bin/cmp GREP=/bin/grep UNIQ=/bin/uniq BASENAME=/bin/basename DIRNAME=/bin/dirname TR=/bin/tr DIFF=/usr/local/bin/diff # *Must* support -u (like GNU Diff) FILE=/usr/bin/file # Used by strip() # Groff stuff for manpages NEQN=/usr/local/bin/neqn NEQNOPTS="-Tlatin1" TBL=/usr/local/bin/tbl NROFF=/usr/local/bin/nroff NROFFOPTS="-c -man" # Define defaults buildpkgbase=$BUILDPKG_BASE stagedir=$buildpkgbase/$topdir/stage srcdir=$buildpkgbase/$topdir/src patchdir=$srcdir # Allow the possibility of easily putting a load of patches in a different location metadir=$buildpkgbase/$topdir/meta distdir=$buildpkgbase/distfiles/beta topsrcdir=$topdir-$version # it may be necessary to override this srcfiles=$buildpkgbase/srcfiles topinstalldir=/usr/local prefix=$topinstalldir # Keep this in hard-quotes to delay expansion configure_args='--prefix=$prefix --disable-nls' # Docdir relative to $prefix _docdir=share/doc # Other relative dirs _bindir=bin _libdir=lib _sharedir=share _mandir=man _infodir=info _includedir=include tmpdir=/tmp _os=$($UNAME -sr|$SED -e 's/ //g' -e 's/\.//g'|$TR '[A-Z]' '[a-z]') # pkg information. # The following 3 vars can be used when constructing pkg metadata # Override as necessary. pkgprefix=SB pkgname=$pkgprefix$topdir # overriding this will be common name=$topdir # as will this ditto pkgdirdesig=${topinstalldir##/*/} # topinstalldir suffix # Functionality controls catman=0 # Don't fix manpages pr. default dostrip=1 dostrip_elf=1 # default to stripping binaries during the install stage dostrip_shared=1 # default to stripping shared objects during the install stage dostrip_static=1 # default to stripping static archives during the install stage shortroot=0 # Deep or shallow stagedir? # 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 # You must override the distfile var in the pr. packaging # system function library # 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 E_ARG_OBSO=42 E_BAD_SECTION_BEGIN=43 E_BAD_SECTION_END=44 E_UNPACKAGED_FILES=45 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" error_txt[$E_ARG_OBSO]="Function nolonger supports the argument you passed" error_txt[$E_BAD_SECTION_BEGIN]="Section start marker found but we are already inside a section!" error_txt[$E_BAD_SECTION_END]="Found end of section marker before section begin!" error_txt[$E_UNPACKAGED_FILES]="Unpackaged files found in stage area!" ##################################################### # Helper functions ##################################################### # Two very useful utility functions courtesy of the ABS guide (see Example A-22 & A-23) # _pls will enclose a string in hard-quotes to avoid expansion # _upls will remove hard-quotes from hard-quoted string thus allowing expansion _pls() { # local IFS=$'x1B' # \ESC character (not required) echo $'\x27'$@$'\x27' # Hard quoted parameter glob } _upls() { # local IFS=$'x1B' # \ESC character (not required) eval echo $@ # Substitution on the glob. } # 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]=$patchdir/${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() { local i local secname local pkgname case $1 in 'source') if [ -d "$srcdir/$topsrcdir" ]; then echo "Removing $srcdir/$topsrcdir" $RM -rf $srcdir/$topsrcdir else echo "No unpacked source to scrub" fi ;; 'stage') if [ -d $stagedir -a "$stagedir" != "/" ]; then echo "Emptying $stagedir" $RM -rf $stagedir # This is very dangerous! $MKDIR $stagedir else error $E_BAD_DIR clean fi ;; 'meta') if [ "$($UNAME -s)" == "SunOS" ]; then for secname in $(list_pkgs) do META_CLEAN="$META_CLEAN prototype.$secname pkginfo.$secname" pkgname=$(get_pkgname $secname) echo "Removing $buildpkgbase/$topdir/$pkgname" $RM -rf $buildpkgbase/$topdir/$pkgname done fi for i in $META_CLEAN do echo "Removing $metadir/$i" $RM -f $metadir/$i done ;; '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() { local f setdir stage # Strip ELF binaries (see brp-strip from RPM) if [ $dostrip_elf -eq 1 ]; then echo "Stripping ELF binaries..." for f in `$FIND . -type f \( -perm -0100 -o -perm -0010 -o -perm -0001 \) -exec $FILE {} \; | \ $GREP -v ' shared object,' | \ $SED -n -e 's/^\(.*\):[ ]*ELF.*, not stripped/\1/p'`; do $STRIP $strip_elf_args $f || : done fi if [ $dostrip_shared -eq 1 ]; then echo "Stripping ELF shared objects..." # Strip ELF shared objects (see brp-strip-shared from RPM) # Please note we don't restrict our search to executable files because # our libraries are not (should not be, at least) +x. for f in `$FIND . -type f -a -exec $FILE {} \; | \ grep ' shared object,' | \ $SED -n -e 's/^\(.*\):[ ]*ELF.*, not stripped/\1/p'`; do $STRIP $strip_shared_args $f done fi if [ $dostrip_static -eq 1 ]; then echo "Stripping static archives..." # Strip static libraries. (see brp-strip-static-archive from RPM) for f in `$FIND . -type f -a -exec $FILE {} \; | \ $GREP 'current ar archive' | \ $SED -n -e 's/^\(.*\):[ ]*current ar archive,.*/\1/p'`; do $STRIP $strip_static_args $f done fi } # fix_man(): create compressed pre-formatted manpages from raw ones # params: none # Run from 'cwd' where 'cwd' contains manX subdirs fix_man() { echo "Formatting manpages" for i in man? do if [ -d $i ]; then catdir=cat${i##man} $MKDIR $catdir cd $i for manpage in * do if [ -L "$manpage" ]; then TARGET=$($LS -l "$manpage" | $AWK '{ print $NF }') ln -snf "$TARGET".gz "$manpage".gz $MV "$manpage".gz "../$catdir" $RM -f "$manpage" else $NEQN $NEQNOPTS "$manpage" | $TBL | $NROFF $NROFFOPTS > "../$catdir/$manpage" $GZIP "../$catdir/$manpage" $RM -f $manpage fi done cd .. rmdir $i fi done } # doc(): Add files from srcdir to 'docs' location # params: $1..$x # Copies files from $srcdir to $_docdir/$topdir-$version doc() { local f if [ ! -z $# ]; then setdir source if [ "$shortroot" -eq 1 ]; then _docdir=$stagedir/$_docdir/$topdir-$version else _docdir=$stagedir/$prefix/$_docdir/$topdir-$version fi mkdir -p $_docdir echo "Adding docs" until [ -z "$1" ] do for f in $(_upls $1) do ($TAR -cf - "$f")|(cd $_docdir; $TAR -xvBpf -) done shift done fi } # compute_octal() # Description: Computes the octal value from a permission list (_rwxrwxrwx) # param: $1=permission list # Caveats: It won't pickup sticky bit and mandatory locking bit compute_octal() { perm=$1 v=0; d1=0; d2=0; d3=0; d4=0 # User part if [ "${perm:1:1}" == "r" ]; then let "v = v + 4" # set read bit fi if [ "${perm:2:1}" == "w" ]; then let "v = v + 2" # set write bit fi if [ "${perm:3:1}" == "x" ]; then let "v = v + 1" # set executable bit elif [ "${perm:3:1}" == "s" ]; then let "v = v + 1" # set executable bit let "d1 = d1 + 4" # Set setuid bit fi d2=$v; v=0 # Group part if [ "${perm:4:1}" == "r" ]; then let "v = v + 4" # set read bit fi if [ "${perm:5:1}" == "w" ]; then let "v = v + 2" # set write bit fi if [ "${perm:6:1}" == "x" ]; then let "v = v + 1" # set executable bit elif [ "${perm:6:1}" == "s" ]; then let "v = v + 1" # set executable bit let "d1 = d1 + 2" # Set setgid bit fi d3=$v; v=0; # Other part if [ "${perm:7:1}" == "r" ]; then let "v = v + 4" # set read bit fi if [ "${perm:8:1}" == "w" ]; then let "v = v + 2" # set write bit fi if [ "${perm:9:1}" == "x" ]; then let "v = v + 1" # set executable bit fi d4=$v; v=0 echo $d1$d2$d3$d4 } ##################################################### # 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 $(_upls $configure_args) 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 if [ $dostrip -eq 1 ]; then strip fi } # 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. # # This function should be implemented in the pr. packaging system # function library. case $OSTYPE in solaris*) . $buildpkgbase/scripts/buildpkg.packaging.solaris ;; irix*) . $buildpkgbase/scripts/buildpkg.packaging.irix ;; *) echo "No packaging system function library available for this OS" ;; esac