#!/bin/bash # Version: 1.6 GSB Section SlackBuild. # Copyright (c) 2007 Darren 'Tadgy' Austin # # Licenced under the terms of the GNU General Public Licence version 3. # # Make sure we are in the right directory (you can never trust users..) cd $( cd ${BASH_SOURCE%/*} ; pwd ) # Section name. # This should not need to be changed unless the auto detection fails. SECTION="$( basename $( pwd ) )" # Packages to build. # Package list is read in from .buildlist in the current directory, with any # comments and blank lines removed. PACKAGES="$( egrep -v "^#|^$" .buildlist | cut -d'#' -f1 )" # Usage. function usage() { cat << EOF Usage: ${0##*/} [options] Options: --help Show this help screen. --list List the packages which will be built in this section. --force A package will not be built if a package of the same name is already installed, or any of the pre-requisite packages are not installed. This option over-rides the checks and attempts a build (which will probably fail) anyway. --no-cleanup By default, any source, temporary build and package directories will be deleted once the package is built. This option prevents those files from being removed. --no-patchesdir When rebuilding packages which already exist in the main package directory, the default is to put the new packages in the patches directory. Using this option completely disables the use of a patches directory. --no-skip During the build process, packages that are up to date (ie, the package version and build numbers match the coresponding SlackBuild) will not be rebuilt. This option forces packages to be rebuilt regardless of the version and build numbers. This option doesn't affect the pre-build checks for installed packages (see the --force option). This option implies --no-patchesdir. --no-prune Normally, when a package is built and copied to the destination directory (whether it be the main package directory or the patches directory), any previous package(s) of the same name in that directory are deleted - it is assumed the new package is to replace any which are already present. This option prevents previous packages being deleted, possibly leaving more than one package of the same name (but with different version or build numbers) laying around. --no-install Build the packages but don't install them afterwards. This should only be used for testing as it WILL cause serious problems - most builds rely on other GSB packages being automatically installed first. --no-metafiles Do not create the package's .txt and .md5 meta files which would usually be produced during a build. Options are passed down to the next level SlackBuild where appropriate. EOF } function list_packages() { local PACKAGE echo "The following packages are built in this section, listed in processing order:" ( for PACKAGE in $PACKAGES do echo -n "$PACKAGE, " done ) | sed -e 's/, $//' | fmt -w 74 | sed -e 's/^/ /g' } function find_package_files() { # $1 = Directory to look for files in [required] # $2 = Package name or regex to match. An empty string matches all. # $3 = Package version or regex to match. An empty string matches all. # $4 = Package architecture or regex to match. An empty string matches all. # $5 = Package build tag or regex to match. An empty string matches all. # $6 = File extension or regex to match. An empty string means no extension. # Note: Remember to escape any regex characters used in fixed strings. [ -z "$1" ] || [ ! -d "$1" ] && return 1 find $1 -maxdepth 1 -mindepth 1 2>/dev/null | \ egrep "^.*/(${2:-.*})(-${3:-[^-]*})(-${4:-[^-]*})(-${5:-[^-.]*})($6)$" 2>/dev/null return $? } function runtime() { # $1 = Number of seconds to convert to readable text [required] [ -z "$1" ] && return 1 local D=$(( $1 / 86400 )) local H=$(( ($1 - ($D * 86400)) / 3600 )) local M=$(( ($1 - ($D * 86400) - ($H * 3600)) / 60 )) local S=$(( $1 - ($D * 86400) - ($H * 3600) - ($M * 60) )) if [ $D -gt 0 ]; then echo -n "${D}d, ${H}h ${M}m ${S}s" else echo -n "${H}h, ${M}m ${S}s" fi return 0 } function gen_pkg_txt() { # $1 = Package file to process [required]. [ -z "$1" ] || [ ! -e "$1" ] && return 1 tar xzOf $1 install/slack-desc 2>/dev/null | \ grep -v "^#" | egrep "[[:alnum:]\+]+\:" >${1%.tgz}.txt return $? } function gen_pkg_md5() { # $1 = Package file to process [required]. [ -z "$1" ] || [ ! -e "$1" ] && return 1 ( cd $( dirname $1 ) && md5sum $( basename $1 ) >$1.md5 ) return $? } # If the user created an options file, read it. [ "$OPTIONSREAD" != "1" -a -r ../gsb.options ] && { . ../gsb.options export OPTIONSREAD=1 } # Environment. export TMP=${TMP:-/tmp} if [ "$ARCH" = "x86_64" ]; then export PKGDEST=${PKGDEST:-$TMP/gsb64-tree} export LOGSDIR=${LOGSDIR:-$TMP/gsb64-buildlogs} else export PKGDEST=${PKGDEST:-$TMP/gsb-tree} export LOGSDIR=${LOGSDIR:-$TMP/gsb-buildlogs} fi export GSBDIR=${GSBDIR:-gsb} export PATCHESDIR=${PATCHESDIR:-patches} export TESTINGDIR=${TESTINGDIR:-testing} export PACKAGESDIR=${PACKAGESDIR:-packages} export SOURCEDIR=${SOURCEDIR:-source} # Option defaults. NOPATCHESDIR=0 NOSKIP=0 NOPRUNE=0 NOINSTALL=0 NOMETAFILES=0 # Sanity check (in case Steve forgets to add packages again :P). [ $( echo "$PACKAGES" | wc -w ) != \ $( find . -type d ! -name .svn -maxdepth 1 -mindepth 1 | wc -w ) ] && { echo echo "*********************************************************************" echo "** Error: the number of packages in the PACKAGES list is different" echo "** to the number of package directories in this section." echo "** Some packages may not have been added to the PACKAGES list." echo "*********************************************************************" exit 1 } # Parse command line arguments. while [ $# -gt 0 ]; do if [ "$1" = "-help" ] || [ "$1" = "--help" ]; then usage exit 0 elif [ "$1" = "-list" ] || [ "$1" = "--list" ]; then list_packages exit 0 elif [ "$1" = "-force" ] || [ "$1" = "--force" ]; then SLACKBUILD_ARGS="${SLACKBUILD_ARGS:+"$SLACKBUILD_ARGS "}--force" shift elif [ "$1" = "-no-cleanup" ] || [ "$1" = "--no-cleanup" ]; then SLACKBUILD_ARGS="${SLACKBUILD_ARGS:+"$SLACKBUILD_ARGS "}--no-cleanup" shift elif [ "$1" = "-no-patchesdir" ] || [ "$1" = "--no-patchesdir" ]; then NOPATCHESDIR=1 shift elif [ "$1" = "-no-skip" ] || [ "$1" = "--no-skip" ]; then NOSKIP=1 NOPATCHESDIR=1 shift elif [ "$1" = "-no-prune" ] || [ "$1" = "--no-prune" ]; then NOPRUNE=1 shift elif [ "$1" = "-no-install" ] || [ "$1" = "--no-install" ]; then NOINSTALL=1 shift elif [ "$1" = "-no-metafiles" ] || [ "$1" = "--no-metafiles" ]; then NOMETAFILES=1 shift else echo "${0##*/}: Unknown option: $1" echo "Try: $0 --help" exit 1 fi done # Temporary space, package and log file storage. mkdir -p $TMP mkdir -p $PKGDEST mkdir -p $LOGSDIR mkdir -p $LOGSDIR/$SECTION echo echo "*********************************************************************" echo "** Building section '$SECTION'..." echo "*********************************************************************" # Process packages. ( for PACKAGE in $PACKAGES do # Build defaults. SKIP_BUILD=0 SUBDIR=$GSBDIR/$PACKAGESDIR/$SECTION echo echo "*********************************************************************" echo "*** Processing package '$PACKAGE'..." echo "*********************************************************************" # Sanity checks. [ ! -e "$PACKAGE/$PACKAGE.SlackBuild" ] && { echo echo "*********************************************************************" echo "*** Error: '$PACKAGE.SlackBuild' not found." echo "*********************************************************************" exit 1 } [ ! -x "$PACKAGE/$PACKAGE.SlackBuild" ] && { echo echo "*********************************************************************" echo "*** Error: '$PACKAGE.SlackBuild' is not executable." echo "*********************************************************************" exit 1 } # Get package version and build numbers from the package SlackBuild. declare PACKAGE_$( egrep -m 1 "^VERSION=.*" $PACKAGE/$PACKAGE.SlackBuild ) declare PACKAGE_$( egrep -m 1 "^BUILD=.*" $PACKAGE/$PACKAGE.SlackBuild ) # Check that we got a version and build. [ -z "$PACKAGE_VERSION" ] || [ -z "$PACKAGE_BUILD" ] && { echo echo "*********************************************************************" echo "*** Error: failed to get VERSION or BUILD from '$PACKAGE.SlackBuild'" echo "*********************************************************************" exit 1 } # Check if the package should be rebuilt, and where it should be put. # The assumption is to always rebuild and put packages in the main # directory, unless modified by the checks below. if find_package_files "$PKGDEST/$SUBDIR" "${PACKAGE//+/\+}" \ "" "" "" "\.tgz" >/dev/null && [ "$NOSKIP" = "0" ] then if find_package_files "$PKGDEST/$SUBDIR" "${PACKAGE//+/\+}" \ "${PACKAGE_VERSION//-/_}" "" "$PACKAGE_BUILD" "\.tgz" >/dev/null then # Package with same version/build was found in the main directory. SKIP_BUILD=1 else # Not in the main directory, check patches. if [ "$NOPATCHESDIR" = "0" ]; then if find_package_files "$PKGDEST/$PATCHESDIR/$PACKAGESDIR/$SECTION" \ "${PACKAGE//+/\+}" "${PACKAGE_VERSION//-/_}" "" "$PACKAGE_BUILD" \ "\.tgz" >/dev/null then # Found in patches dir. SKIP_BUILD=1 SUBDIR=$PATCHESDIR/$PACKAGESDIR/$SECTION else # No package in patches with the same version/build. SUBDIR=$PATCHESDIR/$PACKAGESDIR/$SECTION fi fi fi fi # Build package if required. if [ "$SKIP_BUILD" = "0" ]; then echo echo "*********************************************************************" echo "*** Removing installed package (if required) and cleaning up files" echo "*********************************************************************" rm -f $( find_package_files "$PKGDEST/$SUBDIR" "${PACKAGE//+/\+}" \ "${PACKAGE_VERSION//-/_}" "" "$PACKAGE_BUILD" "\.tgz|\.txt|\.tgz\.md5" \ | tr '\n' ' ' ) >/dev/null 2>&1 find_package_files "/var/log/packages" "${PACKAGE//+/\+}" "" "" "" "" \ >/dev/null && { removepkg $( basename $( find_package_files "/var/log/packages" \ "${PACKAGE//+/\+}" "" "" "" "" ) ) } echo echo "*********************************************************************" echo "*** Building package '$PACKAGE'..." echo "*********************************************************************" mkdir -p $PKGDEST/$SUBDIR ( cd $PACKAGE && export PKGDEST=$PKGDEST/$SUBDIR && ./$PACKAGE.SlackBuild $SLACKBUILD_ARGS 2>&1 ) | \ tee $LOGSDIR/$SECTION/$PACKAGE-$( date +%Y%m%d-%H%M%S ).log ERR=${PIPESTATUS[0]} [ "$ERR" != "0" ] && { echo echo "*********************************************************************" echo "*** Error: '$PACKAGE' build failed." echo "*********************************************************************" exit $ERR } else echo echo "*********************************************************************" echo "*** Skipping build of '$PACKAGE' - package up to date." echo "*********************************************************************" fi PRUNE_FILES="$( find_package_files "$PKGDEST/$SUBDIR" "${PACKAGE//+/\+}" \ "" "" "" "\.tgz|\.txt|\.tgz\.md5" | grep -v "$( find_package_files \ "$PKGDEST/$SUBDIR" "${PACKAGE//+/\+}" "${PACKAGE_VERSION//-/_}" "" \ "$PACKAGE_BUILD" "\.tgz" )" | tr '\n' ' ' )" [ ! -z "$PRUNE_FILES" ] && { if [ "$NOPRUNE" = "0" ]; then echo echo "*********************************************************************" echo "*** Pruning old '$PACKAGE' package files from tree..." echo "*********************************************************************" rm -f $PRUNE_FILES else echo echo "*********************************************************************" echo "*** Warning: not pruning any old '$PACKAGE' files." echo "*********************************************************************" fi } if [ "$NOMETAFILES" = "0" ]; then echo echo "*********************************************************************" echo "*** Creating meta files for '$PACKAGE'..." echo "*********************************************************************" gen_pkg_txt "$( find_package_files "$PKGDEST/$SUBDIR" "${PACKAGE//+/\+}" \ "${PACKAGE_VERSION//-/_}" "" "$PACKAGE_BUILD" "\.tgz" )" && gen_pkg_md5 "$( find_package_files "$PKGDEST/$SUBDIR" "${PACKAGE//+/\+}" \ "${PACKAGE_VERSION//-/_}" "" "$PACKAGE_BUILD" "\.tgz" )" || { echo echo "*********************************************************************" echo "*** Error: failed to create meta files for '$PACKAGE'." echo "*********************************************************************" exit 1 } else echo echo "*********************************************************************" echo "*** Warning: not creating meta files for '$PACKAGE'." echo "*********************************************************************" fi if [ "$NOINSTALL" = "0" ]; then echo echo "*********************************************************************" echo "*** Installing '$PACKAGE'..." echo "*********************************************************************" upgradepkg --install-new $( find_package_files "$PKGDEST/$SUBDIR" \ "${PACKAGE//+/\+}" "${PACKAGE_VERSION//-/_}" "" "$PACKAGE_BUILD" "\.tgz" ) || { echo echo "*********************************************************************" echo "*** Error: failed to install '$PACKAGE'." echo "*********************************************************************" exit 1 } else echo echo "*********************************************************************" echo "*** Warning: not installing '$PACKAGE'." echo "*********************************************************************" fi done echo echo "*********************************************************************" echo "** Finished building section '$SECTION'." echo "*********************************************************************" echo "** Binary packages can be found in sub directories of:" echo "** $PKGDEST" echo "** Individual build logs can be found in:" echo "** $LOGSDIR/$SECTION" echo "** Package files and build logs can be deleted if not required." echo "*********************************************************************" echo "** Section build time was $( runtime $SECONDS )." echo "*********************************************************************" ) 2>&1 | tee $LOGSDIR/$SECTION-$(date +%Y%m%d-%H%M%S).log # Return the exit status from the sub-shell, not the tee command. exit ${PIPESTATUS[0]}