#!/bin/sh
################################################################################
# Updates and recompiles a local KDE CVS tree                                  #
# (c) 2000, 2001, 2002 by Frerich Raabe <raabe@kde.org>                        #
################################################################################
# Do not edit this file, change kde-buildrc instead!                           #
################################################################################

# These strings are defined as variables to make the output look more
# consistent.
#
str_okay="done!"
str_error="failed!"

# The variables whose name is prefixed with ERR_ hold the error codes which
# are returned by the script and depend on the reason for aborting the
# execution.
#
# No error has been noticed, everything seems to be fine.
#
err_no_error="0"

# Could not change into a directory of a module - wrong owner/access
# settings?
#
err_change_into_mod_dir="1"

# Could not find the file 'Makefile.in' for a module, mostly happens if
# 'make -f Makefile.cvs' hasn't been executed for a module.
#
err_no_makefile_in="2"

# The 'configure' command failed for a module because the system doesn't
# support certain features - I hope you activated logfile generation... ;)
#
err_configure_fail="3"

# The compilation of a module failed - if the module is defined in
# $critical_modules (see below) the execution is aborted, otherwise the script
# will continue with the next module.
#
err_compile_fail="4"

# The installation of a module failed - this mostly happens if there's not
# enough free disk space on the partition which $KDEDIRS is mounted to.
#
err_install_fail="5"

# The $KDESRCDIR variable wasn't set or contains a non-existant directory.
#
err_inv_kdesrcdir="6"

# The $QTDIR variable wasn't set, points to a non-existant directory or
# doesn't contain a bin/, lib/, or include/ subdirectory.
#
err_inv_qtdir="7"

# There is no CVS client specified in the configuration file, or the
# specified client is invalid.
#
err_cvsclient_fail="8"

# There was no cvsup server specified in the configuration file.
#
err_inv_cvsup_server="9"

# The script was unable to create a temporary cvsup configuration file
# in /tmp, mostly due to insufficient diskspace.
#
err_no_temp_supfile="10"

# The configuration file couldn't be found.
#
err_no_config="11"

# Certain modules depend on others - those "base" modules which are required
# by others to compile and/or run should be listed here to ensure that the
# script is aborted in case on of these modules doesn't build.
# These modules needs to be build and installed in this specific order!
#
critical_modules="arts kdelibs kdebase"

# Internal variable, do not change.
#
dateformat="`date +%Y%m%d`"

# This method gives some kind of status message in the title bar of Konsole,
# xterm, etc.. Thanks have to go to Malte Starostik
# <malte@kde.org> for the code :-)
set_title() {
if ([ "$TERM" = "xterm" ] || [ "$TERM" = "xterm-color" ] || [ "$TERM" = "screen" ]) && tty -s; then
  echo -ne "\033]0;$1\007"
fi
}

# moves a log file to be named failed, so one can see on first glance
move_logfile() {
  mv $logfile `echo $logfile | sed -e "s,-build-,-failed-,"`
}

# This function computes the time which was needed for a certain task.
#
compute_time() {
  duration=$[`date +%s`-$starttime]
  hours=`echo $[$duration / 3600] | sed -e "s/^[0-9]\$/0&/"`
  minutes=`echo $[$[$duration % 3600] / 60] | sed -e "s/^[0-9]\$/0&/"`
  seconds=`echo $[$duration % 60] | sed -e "s/^[0-9]\$/0&/"`
}

# This function installs a compiled CVS module.
#
install_module() {
  echo -n "  Installing..."
  set_title "Installing module $module..."
  if test "x$KDELOGDIR" != x; then
    echo "-> Installation <---------------------------------------------------------------" >> $logfile
    cmd_make_install="$cmd_make_install >> $logfile 2>&1"
    starttime=`date +%s`
   fi

  if eval ${cmd_make_install}; then
    if test "x$KDELOGDIR" != x; then
      compute_time
      echo "--------------------------------------------------------------------------------" >> $logfile
      echo "Time needed for installation of module $module: $hours:$minutes:$seconds" >> $logfile
      echo "" >> $logfile
      echo "Build of module $module successfully finished at `date +%c`" >> $logfile
      test "x$cmd_compress" != x && eval "$cmd_compress $logfile"
    fi
    echo -e "$str_okay"
    echo "Module $module successfully installed in $KDEDIRS!"
  else
    echo -e "$str_error"
    test "x$cmd_compress" != x && eval "$cmd_compress $logfile"
    test "x$critical" = "x0" || exit $err_compile_fail
    move_logfile
  fi
}

check_admin() {
  if test "x$module" != xkde-common -a "x$CVSCLIENT" = xcvs -a ! -e admin/Makefile.common; then
    if test -d ../kde-common; then
      ln -s ../kde-common/admin
      echo "Making link to ../kde-common/admin" >> $logfile 2>&1
    else
      echo "WARNING: Could not find admin/ subdirectory for this module!" >> $logfile 2>&1
    fi
  fi
}

check_libltdl() {
  if test "x$module" == xarts -a ! -e libltdl/Makefile.am; then
    if test -d ../kdelibs; then
      ln -s ../kdelibs/libltdl
      echo "Making link to ../kdelibs/libltdl" >> $logfile 2>&1
    else
      echo "WARNING: Could not find libltdl/ subdirectory for this module!" >> $logfile 2>&1
    fi
  fi
}

docvsupdate=1
domakefilecvs=1
doconfigure=1
dousage=0
specifiedModules=""
# Parse args
#
while [ $# != 0 ]
do
  arg=$1
  case "$arg" in
    --help)
        dousage=1
        break ;;
    --version)
        # Show version
        echo "$0 version 0.8.15"
        exit $err_no_error ;;
    --no-update)
        docvsupdate=0 ;;
    --incremental) ### This is experimental, don't use
        domakefilecvs=0
        doconfigure=0 ;;
    -*)
        echo "Unhandled option $arg"
        dousage=1
        break ;;
    *) 
        specifiedModules="$specifiedModules $arg" ;;
  esac
  shift
done

# Show help info
if test "$dousage" -eq 1; then
  echo "usage: $0 [--options] [modules]"
  echo "--no-update    do not update from cvs"
  echo "--help         this message"
  exit $err_no_error
fi

# Get current configuration, bail out if it couldn't be found.
#
if !(test -e ./kde-buildrc); then
  cd `dirname $0`
  if !(test -e ./kde-buildrc); then
    echo "ERROR: Cannot load configuration file ./kde-buildrc!"; exit $err_no_config
  fi
fi
. ./kde-buildrc

# Make sure some paths are according to the rc file. Note that there are AFAIK
# UNIX flavors which don't support LD_LIBRARY_PATH
PATH=$QTDIR/bin:$KDEDIRS/bin:$PATH
MANPATH=$QTDIR/doc/man:$MANPATH
LD_LIBRARY_PATH=$KDEDIRS/lib:$QTDIR/lib:$LD_LIBRARY_PATH

if test -z "$MAKE"; then
  MAKE=make
fi

if test -n "$specifiedModules"; then
   modules=$specifiedModules
else
   if test "x$ONLYLISTEDMODULES" = xyes; then
      if test "x$USEKDESUPPORT" = xyes; then
          modules="kdesupport $critical_modules $KDEMODULES"
      else
          modules="$critical_modules $KDEMODULES"
      fi
   else

     # This generates in 'modules' a list of the modules which shall be updated.
     #
     potential_modules=`find $KDESRCDIR -type d -mindepth 1 \
         -maxdepth 1 -follow | sed -e "s@.*/?*@@"`
     for module in $potential_modules; do
       if test -d $KDESRCDIR/$module/CVS -a -w $KDESRCDIR/$module \
             && !(echo $EXCLUDE | grep -q $module); then
         modules="$modules $module"
       fi
     done
  fi
fi

# Various checks to ensure that the user didn't specify invalid data which
# would make our script break.
#
if test "x$CVSCLIENT" != xcvs -a "x$CVSCLIENT" != xcvsup; then
  echo "ERROR: Invalid CVS type specified, valid types are 'cvs' and 'cvsup'!"; exit $err_cvsclient_fail
fi
if test "x$KDELOGDIR" != x -a ! -d "$KDELOGDIR"; then
  if ! mkdir -p "$KDELOGDIR" > /dev/null 2>&1; then
    echo "WARNING: Could not create logfile-directory."
    echo "WARNING: Logfile generation deactivated."
    KDELOGDIR=""
  fi
else
  if test "x$KDELOGDIR" != x -a ! -w "$KDELOGDIR"; then
    echo "WARNING: Could not obtain write access to specified logfile-directory."
    echo "WARNING: Logfile generation deactivated."
    KDELOGDIR=""
  fi
fi
test "x$KDELOGDIR" != x && str_error="$str_error\x00a\x00d\x020\x020Check the logfile in $KDELOGDIR for further information."
if test ! -d "$KDESRCDIR"; then
  echo "ERROR: Invalid source directory specified!"; exit $err_inv_kdesrcdir
fi
if test ! -d "$QTDIR" -o ! -d "$QTDIR/lib" -o ! -d "$QTDIR/bin" -o ! -d "$QTDIR/include"; then
  echo "ERROR: Invalid Qt directory specified!"; exit $err_inv_qtdir
fi

if test "x$COMPRESSLOGS" = xyes; then
  if which bzip2 > /dev/null 2>&1; then
    cmd_compress="`which bzip2` -f "
  else
    if which gzip > /dev/null 2>&1; then
      cmd_compress="`which gzip` -f "
    else
      echo "WARNING: Neither bzip2 nor gzip was found, disabling compression of logfiles."
      cmd_compress=""
    fi
  fi
else
  cmd_compress=""
fi

# Clean the installation directory if selected.
#
if test "x$INSTALLFROMSCRATCH" = xyes; then
  if test ! -w $KDEDIRS; then
    echo "Enter the root password to clean the installation directory."
    echo "WARNING: All files and directories in $KDEDIRS will be deleted!"
    echo -n "Please enter root "
    su -c "rm -rf $KDEDIRS/*"
  else
    rm -rf $KDEDIRS/*
  fi
fi

# Optionally activate cheap tweaks.
#
if test "x$TWEAKCOMPILE" = xyes; then
  CFLAGS="-O0"
  CXXFLAGS="-O0"
  export CFLAGS CXXFLAGS
fi

# This checks whether the user wants a certain branch and generates the
# command line. For cvsup users it even generates a supfile. :-)
#
if test "x$CVSCLIENT" = xcvs; then
  cmd_update="cvs up"
  if test "x$BRANCH" != x; then
    cmd_update="$cmd_update -dPr $BRANCH"
  elif test "$BRANCH" = "HEAD"; then
    cmd_update="$cmd_update -dPA"
  else
    cmd_update="$cmd_update -dP"
  fi
  if test "x$CVSROOT" = x; then
    if test "x$ACCOUNT" = x; then
      CVSROOT=":pserver:anonymous@anoncvs.kde.org:/home/kde"
    else
      CVSROOT=":pserver:$ACCOUNT@cvs.kde.org:/home/kde"
    fi
    export CVSROOT
  fi
else
  if test "x$CVSUPSERVER" = x; then
    echo "ERROR: No cvsup server specified!"
    exit $err_inv_cvsup_server
  fi
  supfile=`mktemp /tmp/$0.XXXXXX`
  if [ $? -ne 0 ]; then
    echo "ERROR: Could not create temporare cvsup configuration file in /tmp!"
    exit $err_no_temp_supfile
  fi
  cmd_update="cvsup $supfile"
  echo "*default host=$CVSUPSERVER" >> $supfile
  echo "*default base=$KDESRCDIR" >> $supfile
  echo "*default prefix=$KDESRCDIR" >> $supfile
  echo "*default release=cvs" >> $supfile
  echo "*default delete" >> $supfile
  echo "*default compress" >> $supfile
  if test "x$BRANCH" != x; then
    echo "*default tag=$BRANCH" >> $supfile
  else
    echo "*default tag=." >> $supfile
  fi
  echo "*default use-rel-suffix" >> $supfile
  for module in $modules; do
    if test -d $KDESRCDIR/$module/CVS && !(echo $EXCLUDE | grep -q $module); then
      echo "$module" >> $supfile
    fi
  done
fi

# Guess what? We'll finally start checking out the modules. :-)
#
for module in $modules; do
  if test "x$KDELOGDIR" != x; then
    rm -f $KDELOGDIR/$module-build-*
    rm -f $KDELOGDIR/$module-failed-*
    logfile="$KDELOGDIR/$module-build-$dateformat"
    echo "================================================================================" > $logfile
    echo "Build log of module $module, started on `date +%c`" >> $logfile
    echo "================================================================================" >> $logfile
    echo "" >> $logfile
  fi
  if ! cd $KDESRCDIR/$module; then
    echo "WARNING: Could not change into directory $KDESRCDIR/$module."
    echo "Update for module $module skipped."
  else
    set_title "Updating module $module..."
    if test "$docvsupdate" -eq 0; then
        echo -n "Checking module $module (no cvs update)..."
        cmd_update_raw="echo Warning: no cvs update of module $module - as requested"
    else
        echo -n "Updating module $module..."
        # Hack for the kdemultimedia/noatun/noatun problem
        if test "x$module" = xkdemultimedia -a "x$KDEBUILDDIR" = x -a ! -d noatun/noatun; then
            rm -f noatun/noatun
        fi
        cmd_update_raw="$cmd_update"
    fi

    if test "x$KDELOGDIR" != x; then
        echo "-> Update $cmd_update <---------------------------------------------------------------" >> $logfile
        cmd_update_raw="$cmd_update_raw >> $logfile 2>&1"
        starttime=`date +%s`
    fi
    
    if eval ${cmd_update_raw}; then

      if test "x$module" != xkde-common -a "x$CVSCLIENT" = xcvs -a ! -e admin/Makefile.common; then
        check_admin
      fi
      if test "x$CVS_CLEAN" = xyes -a -e admin/Makefile.common; then
        cmd_make_cvs_clean="$MAKE -f admin/Makefile.common cvs-clean"
        test "x$KDELOGDIR" != x && cmd_make_cvs_clean="$cmd_make_cvs_clean >> $logfile 2>&1"
      fi
    
      if eval ${cmd_make_cvs_clean}; then
        if test -e Makefile.cvs; then
          check_admin
          check_libltdl
          cmd_make_makefile_cvs="$MAKE -f Makefile.cvs"
          test "x$NICECOMPILE" = xyes && cmd_make_makefile_cvs="nice $cmd_make_makefile_cvs"
          if test -f Makefile.am.in && test -n "$USE_UNSERMAKE"; then
              export UNSERMAKE=$USE_UNSERMAKE
          else
              unset UNSERMAKE || :
          fi
          if test $domakefilecvs -eq 0 -a -e "Makefile.in"; then
            cmd_make_makefile_cvs="echo Warning: no Makefile.cvs for module $module - as requested"
          fi
          test "x$KDELOGDIR" != x && cmd_make_makefile_cvs="$cmd_make_makefile_cvs >> $logfile 2>&1"
          if eval ${cmd_make_makefile_cvs}; then
            echo "$str_okay"
          else
            echo -e "$str_error"
          fi
        fi
      else
        echo -e "$str_error"
      fi
      if test "x$KDELOGDIR" != x; then
        compute_time
        echo "--------------------------------------------------------------------------------" >> $logfile
        echo "Time needed for updating module $module: $hours:$minutes:$seconds" >> $logfile
        echo "" >> $logfile
      fi
    else
      echo -e "$str_error"
    fi
  fi
done

for module in $modules; do
  critical=0
  for m in $critical_modules; do if test $m = $module; then critical=1; fi; done

  if ! cd $KDESRCDIR/$module; then
    if test "x$critical" = "x1"; then
      echo "ERROR: Could not change into directory $KDESRCDIR/$module!"
      exit $err_change_into_mod_dir
    else
      echo "WARNING: Could not change into directory $KDESRCDIR/$module."
      echo "WARNING: Skipping module $module."
    fi
  else
    cd $KDESRCDIR/$module

    # Check whether 'make -f Makefile.cvs' has been called.
    #
    if test ! -e "Makefile.in"; then
      if test "x$critical" = "x1"; then
        echo "ERROR: Please execute '$MAKE -f Makefile.cvs' first for this module!"
        exit $err_no_makefile_in
      else
        echo "WARNING: '$MAKE -f Makefile.cvs' seems not to be executed for this"
        echo "WARNING: module, skipping compilation."
      fi
    else
      echo "Building module: $module"

      if test -n "$KDEBUILDDIR"; then

        if test "x$BUILD_CLEAN" = "xyes"; then
	   if test -d $KDEBUILDDIR/$module; then
	     echo -n "  Removing build dir..."
	     set_title "Removing build dir for module $module..."
	     rm -rf $KDEBUILDDIR/$module
	     echo " done"
	   fi
	fi
        mkdir -p $KDEBUILDDIR/$module
        cd $KDEBUILDDIR/$module
      fi
      # Configure the module.
      #
      echo -n "  Configuring..."
      set_title "Configuring module $module..."
      configureflags=$CONFIGUREFLAGS;
      varname="CONFIGUREFLAGS_`echo $module|tr a-z A-Z|sed "s/\(.*\)-[0-9]*/\1/g"`"; # e.g. CONFIGUREFLAGS_ARTS etc.
      varvalue=`eval echo '$'$varname`
      test -n "$varvalue" && configureflags="$configureflags $varvalue"
      cmd_configure="$KDESRCDIR/$module/configure $configureflags --prefix=$KDEDIRS --with-qt-libs=$QTDIR"
      test "$NICECOMPILE" = yes && cmd_configure="nice $cmd_configure"
      configure_okay="$str_okay"
      if test $doconfigure -eq 0 -a -e "Makefile"; then
        cmd_configure="echo Warning: no configure for module $module - as requested"
        configure_okay="skipped."
      fi
      if test -n "$KDELOGDIR"; then
        logfile="$KDELOGDIR/$module-build-$dateformat"
        echo "-> Configuration <--------------------------------------------------------------" >> $logfile
        cmd_configure="$cmd_configure >> $logfile 2>&1"
        starttime=`date +%s`
      fi

      if eval ${cmd_configure}; then
        if test "x$KDELOGDIR" != x; then
          compute_time
          echo "--------------------------------------------------------------------------------" >> $logfile
          echo "Time needed for configuration of module $module: $hours:$minutes:$seconds" >> $logfile
          echo "" >> $logfile
        fi
        echo -e "$configure_okay"

        # Compile the module.
        #
        echo -n "  Compiling..."
        set_title "Compiling module $module..."
	test -f $KDESRCDIR/$module/Makefile.am.in && test -n "$USE_UNSERMAKE" && use_compile_target=yes
	if test "$use_compile_target" = yes && test -n "$MAKE_OPTS_COMPILE"; then
	    cmd_make="$MAKE $MAKE_OPTS_COMPILE"
	else
	    cmd_make="$MAKE $MAKE_OPTS"
	fi
        test "x$critical" = "x0" && cmd_make="$cmd_make -k"
        test "x$NICECOMPILE" = xyes && cmd_make="nice $cmd_make"
        test "$use_compile_target" = yes && cmd_make="$cmd_make compile"

        if test "x$KDELOGDIR" != x; then
          echo "-> Compilation <----------------------------------------------------------------" >> $logfile
          echo "-> $cmd_make <-" >> $logfile
          cmd_make="$cmd_make >> $logfile 2>&1"
          starttime=`date +%s`
        fi
       
        eval ${cmd_make}
	      compile_ret=$?

        if test $compile_ret = 0; then
          if test "x$KDELOGDIR" != x; then
            compute_time
            echo "--------------------------------------------------------------------------------" >> $logfile
            echo "Time needed for compilation of module $module: $hours:$minutes:$seconds" >> $logfile
            echo "" >> $logfile
          fi
          echo -e "$str_okay"
	 
	  # Link the module
	  if test "$use_compile_target" = yes; then
	    echo -n "  Linking..."
	    set_title "Linking module $module..."
	    cmd_make="$MAKE $MAKE_OPTS"
            test "x$critical" = "x0" && cmd_make="$cmd_make -k"
            test "x$NICECOMPILE" = xyes && cmd_make="nice $cmd_make"
	    
	    if test "x$KDELOGDIR" != x; then
               echo "-> Linking <----------------------------------------------------------------" >> $logfile
	       echo "-> $cmd_make <-" >> $logfile
               cmd_make="$cmd_make >> $logfile 2>&1"
               starttime=`date +%s`
            fi

	    eval ${cmd_make}
	    link_ret=$?
	    if test "$link_ret" = 0; then
              if test "x$KDELOGDIR" != x; then
                compute_time
                echo "--------------------------------------------------------------------------------" >> $logfile
                echo "Time needed for linkage of module $module: $hours:$minutes:$seconds" >> $logfile
                echo "" >> $logfile
              fi
              echo -e "$str_okay"
	    else
		  compile_ret=$link_ret
	    fi
          fi
	fi

	if test $compile_ret = 0; then
	      
          # Install the module.
          #
          cmd_make_install="$MAKE"
          test "x$critical" = "x0" && cmd_make_install="$cmd_make_install -k"
          test "x$NICECOMPILE" = xyes && cmd_make_install="nice $cmd_make_install"
          cmd_make_install="$cmd_make_install install"
          if test ! -w $KDEDIRS; then
            echo -n "  To install module $module, please enter the root "
            su -c "$cmd_make_install"
          else
            install_module
          fi
        else
          echo -e "$str_error"
          test "x$cmd_compress" != x && eval "$cmd_compress $logfile"
          test "x$critical" = "x0" || exit $err_compile_fail
          # Attempt to display the actual error
          grep -B3 Error $logfile | head -2
          move_logfile
        fi
      else
        echo -e "$str_error"
        test "x$cmd_compress" != x && eval "$cmd_compress $logfile"
        test "x$critical" = "x0" || exit $err_compile_fail
        move_logfile
      fi
    fi
  fi
done

set_title "KDE build finished."

exit $err_no_error

=head1 NAME

kde-build - Updates and recompiles a tree of KDE CVS modules

=head1 SYNOPSIS

        kde-build

=head1 DESCRIPTION

kde-build has been designed to keep a local copy of several KDE CVS
modules up to date and recompile them. Those modules have to be saved in a
common directory, e.g. something like

    ~/kde-src/
      |
      +-> kdelibs/
      |
      +-> kdebase/
      |
      \-> kdenetwork/

In this case, the KDE source directory would be ~/kde-src/. The script will
take care of compiling them in the correct order, checks for dependencies
and resolves them as far as possible.

Please not that, prior to first invokation of the script, the configuration
file 'F<kde-buildrc>' has to be modified to reflect the local environment,
such as paths etc.

=head1 RETURN VALUE

The following error codes are returned by the script.

0 - No error seems to have occured.

1 - The script could not change into the directory of a module.

2 - The script could not open the file 'Makefile.in' of a module.

3 - The configuration of a module failed.

4 - The compilation of a module failed.

5 - The installation of a module failed.

6 - An invalid source directory was specified.

7 - An invalid Qt directory was specified.

8 - An invalid CVS client was specified.

9 - No cvsup server was specified.

10 - The temporary CVSUP configuration file couldn't be created.

11 - The configuration file F<kde-buildrc> couldn't be loaded.

=head1 EXAMPLES

        cd ~/scripts/; vi ./kde-buildrc; ./kde-build

=head1 BUGS

Lots, mostly that the script wasn't written with portability in mind
and therefore won't run very nice on platforms other than Linux.

=head1 TODO

Add a DIAGNOSIS section to this man page.

=head1 AUTHOR

Frerich Raabe <raabe@kde.org>

=cut

# vim:et:ts=2:sw=2
