#!/bin/bash set -e ############################################### ### ### check for environment variables ### if test -z $MAKE; then MAKE=make fi ############################################### ### ### read lib ### canonicalname(){ if test $# -ne 1; then echo Usage: canonicalname path >&2 return 1 fi file="`eval echo $1`" # expand ~ if test ! -e "$file"; then echo $file: file not found >&2 return 1 fi # if this is a symlink, then follow the symlink if test -L "$file"; then fdir="`dirname \"$file\"`" flink="`readlink \"$file\"`" if test -e "$flink"; then # these are absolute links, or links in the CWD canonicalname "$flink" else canonicalname "$fdir/$flink" fi else # if this is a file, then remember the filename and # canonicalize the directory name if test -f "$file"; then fdir="`dirname \"$file\"`" fname="`basename \"$file\"`" fdir="`canonicalname \"$fdir\"`" echo "$fdir/$fname" fi # if this is a directory, then create an absolute # directory name and we are done if test -d "$file"; then (cd "$file"; pwd) fi fi } canonicalpath(){ if test $# -ne 1; then echo Usage: canonicalpath path >&2 return 1 fi dirname `canonicalname "$1"` } checkdebug () { while test $# -gt 0; do if test x$1 = x--debug; then echo yes return fi shift done echo no } DEBUG=`checkdebug $@` if test "x$DEBUG" = "xyes"; then set -x set -v fi export COMMAND_DIR="`canonicalpath $0`" export RESUME_FILE="$HOME/.dune.resume" # Read the modules find part . "$COMMAND_DIR/dunemodules.inc" # create PKG_CONFIG_PATH for installed dune modules export PKG_CONFIG_PATH="$PKG_CONFIG_PATH:`canonicalpath $0`/../lib/pkgconfig" ############################################### # # for each module load the $CONTROL script part and run $command # # parameters: # $1 command to execute # build_modules() { local command="$1" shift local runcommand=run_$command modules="$@" for module in $modules ; do echo $module done > $RESUME_FILE for module in $modules; do local path=$(eval "echo \$PATH_${module}") eval echo "--- calling $command for \$NAME_${module} ---" if ! ( set -e cd "$path" export module eval_control $runcommand $path/$CONTROL ); then eval echo "--- Failed to build \$NAME_${module} ---"; exit 1; fi modules_togo=`cat $RESUME_FILE` for module_togo in $modules_togo ; do if test x$module_togo != x$module ; then echo $module_togo fi done > $RESUME_FILE eval echo "--- \$NAME_${module} done ---" done } # # load command options from an opts file # the name of the opts file is stored in the global variable $DUNE_OPTS_FILE # # parameters: # $1 command # load_opts() { local command=$1 local COMMAND=$(echo $command | tr '[:lower:]' '[:upper:]') CMD_FLAGS="$(eval echo \$${COMMAND}_FLAGS)" local CMD_FLAGS_FROM_FILE="" BUILDDIR=$DUNE_BUILDDIR if test "x$DUNE_OPTS_FILE" != "x"; then BUILDDIR="$(eval BUILDDIR=""; . $DUNE_OPTS_FILE; eval echo \$BUILDDIR)" CMD_FLAGS_FROM_FILE="$(eval ${COMMAND}_FLAGS=""; . $DUNE_OPTS_FILE; eval echo \$${COMMAND}_FLAGS)" fi if test -n "$CMD_FLAGS_FROM_FILE"; then echo "----- using default flags \$${COMMAND}_FLAGS from $DUNE_OPTS_FILE -----" CMD_FLAGS=$CMD_FLAGS_FROM_FILE elif test -n "$CMD_FLAGS"; then echo "----- using default flags \$${COMMAND}_FLAGS from environment -----" fi } ############################################### ### ### Commands ### # check wheteher the parameter is valid command or not is_command() { eval ' case "$1" in '`echo $COMMANDS | sed -e 's/ / | /g'`') return 0 ;; *) return 1 ;; esac' } # list of all dunecontrol commands COMMANDS="update autogen configure make all exec status svn" # help string for the commands update_HELP="updated all modules from the repository" autogen_HELP="run the autogen.sh script for each module" configure_HELP="run configure for each module" make_HELP="run make for each module" all_HELP="\trun 'autogen', 'configure' and 'make' command for each module" exec_HELP="execute an arbitrary command in each module directory" status_HELP="show vc status for all modules" svn_HELP="\trun svn command for each svn managed module" # # setup command proxies # call will be forwarded to run_default_$command # for command in $COMMANDS; do eval "run_$command () { run_default_$command; }" done # # default implementations for commands... # these can be overwritten in the $CONTROL files # run_default_exec () { bash -c "eval $CMD_FLAGS"; } run_default_status () { local verbose=0 local update="" for i in $CMD_FLAGS; do if eval test "x$i" = "x-v"; then verbose=1; fi if eval test "x$i" = "x-vv"; then verbose=2; fi if eval test "x$i" = "x-u"; then update="-u"; fi done # is out output connected to a tty? if test -t 1; then blue="\e[1m\e[34m" green="\e[1m\e[32m" red="\e[1m\e[31m" reset="\e[0m\e[0m" fi if test $verbose -eq 1; then svn status $update | grep -E "^M|^A|^D|^C|^U" elif test $verbose -eq 2; then svn status $update fi name="$(eval echo \$NAME_$module)" changed=$(svn status | grep -E "^M|^A|^D" | wc -l) collisions=$(svn status | grep -E "^C"| wc -l) pending=$(svn status $update | grep -E "^...... \* " | wc -l) color=$green text="no changes" if [ $changed -eq 0 ]; then true elif [ $changed -eq 1 ]; then color=$blue; text="1 change" else color=$blue; text="$changed changes" fi if [ $pending -eq 0 ]; then true elif [ $pending -eq 1 ]; then color=$blue; text="$text, 1 update pending" else color=$blue; text="$text, $pending updates pending" fi if [ $collisions -eq 0 ]; then true elif [ $collisions -eq 1 ]; then color=$red text="$text, 1 collision" else color=$red text="$text, $count collisions" fi echo -e "$color[$text]$reset $name" } run_default_update () { DUNELINK=0 if test -L dune; then rm dune DUNELINK=1 fi if test -d .svn; then svn update elif test -d CVS; then cvs update -dP else echo "WARNING: $module is not under a known version control system." echo " We support svn and cvs." fi if test "$DUNELINK" != 0 && ! test -d dune; then echo "WARNING: $module is using the deprecated dune symlink" ln -s . dune fi } run_default_autogen () { PARAMS="$CMD_FLAGS" local M4_PATH="" if test -f configure.ac && \ ( test -d .svn || test -d .git || test -d CVS || test -f stamp-vc ); then for m in $FOUND_MODULES; do path=$(eval "echo \$PATH_$m") MODULE_PATHS="$MODULE_PATHS$path " done if test -f autogen.sh; then eval echo "WARNING: \$NAME_$module contains obsolete autogen.sh," \ >&2 echo " dune-autogen is used instead." >&2 fi eval "$COMMAND_DIR/dune-autogen" "$MODULE_PATHS" "$PARAMS" || exit 1 else echo Skipping dune-autogen fi } run_default_configure () { PARAMS="$CMD_FLAGS" if test -x configure; then ACLOCAL_FLAGS="-I ." MY_MODULES= # get dependencies & suggestions sort_modules $module for m in $MODULES; do if test x$module = x$m; then continue; fi # skip myself path=$(eval "echo \$PATH_$m") name=$(eval "echo \$NAME_$m") if test -d "$path/m4"; then ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I $path/m4" fi if test -d "$path/share/aclocal"; then ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I $path/share/aclocal" fi if test -d "$path/$BUILDDIR"; then PARAMS="$PARAMS \"--with-$name=$path/$BUILDDIR\"" else PARAMS="$PARAMS \"--with-$name=$path\"" fi done if test "x$HAVE_duneweb" == "xyes"; then PARAMS="$PARAMS \"--with-duneweb=$PATH_duneweb\"" fi PARAMS="$PARAMS ACLOCAL_AMFLAGS=\"$ACLOCAL_FLAGS\"" echo ./configure "$PARAMS" # create build directory of requested if test -n "$BUILDDIR"; then test -d "$BUILDDIR" || mkdir "$BUILDDIR" SRCDIR="$PWD" cd "$BUILDDIR" eval "$SRCDIR/configure" "$PARAMS" || exit 1 else eval ./configure "$PARAMS" || exit 1 fi else if test -f configure.in || test -f configure.ac; then echo "ERROR: configure.[in|ac] found, but configure missing." >&2 echo "Did you forget to run autoconf?" >&2 echo "Perhaps you didn't update your project to" >&2 echo "the latest buildsystem changes (FS#382)." >&2 echo "If your project is under version control, please make sure" >&2 echo "you have a file stamp-vc in you top_srcdir." >&2 exit 1 fi fi } run_default_make () { test ! -d "$BUILDDIR" || cd "$BUILDDIR" PARAMS="$CMD_FLAGS" echo make "$PARAMS" eval $MAKE "$PARAMS" } run_default_all () { for cmd in autogen configure make; do eval echo "--- calling $cmd for \$NAME_${module} ---" load_opts $cmd run_$cmd done } run_default_svn () { if test -d .svn; then PARAMS="$CMD_FLAGS" eval svn "$PARAMS" fi } ############################################### ### ### main ### onfailure() { echo "Execution of $(basename $0) terminated due to errors!" >&2 exit 1 } usage () { ( echo "Usage: $(basename $0) [OPTIONS] COMMANDS [COMMAND-OPTIONS]" echo "" echo " Execute COMMANDS for all Dune modules found. All entries in the" echo " DUNE_CONTROL_PATH variable are scanned recursively for Dune modules." echo " If DUNE_CONTROL_PATH is empty, the current directory is scanned." echo " Dependencies are controlled by the $CONTROL files." echo "" echo "OPTIONS:" echo " -h, --help show this help" echo " --debug enable debug output of this script" echo " --module=mod only apply the actions on module mod" echo " and all modules it depends on" echo " --only=mod only apply the actions on module mod" echo " and not the modules it depends on" echo " --current only apply the actions on the current module," echo " the one whose source tree we are standing in" echo " --resume resume a previous run (only consider the modules" echo " not built successfully on the previous run)" echo " --opts=FILE load default options from FILE" echo " (see dune-common/doc/example.opts)" echo " --builddir=NAME make out-of-source builds in a subdir NAME." echo " This directory is create inside each module." echo " --[COMMAND]-opts=opts set options for COMMAND" echo " (this is mainly useful for the all COMMAND)" echo "COMMANDS:" echo " Colon-separated list of commands. Available commands are:" printf " \`help'\tguess what :-)\n" printf " \`print'\tprint the list of modules sorted after their dependencies\n" for i in $COMMANDS; do printf " \`$i'\t$(eval echo \$${i}_HELP)\n" done printf " \`export'\trun eval \`dunecontrol export\` to save the list of\n" printf " \t\tdune.module files to the DUNE_CONTROL_PATH variable\n" echo ) >&2 } # create the module list create_module_list() { find_modules_in_path if test "x$SEARCH_MODULES" != "x"; then sort_modules $SEARCH_MODULES else sort_modules $MODULES fi if test "x$ONLY" != x; then export MODULES="$ONLY" fi } # print the module list print_module_list() { DELIM=$1 shift while test -n "$2"; do echo -n "$(eval echo \$NAME_$1)$DELIM" shift done echo -n "$(eval echo \$NAME_$1)" } trap onfailure EXIT # clear variables export SEARCH_MODULES="" export MODULES="" export ONLY="" # parse commandline parameters while test $# -gt 0; do # get option option=$1 # get args set +e # stolen from configure... # when no option is set, this returns an error code arg=`expr "x$option" : 'x[^=]*=\(.*\)'` set -e # switch case "$option" in --opts=*) if test "x$arg" = "x"; then usage echo "ERROR: Parameter for --opts is missing" >&2 echo >&2 exit 1; fi DUNE_OPTS_FILE=`canonicalname $arg` if ! test -r "$DUNE_OPTS_FILE"; then usage echo "ERROR: could not read opts file \"$DUNE_OPTS_FILE\"" >&2 echo >&2 exit 1; fi ;; --*-opts=*) optcmd=`expr "x$option=" : 'x--\([^-]*\)-opts=.*'` if is_command $optcmd; then COMMAND=`echo $optcmd | tr '[:lower:]' '[:upper:]'` export ${COMMAND}_FLAGS="$arg" else usage echo "ERROR: unknown option \"$option\"" >&2 exit 1 fi ;; -h|--help) command=help break ;; -p|--print) command=print break ;; --module=*) if test "x$arg" = "x"; then usage echo "ERROR: Parameter for --module is missing" >&2 echo >&2 exit 1; fi for a in `echo $arg | tr ',' ' '`; do export NAME_`fix_variable_name $a`="$a" fix_and_assign MODULE "$a" export SEARCH_MODULES="$SEARCH_MODULES $MODULE" done ;; --only=*) if test "x$arg" = "x"; then usage echo "ERROR: Parameter for --only is missing" >&2 echo >&2 exit 1; fi for a in `echo $arg | tr ',' ' '`; do export NAME_`fix_variable_name $a`="$a" fix_and_assign MODULE "$a" export SEARCH_MODULES="$SEARCH_MODULES $MODULE" export ONLY="$ONLY $MODULE" done ;; --builddir=*) export DUNE_BUILDDIR=$arg ;; --no-builddir) export DUNE_BUILDDIR="" ;; --skipversioncheck) export SKIPVERSIONCHECK=yes ;; --current) while ! test -f $CONTROL; do cd .. if test "$OLDPWD" = "$PWD"; then echo "You are not inside the source tree of a DUNE module." >&2 exit -1 fi done; parse_control $PWD/$CONTROL fix_and_assign MODULE "$module" export SEARCH_MODULES="$SEARCH_MODULES $MODULE" export ONLY="$ONLY $MODULE" export HAVE_${module}= ;; --resume) if test -s $RESUME_FILE ; then RESUME="`cat $RESUME_FILE`" for a in $RESUME ; do export NAME_`fix_variable_name $a`="$a" fix_and_assign MODULE "$a" export SEARCH_MODULES="$SEARCH_MODULES $MODULE" export ONLY="$ONLY $MODULE" done else echo "Error: No previous run to resume. ('$RESUME_FILE' is empty or does not exist)" exit 1 fi ;; --debug) true ;; # ignore this option, it is handled right at the beginning --*) usage echo "ERROR: Unknown option \`$option'" >&2 echo >&2 exit 1 ;; *) break ;; esac shift done # we assume there should be a command... if test "x$1" = "x"; then usage exit 1 fi while test $# -gt 0; do # get command command=$1 shift # only load other parameters load_opts NONE # get command options CMD_FLAGS= while test $# -gt 0 && test "$1" != ":"; do COMMAND=$(echo $command | tr '[:lower:]' '[:upper:]') # setup paramter list CMD_FLAGS="$CMD_FLAGS \"$1\"" shift done if test -z "$CMD_FLAGS"; then load_opts $command else # disable usage of opts file if test "x$DUNE_OPTS_FILE" != "x"; then echo "WARNING: commandline parameters will overwrite setting in opts file \"$DUNE_OPTS_FILE\"" fi fi # skip command delimiter if test "$1" = ":"; then shift; fi case "$command" in print) create_module_list eval "print_module_list ' ' $MODULES" echo >&2 ;; export) create_module_list DUNE_CONTROL_PATH="" for mod in $MODULES; do if test x != x$DUNE_CONTROL_PATH; then export DUNE_CONTROL_PATH="$DUNE_CONTROL_PATH:$(eval echo \$PATH_$mod/dune.module)" else export DUNE_CONTROL_PATH="$(eval echo \$PATH_$mod/dune.module)" fi done echo export DUNE_CONTROL_PATH=$DUNE_CONTROL_PATH ;; m4create) find_modules_in_path mainmod=`echo $SEARCH_MODULES` fname="dependencies.m4" name=`eval echo \\${NAME_$mainmod}` version=`eval echo \\${VERS_$mainmod}` maintainer=`eval echo \\${MAIN_$mainmod}` # get dependencies eval deps=\$DEPS_$module #initially remove leading space deps=`echo "$deps" | sed 's/^ *//'` while test -n "$deps"; do #the end of the name is marked either by space, opening paren #or comma depname="${deps%%[ (,]*}" #remove the name and adjacent whitespace deps=`echo "$deps" | sed 's/^[^ (,]* *//'` #check whether there is a dependency version case "$deps" in '('*) deps="${deps#(}" depver="${deps%%)*}" deps="${deps#*)}" ;; *) depver= ;; esac #remove any leading whitespace or commas for te next iteration deps=`echo "$deps" | sed 's/^[, ]*//'` requires="$requires $depname $depver " done # ensure a version number if test "x$version" = "x"; then version="0.0"; fi echo "writing $fname" echo " for $name $version $maintainer" echo " requires $requires" AC_MACRO_DIR="." test ! -d m4 || AC_MACRO_DIR=m4 cat > $fname <<EOF # dependencies.m4 generated by dunecontrol m4_define([DUNE_AC_INIT],[ AC_INIT([$name], [$version], [$maintainer]) AM_INIT_AUTOMAKE([foreign 1.5 tar-pax]) AC_SUBST([DUNE_MOD_VERSION], [$version]) AC_SUBST([DUNE_MOD_NAME], [$name]) AC_SUBST([DUNE_MAINTAINER_NAME], [$maintainer]) DUNE_PARSE_MODULE_VERSION([$name], [$version]) REQUIRES="$requires" AC_SUBST(REQUIRES, [$REQUIRES]) AC_CONFIG_MACRO_DIR([$AC_MACRO_DIR]) ]) AC_DEFUN([DUNE_CHECK_MOD_DEPENDENCIES], [ EOF ### initialize AM_CONDITIONAL for suggestions that were not found for name in $(eval echo \$SUGS_$mainmod); do mod=$(fix_variable_name $name) MOD=`echo $mod | tr [:lower:] [:upper:]` if test "x$(eval echo \$HAVE_$mod)" = "x"; then cat >> $fname <<EOF ### add a conditional check for $name, # just in case the module is not available at autogen time AM_CONDITIONAL([HAVE_${MOD}], false) EOF fi done ### DEPENDENCIES if test "x$SEARCH_MODULES" != "x"; then MODULES=$SEARCH_MODULES fi sort_dependencies $MODULES for mod in $MODULES; do name=`eval echo \\$NAME_$mod` MOD=`echo $mod | tr [:lower:] [:upper:]` cat >> $fname <<EOF ### check dependency $name # invoke checks required by this module AC_REQUIRE([${MOD}_CHECKS]) # invoke check for this module AC_REQUIRE([${MOD}_CHECK_MODULE]) if test x\$with_$mod = xno; then AC_MSG_ERROR([could not find required module _dune_name]) fi EOF done ### sort_suggestions $mainmod for mod in $MODULES; do name=`eval echo \\$NAME_$mod` MOD=`echo $mod | tr [:lower:] [:upper:]` cat >> $fname <<EOF ### check suggestion $name # invoke checks required by this module AC_REQUIRE([${MOD}_CHECKS]) # invoke check for this module AC_REQUIRE([${MOD}_CHECK_MODULE]) if test x\$with_$mod = xno; then AC_MSG_WARN([could not find suggested module _dune_name]) fi EOF done ### # only test for the module if we really define our own checks if test -d m4; then mod=$mainmod name=`eval echo \\$NAME_$mod` MOD=`echo $mod | tr [:lower:] [:upper:]` cat >> $fname <<EOF ### invoke checks for $name AC_REQUIRE([${MOD}_CHECKS]) EOF fi cat >> $fname <<EOF ]) EOF ;; unexport) echo export DUNE_CONTROL_PATH="" ;; help) usage ;; *) if is_command $command; then if test $command == update; then export SKIPVERSIONCHECK=yes; fi create_module_list NAMES="" BUILDMODULES="" for mod in $MODULES; do if test "$(eval echo \$INST_$mod)" != "yes"; then NAMES="$NAMES$(eval echo \$NAME_$mod) " BUILDMODULES="$BUILDMODULES$mod " fi done echo "--- going to build $NAMES ---" build_modules "$command" $BUILDMODULES echo "--- done ---" else usage echo "ERROR: unknown command \"$command\"" >&2 exit 1 fi ;; esac done trap - EXIT