#!/bin/bash
# --
# Copyright (C) CEA, EDF
# Author : Nicolas Crouzet (CEA)
# --
#
# Utility for building Salome Modules
#
# default directory containing sources. Look-up is performed first localy, then in this directory if present.
SRC_ROOT_DIR=
# default directory where you want to put build & install directories. alternative for -i option
INSTALL_ROOT_DIR=
# default building environment file. alternative to --environ= option
ENVIRON_FILE=
# Utilitaire de compilation Salome
#

usage()
{
    echo
    echo Name : SA_build  -  build Salome modules
    echo
    echo "Description : Small utility that automate Salome components building."
    echo "               -> call build_configure in source directories"
    echo "               -> create build and install directories"
    echo "               -> call configure, make, make install from build directories"
    echo "               -> update environment file (only sh syntax is supported)"
    echo
    echo Usage :
    echo
    echo "  SA_build   [modulename(s)]  sourcename(s)  [ options ]"
    echo
    echo "     sourcename(s) are component's source directories and should end up by convention with _SRC"
    echo "     modulename(s) are module directories that contain source directories"
    echo
    echo "    -> A look-up is done to find component's source directories - then building is done"
    echo "        - modulenames are searched localy, then in SRC_ROOT_DIR"
    echo "        - sourcename(s) are searched in modulename(s), or localy if no module name is specified"
    echo "        - if no sourcename is entered, search for modulename_SRC"
    echo
    echo "Options :"
    echo
    echo "  --disable-debug : compilation without debug traces"
    echo "  --batch         : compilation is done in batch mode - no prompting"
    echo "  --environ=path  : set environment file to path (should be absolute)"
    echo "                    this file will be updated with new environment variables. "
    echo "                    it will also be sources if it has sh syntax"
    echo "  --install=path  : set install directory where module building and install is done (should be absolute)"
    echo "  --compile-only -c  : no building and configure - just compile by calling make && make install"
    echo "  --local -l      : look for source directories localy - build and install localy"
    echo "  --sources=src1,src2,...  : for specifying source directories that don't end up with _SRC"
    echo 
    echo
    echo "Examples :"
    echo
    echo "  SA_build  KERNEL"
    echo "    -> compilation of KERNEL/KERNEL_SRC"
    echo "       build is done in KERNEL/KERNEL_BUILD"
    echo "       install is done in KERNEL/KERNEL_INSTALL"
    echo "       environment should be set up correctly before (option --environ not used)"
    echo
    echo "  SA_build  MED_SRC --install=/export/home/SALOME"
    echo "    -> compilation of MED_SRC  (no module name was specified)"
    echo "       build is done in /export/home/SALOME/MED_BUILD"
    echo "       install is done in /export/home/SALOME/MED_INSTALL"
    echo 
    echo "  SA_build  --batch --disable-debug --environ=my_env_products.sh V_3_0_2 KERNEL_SRC GUI_SRC GEOM_SRC MED_SRC MESH_SRC VISU_SRC SUPERV_SRC"
    echo "    -> compilation without prompting (--batch option) of KERNEL_SRC, GUI_SRC, GEOM_SRC, MED_SRC, MESH_SRC, VISU_SRC and SUPERV_SRC"
    echo "       all sources are searched in V_3_0_2 directory "
    echo "       environment is setup using my_env_products.sh file"
    echo "       configure is done with --disable-debug option"
    echo 
    exit 1
}

ask_confirmation()
{
       echo
       echo $1
       echo
       read answer
       case $answer in
	   y* | Y* | o* | O* )   ;;
	   *) exit 1
       esac
}

check_dir()
{
   if [ -d $1 ]
   then
      rm -rf $1/*
      echo "remove $1 content"
   else
      mkdir -p $1
      echo "create $1"
   fi
}

set_environ()
{
   if [ -f $1 ]
   then
       ENVIRON_FILE=$1
   else
       echo -e "\n\nError : environment file $1 NOT FOUND\n"
       exit
   fi
}

compile()
{
    clear
    echo "----------------- Compile ---------------------"
    make 
    if [ $? -eq 0 ]
    then
	echo -e "\n     [OK] Compile : ${module}/${SOURCE_NAME}_SRC" >> $CR
	echo Compilation succeeded : we make install
	echo
	echo "----------------- Install ---------------------"
	make install
	if [ $? -eq 0 ]
	then
	    echo -e "     [OK] Install : ${module}/${SOURCE_NAME}_SRC" >> $CR
        else
	    echo -e "     [KO] Install : ${module}/${SOURCE_NAME}_SRC" >> $CR
	fi    
    else
	echo Compilation failed
	echo -e "\n     [KO] Compile : ${module}/${SOURCE_NAME}_SRC" >> $CR
    fi
}

get_source_dir()
{
    COMPILE_DIR=
    SOURCE_DIRS=
    if [ -d ${LOCAL_DIR}/${module} ]
    then
       COMPILE_DIR=${LOCAL_DIR}/${module}
    elif [ -d ${SRC_ROOT_DIR}/${module} ]
    then
           COMPILE_DIR=${SRC_ROOT_DIR}/${module}
    else
       echo Sorry : ${module} not found!
       usage
    fi
    
    if [ -d ${COMPILE_DIR}/${module}_SRC ]
    then
        SOURCE_DIRS=${COMPILE_DIR}/${module}_SRC
    fi

    for src in $LISTE_SRC
    do
        if [ -d ${COMPILE_DIR}/${src} ]
	then
	   SOURCE_DIRS="$SOURCE_DIRS ${COMPILE_DIR}/${src}"
        fi
    done

}

build_source_dir()
{
   isrc=0 # compteur
   for SOURCE_DIR in ${SOURCE_DIRS}
   do
       (( isrc += 1 ))
       echo -e "\n${isrc})  Compilation dans $SOURCE_DIR \n"
       src=`basename $SOURCE_DIR`
       SOURCE_NAME=${src%_SRC}
       echo " -> Repertoire Source  = ${SOURCE_DIR}"
       echo " -> Component name     = ${SOURCE_NAME}"
       echo " -> Repertoire Build   = ${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_BUILD"
       echo " -> Repertoire Install = ${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_INSTALL"
       echo
       echo
       echo
       if [ $COMPILE_ONLY -eq 1 ]
       then
	   if [ $BATCH_MODE -eq 0 ]
	   then
	       ask_confirmation "Compile ?"
           fi
	   cd ${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_BUILD
	   if [ $? -eq 0 ]
	   then
	       compile
	   else
	       echo "ERROR : build directory ${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_BUILD  not found"
	       echo "        with -c option, build directory should already exist"
	       exit
	   fi    
       else

	   if [ $BATCH_MODE -eq 0 ]
	   then
	       ask_confirmation "build configure and configure ?"
	   fi
	#
	   cd ${SOURCE_DIR}
	   echo
	   echo "----------------- Build configure ---------------------"
	   ./build_configure
	   echo
	   echo "----------------- Configure ---------------------"
	   echo
	   # cre ou vide les rpertoires
	   check_dir ${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_BUILD
	   check_dir ${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_INSTALL
	   cd ${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_BUILD
	   ${SOURCE_DIR}/configure ${OPTIONS_CONFIGURE} --prefix=${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_INSTALL | tee ${TMP_FILE}
	   echo
	   echo "retour configure : $?"
	   echo
	   if [ $BATCH_MODE -eq 0 ]
	   then
	       ask_confirmation "Compile ?"
	   fi
	   export `echo ${SOURCE_NAME}`_ROOT_DIR=${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_INSTALL
	   compile
	   cd $LOCAL_DIR
	   if [ $ENVIRON_FILE ]  &&  [ -f $ENVIRON_FILE ]
	   then
               #  Mise  jour du script d'environnement
	       if [ $BATCH_MODE -eq 1 ]
	       then
		   update_environ ${SOURCE_NAME}_ROOT_DIR ${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_INSTALL ${SOURCE_NAME}_SRC_DIR ${SOURCE_DIR}
	       else
		   echo "Voulez vous mettre mettre  jour le script d'environnement  ${ENVIRON_FILE} ?"
		   echo " (ajouter la variable ${SOURCE_NAME}_ROOT_DIR - une copie de l'ancien script est faite dans un .old)"
		   echo
		   read answer
		   case $answer in
		     y* | Y* | o* | O* )  update_environ ${SOURCE_NAME}_ROOT_DIR ${INSTALL_ROOT_DIR}/${module}/${SOURCE_NAME}_INSTALL ${SOURCE_NAME}_SRC_DIR ${SOURCE_DIR} ;;
		     *) exit 1
		   esac
	       fi
           fi
       fi
   done    
}


# update environment scrip : add or replace ROOT_DIR and SRC_DIR variable for component
update_environ()
{
    cp ${ENVIRON_FILE} ${ENVIRON_FILE}.old
    if [ "${SHELL_EXT}" == "sh" ]
    then
	grep " $1" ${ENVIRON_FILE}.old > /dev/null
	if [ $? -eq 0 ]
	then
	   # if variable is already set, we replace old setting by new one
	   cat ${ENVIRON_FILE}.old | awk -v var_root_dir=$1 -v path=$2 -v src_root_dir=$3 -v src_dir=$4 '
	       $1=="export" && $2 ~ "^"var_root_dir"=" {print "#"$0; $0="export "var_root_dir "=" path}
	       $1=="export" && $2 ~ "^"src_root_dir"=" {print "#"$0; $0="export "src_root_dir "=" src_dir}
	       $1 ~ "^"var_root_dir"=" {print "#"$0; $0=var_root_dir "=" path}
	       $1 ~ "^"src_root_dir"=" {print "#"$0; $0=src_root_dir "=" src_dir}
	       { print $0}'  > ${ENVIRON_FILE}
	else
	   echo -e "##\n#------ ${SOURCE_NAME}-Src ------\nexport $3=$4" >> ${ENVIRON_FILE}
	   echo -e "##\n#------ ${SOURCE_NAME}-Bin ------\nexport $1=$2" >> ${ENVIRON_FILE}
	   if [ -d $2/lib ] && [ ! -d $2/lib/salome ]
	   then
	       # for salome modules, do nothing
	       echo -e "export PYTHONPATH=\${${1}}/bin:\${${1}}/lib:\${PYTHONPATH}" >> ${ENVIRON_FILE}
	   fi
	fi
    else
	grep " $1" ${ENVIRON_FILE}.old > /dev/null
	if [ $? -eq 0 ]
	then
	   # if variable is already set, we replace old setting by new one
	   cat ${ENVIRON_FILE}.old | awk -v var_root_dir=$1 -v path=$2 -v src_root_dir=$3 -v src_dir=$4 '
	       $1=="setenv" && $2 == var_root_dir {print "#"$0; $0="setenv "var_root_dir " " path}
	       $1=="setenv" && $2 == src_root_dir {print "#"$0; $0="setenv "src_root_dir " " src_dir}
	       { print $0}'  > ${ENVIRON_FILE}
	else
	   echo -e "##\n#------ ${SOURCE_NAME}-Src ------\nsetenv $3 $4" >> ${ENVIRON_FILE}
	   echo -e "##\n#------ ${SOURCE_NAME}-Bin ------\nsetenv $1 $2" >> ${ENVIRON_FILE}
	   if [ -d $2/lib ] && [ ! -d $2/lib/salome ]
	   then
	       echo -e "setenv PYTHONPATH \${${1}}/bin:\${${1}}/lib:\${PYTHONPATH}" >> ${ENVIRON_FILE}
	   fi

	fi
    fi
}

###########  Programme Principal #############

# parse arguments

LISTE_SRC=""
OPTIONS_CONFIGURE=""
LISTE_MODULE=""
BATCH_MODE=0
COMPILE_ONLY=0

if [ $# -eq 0 ]
then
    echo
    echo "Pas d'arguments!"
    usage
fi

for arg in $*
do
    case $arg in

      --disable-debug  )   OPTIONS_CONFIGURE="${OPTIONS_CONFIGURE} --disable-debug"   ;;

      --batch)             BATCH_MODE=1   ;;
      
      --environ=*)         set_environ ${arg#--environ=}   ;;

      --install=*)         INSTALL_ROOT_DIR=${arg#--install=}   ;;
      
      --sources=*)         LISTE_SRC="${LISTE_SRC} ${arg#--sources=}"   ;;
      
      --local | -l )       SRC_ROOT_DIR=$PWD ; INSTALL_ROOT_DIR=$PWD ;;

      --compile-only | -c ) COMPILE_ONLY=1 ;;

      *_SRC  )             LISTE_SRC="${LISTE_SRC} ${arg}" ;;

      *)                   LISTE_MODULE="${LISTE_MODULE} ${arg}" ;;

    esac
done

LISTE_SRC=`echo ${LISTE_SRC} | sed "s/,/ /g"`  # replaces ',' by blanks

if [ ! $INSTALL_ROOT_DIR ]
then
    echo Local installation
    INSTALL_ROOT_DIR=$PWD
fi

clear
echo
echo "                  ------------------------------------"
echo "                  | Utilitaire de Compilation Salome |"
echo "                  ------------------------------------"
echo
echo
echo "Liste des modules  parcourir : $LISTE_MODULE"
echo "Liste repertoire  compiler   : $LISTE_SRC"
echo "Options configure             : $OPTIONS_CONFIGURE"
echo "Environment File              : $ENVIRON_FILE"
echo
CR=/tmp/${USER}_SA_build_CR
echo -e "\n" > $CR

if [ $ENVIRON_FILE ]  && [ -f $ENVIRON_FILE ]  # if an existing environment file was specified
then
    # get shell extension
    case ${ENVIRON_FILE##*\.} in 
       bash) SHELL_EXT=sh;;
       ksh)  SHELL_EXT=sh;;
       csh)  SHELL_EXT=csh;;
       sh)   SHELL_EXT=sh;;
       *)    SHELL_EXT=sh;echo WARNING : shell extension not recognized! Assume sh ;;
    esac
    if [ "${SHELL_EXT}" == "sh" ]
    then
    #   if shell syntax is sh, source environment with ENV_FOR_LAUNCH set to 0
        cat ${ENVIRON_FILE} | sed "s/ENV_FOR_LAUNCH=1/ENV_FOR_LAUNCH=0/g" > ${ENVIRON_FILE}.tmp
        source ${ENVIRON_FILE}.tmp
        rm ${ENVIRON_FILE}.tmp
        echo source Environment File with ENV_FOR_LAUNCH=0
    else
        echo "WARNING : environment file has csh extension => cannot source it and assume environment already set."
	echo -e "          (if compilation fails, please set environment before, of choose an sh syntax file)\n"
    fi
else
    echo Warning : Environment File Not Found!
fi

LOCAL_DIR=`pwd`
if [ "$LISTE_MODULE" == "" ]
then
    # no module specified -> lookup for sources localy
    echo lookup for sources localy
    SOURCE_DIRS=
    for src in $LISTE_SRC
    do
        if [ -d ${LOCAL_DIR}/${src} ]
	then
	   SOURCE_DIRS="$SOURCE_DIRS ${LOCAL_DIR}/${src}"
        elif [ -d ${SRC_ROOT_DIR}/${src} ]
	then
	   SOURCE_DIRS="$SOURCE_DIRS ${LOCAL_DIR}/${src}"
        fi
    done
    build_source_dir
else
    for module in $LISTE_MODULE
    do
       echo "----------------- Compilation dans $module ----------------"
       echo
       echo
       get_source_dir
       build_source_dir
       echo
    done
fi

echo -e "\n----------------- Rsum ----------------"
cat ${CR}
