#!/bin/bash # # This script is used to build one or more KDE modules # # show_help() { cat </dev/null } isntBlank() { if isBlank "$1"; then return 1 else return 0 fi } # Prints something to the screen and the log file print() { [ -z $no_prefix ] && local print_prefix="[$(date +%s) $(pwd)]: " echo "$*" echo "$print_prefix$*" >&5 } # Runs (and times) a command run() { # [ -n "`type -t time`" ] && local TIME=time print "running:" "$*" tmpfile=$(mktemp /tmp/kde-rebuild.$subdir.XXXXXX) trap "rm $tmpfile; exit 1" 1 2 9 15 if [ -z "$debug" ]; then ( $TIME $* || { print "command \"$1\" failed with exit code $?" return $? } ) 2>&1 | ( if [ -z "$quiet" ]; then tee $tmpfile else cat > $tmpfile fi ) fi cat $tmpfile >&5 rm $tmpfile return 0 } # Pre-compilation ccache routine ccache_pre() { $using_ccache && ccache -z >/dev/null } # Post-compilation ccache routine ccache_post() { $using_ccache || return cache_hit=0 cache_miss=0 eval $(ccache -s | \ awk '/cache hit/ { printf "cache_hit=%d\n", $3 } /cache miss/ { printf "cache_miss=%d\n", $3 }' ) global_cache_hit=$(( $global_cache_hit + $cache_hit )) global_cache_miss=$(( $global_cache_miss + $cache_miss )) print "Cache hit: $cache_hit" print "Cache miss: $cache_miss" print "Cumulated cache hit: $global_cache_hit" print "Cumulated cache miss: $global_cache_miss" } ccache_start() { return } # Prints the final ccache stats ccache_end() { $using_ccache || return ccache -z >/dev/null no_prefix=true print "cache results:" no_prefix=true print "global cache hit $global_cache_hit" no_prefix=true print "global cache miss $global_cache_miss" ccache -s | sed 1,2d ccache -s | sed 1,2d >&5 } # # Builds qt-copy # qt_copy_proc() { [ -n "$WITHOUT_QT" ] && { print "Qt build skipped" return } pushd $OBJDIR/qt-copy run make distclean [ -z $NO_CVS ] && run cvs up [ -z $NO_CONFIGURE -a -z $NO_MAKEFILE_CVS ] && run make -f Makefile.cvs if [ "x$qt_copy_PATCHES" = "xyes" ]; then run ./apply_patches fi # Don't use the global $CONFIGUREFLAGS here echo yes | \ EXTRA_CFLAGS=$CFLAGS EXTRA_CXXFLAGS=$CXXFLAGS run ./configure $qt_copy_CONFIGUREFLAGS ccache_pre run make -j${NRPROC-2} $MAKEFLAGS symlinks sub-src sub-tools ccache_post if [ "x$CLEAN" = "xyes" ]; then run make clean fi popd } # # Update the CVS tree # cvs_up() { if [ -z $NO_CVS ]; then # if BRANCH isn't empty, update to that branch if isntBlank "$BRANCH" ; then CVSFLAGS="$CVSFLAGS -r $BRANCH" fi # Check if we are to update everything or just some subdirs if isBlank "$SUBDIRS"; then run cvs up $CVSFLAGS else for subdir in . $SUBDIRS; do (cd $subdir; run cvs up -l $CVSFLAGS) done fi fi } # # Standard KDE CVS build sequence # standard_build() { cvs_up # Update the CVS tree # prepare the sources if [ "$UNSERMAKE" == "yes" ]; then export UNSERMAKE UNSERMAKE_BIN else local UNSERMAKE UNSERMAKE_BIN unset UNSERMAKE UNSERMAKE_BIN fi [ -z "$NO_CONFIGURE" -a -z "$NO_MAKEFILE_CVS" ] && run make -f Makefile.cvs # create the target directory pushd $OBJDIR run mkdir -p $1 2>/dev/null || return 1 cd $1 # run the configure script export DO_NOT_COMPILE if [ -z $NO_CONFIGURE ]; then run ~1/configure --prefix=$prefix $CONFIGUREFLAGS || return 1 fi if [ "$UNSERMAKE" == "yes" ]; then # build with unsermake ccache_pre run $UNSERMAKE_BIN --compile-jobs=${NRPROC-2} $MAKEFLAGS || local NO_INSTALL=1 ccache_post # install [ -z "$NO_INSTALL" ] && run $SUDO PATH=$PATH\;$UNSERMAKE_BIN -C $PWD install $MAKEINSTALLFLAG # clean up if [ "x$CLEAN" = "xyes" ]; then run $UNSERMAKE_BIN clean fi else # build with automake ccache_pre run make -j${NRPROC-2} $MAKEFLAGS || local NO_INSTALL=1 ccache_post # install [ -z "$NO_INSTALL" ] && run $SUDO make -C $PWD install $MAKEINSTALLFLAG # clean up if [ "x$CLEAN" = "xyes" ]; then run make clean fi fi popd } # # Sets local variables and build a subdir # do_subdir() { subdir="$1" local cleanname=$(echo $subdir | sed s,[.+/-],_,g) # Are we using per-module logfiles? if [ "x$USE_LOGDIR" == "xyes" ]; then [ -d $LOGDIR ] || mkdir -p $LOGDIR || exit $? exec 5> "$LOGDIR/$subdir.log" fi # Set variables # # First, the variables made from the concatenation of the global # one with this module's for variable in \ CONFIGUREFLAGS CFLAGS CXXFLAGS MAKEFLAGS AFLAGS LDFLAGS CVSFLAGS CC CXX LD DO_NOT_COMPILE do eval "local $variable=\"\$${variable}\${$variable+ }\$${cleanname}_${variable}\"" done # The variables whose local one overrides the global: for variable in \ CLEAN UNSERMAKE BRANCH do eval "[ \"\$${cleanname}_${variable}\" ] && local $variable=\"\$${cleanname}_${variable}\"" done # The local-only variables for variable in \ SUBDIRS BUILD do eval "local $variable=\"\$${cleanname}_${variable}\"" done print "==================== Entering $subdir =============" echo "Local variables:" >&5 local >&5 # if unset, default to 'standard_build' building if [ -z "$BUILD" ]; then BUILD=standard_build fi pushd $subdir && $BUILD $subdir && popd print "==================== Exiting $subdir =============" } # Detect ccache using_ccache=false readlink `type -p gcc` 2>/dev/null | grep -q ccache && { using_ccache=true echo "ccache detected" > /dev/null # just for debugging } ccache_start global_cache_hit=0 global_cache_miss=0 export global_cache_hit global_cache_miss # Check the parameters OPTS=`getopt -o qcmurFDM:o: --long with-qt,without-qt,with-qt-patches,without-qt-patches,options:,modules-file:,no-makefile-cvs,no-configure,no-update,no-cvs,no-install,prefix:,just-rebuild:,unsermake,no-unsermake,distcc::,log-mode,help,version,ccache -n kde-rebuild.sh -- "$@"` if [ $? != 0 ]; then exit $?; fi eval set -- "$OPTS" while true; do case "$1" in --with-qt) unset WITHOUT_QT ;; -q|--without-qt) WITHOUT_QT=1 ;; --with-qt-patches) unset WITHOUT_QT qt_copy_PATCHES=yes ;; --without-qt-patches) qt_copy_PATCHES=no ;; -o|--options) [ -r $2 ] && source $2 shift ;; -m|--no-makefile-cvs) NO_MAKEFILE_CVS=1 ;; -c|--no-configure) NO_CONFIGURE=1 ;; -u|--no-update|--no-cvs) NO_CVS=1 ;; --no-install) NO_INSTALL=1 ;; --prefix) prefix="$2" shift ;; -r|--just-rebuild) NO_CVS=1 NO_CONFIGURE=1 NO_MAKEFILE_CVS=1 ;; --unsermake) # detect unsermake # Is environment variable set? if [ \! -x "$UNSERMAKE_BIN" ]; then # No, detect from PATH UNSERMAKE_BIN=`type -p unsermake` if [ -z "$UNSERMAKE_BIN" ]; then # unsermake not found unset UNSERMAKE_BIN fi fi UNSERMAKE=yes # we'll deal with it below ;; --no-unsermake) export UNSERMAKE=no ;; --ccache) using_ccache=true ;; --distcc) [ -n "$2" ] && DISTCC_HOSTS="$2" shift # Find distcc if [ \! -x "$DISTCC" ]; then DISTCC=`type -p distcc` fi if [ -x "$DISTCC" ]; then if $using_ccache; then CCACHE_PREFIX=$DISTCC export CCACHE_PREFIX else CC="$DISTCC ${CC-cc}" CXX="$DISTCC ${CXX-c++}" fi export DISTCC_HOSTS fi ;; -M|--modules-file) [ -r $2 ] && { unset TOPSUBDIRS ourTOPSUBDIRS=`cat $2` } shift ;; --log-mode) case $2 in flat) USE_LOGDIR=no ;; dir) USE_LOGDIR=yes ;; *) echo "`basename $0`: Invalid option for --log-mode: $2" >&2 ;; esac shift ;; -F) USE_LOGDIR=no ;; -D) USE_LOGDIR=yes ;; --help) show_help ;; --version) echo "kde-rebuild version 0.1" exit 0 ;; --) shift for arg; do ourTOPSUBDIRS="$ourTOPSUBDIRS $arg" done break ;; *) ourTOPSUBDIRS="$ourTOPSUBDIRS $1" ;; esac shift if [ $# -eq 0 ]; then break fi done if [ -z "$ourTOPSUBDIRS" ]; then ourTOPSUBDIRS=$TOPSUBDIRS fi if [ -n "$UNSERMAKE_BIN" ]; then if [ -x "$UNSERMAKE_BIN" ]; then PATH=$PATH:`dirname "$UNSERMAKE_BIN"` fi fi PATH=$PATH:$prefix/bin # Open log [ "x$USE_LOGDIR" == "xno" ] && exec 5> $LOGFILE for subdir in $ourTOPSUBDIRS; do do_subdir $subdir done ccache_end