Skip to content
Snippets Groups Projects
install.sh 14.1 KiB
Newer Older
### CONFIGURATION ############################################################
# ROOT_v : require version of ROOT
ROOT_v="5.34/32" # useless variable...
ROOT_v_low="5.34"
ROOT_v_up="5.99"
# flags
ROOTCFLAGS='$(shell ${ROOTSYS}/bin/root-config --cflags)'
ROOTGLIBS='$(shell ${ROOTSYS}/bin/root-config --glibs)'
ROOTLIBS='$(shell ${ROOTSYS}/bin/root-config --libs)'

OMPFLAGS="-fopenmp -DOpenMP"
OMPLIB="-lgomp"

# default value, could be change by argument (see usage for more information)
OMPenable="yes"
libDir="lib"
guiDir="bin"


#_____________________________________________________________________________
# compilator and options
if [[ -z "$CXX" ]]; then
	CXX="g++" # default compiler is g++ with C++11
fi
if [[ -z "$CXXFLAGS" ]]; then
	CXXFLAGS=" -std=c++11 -O2 -g -fPIC -finline-functions" # some optimization flags for GCC, -fPIC and -finline-functions are not avalable for clang
fi
if [[ -z "$CPPFLAGS" ]]; then
	CPPFLAGS=$OMPFLAGS
fi

#_____________________________________________________________________________
# usage
# call if option -h, -help or --help, display usage and quit
function usage ()
{
	cat <<\MANUAL_EOF
###############################################################
############# configures and compiles CLASS V4.1 ##############
###############################################################

Usage: install.sh [VAR=VALUE] [OPTION]
Defaults for the options are specified in brackets.

Configuration:
  -h, --help         display this help and exit
Optional Features:
  --disable-OMP      do not compile with OpenMP support for evolution 
                     [default: enable for gcc version >= 4.1]
  --InstallLib-path=path     Install location of CLASS's libraries [default= $PWD/lib]
  --InstallGui-path=path     Install location of the GUI binary [default= $PWD/gui/bin]

Some influential environment variables:
  CXX         C++ compiler command [default=g++]
  CXXFLAGS    C++ compiler flags, e.g. -I<include dir> if
              you have headers in a nonstandard directory <include dir>
  CPPFLAGS    C++ preprocessor flags, e.g. -D<special flag>


Report bugs to <nicolas.thiolliere@subatech.in2p3.fr>.
MANUAL_EOF

exit 418
}

# colors
# test file descriptor, if it's 1 so this is standard output, else we don't need colors
	# explication : si le script est exéctué normalement, le `file descriptor`
	# de sortie est la sortie standard, donc le `file descriptor` 1, sinon il
	# y a redirection du flux donc il ne faut pas afficher les caractères de
	# changement de couleur. (NB: si la redirection se fait dans le flux
	# d'erreur, il n'y a pas de couleur non plus).
if [[ -t 1 ]]; then
	# sepecial color characters
	c_default="\033[0m";
	c_black="\033[30m";
	c_red="\033[31m";
	c_green="\033[32m";
	c_yellow="\033[33m";
	c_blue="\033[34m";
	c_magenta="\033[35m";
	c_cyan="\033[36m";
	c_lgray="\033[37m";
	c_dgray="\033[90m";
	c_lred="\033[91m";
	c_lgreen="\033[92m";
	c_lyellow="\033[93m";
	c_lblue="\033[94m";
	c_lmagenta="\033[95m";
	c_lcyan="\033[96m";
	c_white="\033[97m";
	c_bold="\033[1m";
	c_default=""; c_black=""; c_red=""; c_green=""; c_yellow=""; c_blue=""; c_magenta=""; c_cyan=""; c_lgray=""; c_dgray=""; c_lred=""; c_lgreen=""; c_lyellow=""; c_lblue=""; c_lmagenta=""; c_lcyan=""; c_white=""; c_bold="";
### ROOT support #############################################################
# root_version
# return the version of ROOT without the patch release (only major.minor)
function root_version () {
	$ROOTSYS/bin/root-config --version | cut -d '/' -f 1
}
#_____________________________________________________________________________
# root_TMVA
# return "ok" if the version of ROOT implement the TMVA feature, "ko" else
function root_TMVA () {
	local features=$($ROOTSYS/bin/root-config --features)
	if [[ "$features" =~ "tmva" ]]; then
		echo "ok"
		echo "ko"
	fi
}

#_____________________________________________________________________________
# test_root
# test version and TMVA feature of ROOT
function test_root () {
	# test version between ROOT_v_low and ROOT_v_up (remove . and patch release)
	if [[ "$(echo ${ROOT_v_low} | tr -d '.')" -le "$(echo $(root_version) | tr -d '.')" ]] && [[ "$(echo $(root_version) | tr -d '.')" -le "$(echo ${ROOT_v_up} | tr -d '.')" ]]; then
		echo -e "[ROOT]  version between ${ROOT_v_low} and ${ROOT_v_up}      [ ${c_green}ok${c_default} ]"
		echo -e "[ROOT]  version between ${ROOT_v_low} and ${ROOT_v_up}      [${c_red}fail${c_default}]"
		echo -e "Please install ROOT-${ROOT_v} :\n\thttps://root.cern.ch/content/release-53432"
		exit 505
	# TMVA
	if [[ $(root_TMVA) == "ok" ]]; then
		echo -e "[ROOT]  TMVA feature                       [ ${c_green}ok${c_default} ]"
	else
		echo -e "[ROOT]  TMVA feature                       [${c_red}fail${c_default}]"
		exit 501
	fi
}

### OMP ######################################################################
# write_OMP_test
# write a small file to test OpenMP feature
function write_OMP_test () {
	echo "#include <omp.h>"
	echo "int main (int,char**) { return 0; }"
}

#_____________________________________________________________________________
# test_OMP
# if OpenMP is enable, test the OMP feature by compiling the small test
function test_OMP () {
	write_OMP_test > test_conf_OMP.cxx
	local isOMPenable=$(g++ -fopenmp  test_conf_OMP.cxx -lgomp  2>&1 | wc -l | awk '{ print $1 }')
	
	if [[ $isOMPenable == 0 ]]; then
		echo -e "[OMP]   enable                             [ ${c_green}ok${c_default} ]"
	else
		echo -e "[OMP]   enable                             [${c_red}fail${c_default}]"
		exit 501
	fi
}

### Makefile.config ##########################################################
# write_makefileconfig
# write Makefile.config file with correct value
function write_makefileconfig () {
	now=`date +%F\ %T`
	echo -e "# autogenerate by $0 ($now)"
	echo -e "
#####################
###### OPEN MP ######
#####################
OMPFLAGS=$OMPFLAGS
OMPLIB=$OMPLIB

#####################
####### ROOT ########
#####################
ROOTCFLAGS:=$ROOTCFLAGS
ROOTGLIBS:=$ROOTGLIBS
ROOTLIBS:=$ROOTLIBS

#####################
##### COMPILER ######
#####################
CXX= ${CXX}
CXXFLAGS= ${CXXFLAGS}

####Installation folder of librairies##
LIBDIR=${PWD}/$LIBDIR
####Installation folder of Gui##
Gui_bin_PATH=$Gui_bin_PATH
"
}
#_____________________________________________________________________________
# make-dirs
# make config, lib, gui/bin directories
function make_dirs () {
	mkdir -p config
	mkdir -p $LIBDIR
	mkdir -p $Gui_bin_PATH
}

#_____________________________________________________________________________
# makefileconfig
# test directories, write Makefile.config, an test it
function makefileconfig () {
	make_dirs

	if [[ -d config ]]; then
		echo -e "[DIR]   build config dir                   [ ${c_green}ok${c_default} ]"
	else
		echo -e "[DIR]   build config dir                   [${c_red}fail${c_default}]"
		exit 507
	fi
	if [[ -d $LIBDIR ]]; then
		echo -e "[DIR]   build lib dir                      [ ${c_green}ok${c_default} ]"
	else
		echo -e "[DIR]   build lib dir                      [${c_red}fail${c_default}]"
		exit 507
	fi
	if [[ -d $Gui_bin_PATH ]]; then
		echo -e "[DIR]   build gui dir                      [ ${c_green}ok${c_default} ]"
	else
		echo -e "[DIR]   build gui dir                      [${c_red}fail${c_default}]"
		exit 507
	fi
	write_makefileconfig > config/Makefile.config
	if [[ -f config/Makefile.config ]]; then
		echo -e "[DIR]   write Makefile.config              [ ${c_green}ok${c_default} ]"
	else
		echo -e "[DIR]   write Makefile.config              [${c_red}fail${c_default}]"
		exit 404
	fi
}

### config.hxx ###############################################################
# write_confighxx
# wrtie config.hxx file
function write_confighxx () {
	local omp="$1"
	if [[ $omp =~ "no" ]]; then
		echo -e "#define omp_get_thread_num() 0"
	else
		echo -e "#include <omp.h>"
	fi
}
#_____________________________________________________________________________
# confighxx
# write and test config/config.hxx file
function confighxx () {
	local omp="$1"
	write_confighxx $omp > config/config.hxx
	if [[ -f config/config.hxx ]]; then
		echo -e "[FILE]  write config.hxx                   [ ${c_green}ok${c_default} ]"
	else
		echo -e "[FILE]  write config.hxx                   [${c_red}fail${c_default}]"
		exit 404
	fi
}
### compilation CLASS ########################################################
# compile_class_lib
# clean, compile and make symbolic links in CLASS
function compile_class_lib () {
	# clean
	make -C source clean   && echo -e "[CLASS] clean source directory             [ ${c_green}ok${c_default} ]" || (echo -e "[CLASS] clean source directory             [${c_red}fail${c_default}]"; exit 418)
	make -C source external_link && echo -e "[CLASS] create external link               [ ${c_green}ok${c_default} ]" || (echo -e "[CLASS] create external link               [${c_red}fail${c_default}]"; exit 418)
	
	# make dir for *.o files
	mkdir -p source/obj
	if [[ -d source/obj ]]; then
		echo -e "[DIR]   build obj dir                      [ ${c_green}ok${c_default} ]"
	else
		echo -e "[DIR]   build obj dir                      [${c_red}fail${c_default}]"
		exit 507
	fi
	
	# compile
	make -C source -j 4    && echo -e "[CLASS] compile CLASS                      [ ${c_green}ok${c_default} ]" || (echo -e "[CLASS] compile CLASS                                             [${c_red}fail${c_default}]"; exit 501)

	# make links (install)
	make -C source install && echo -e "[CLASS] install CLASS                      [ ${c_green}ok${c_default} ]" || (echo -e "[CLASS] install CLASS           [${c_red}fail${c_default}]"; exit 501)
}

#_____________________________________________________________________________
# compile_class_gui
# clean and compile CLASSGui
function compile_class_gui () {
	make -C gui clean && echo -e "[CLASS] clean gui directory                [ ${c_green}ok${c_default} ]" || (echo -e "[CLASS] clean gui directory     [${c_red}fail${c_default}]"; exit 501)
	make -C gui -j 4  && echo -e "[CLASS] compile GUI                        [ ${c_green}ok${c_default} ]" || (echo -e "[CLASS] compile GUI             [${c_red}fail${c_default}]"; exit 501)
}

### decay data bases #########################################################
# set_decaydata
# write DATA_BASE/DECAY/ALL/Decay.idx file with the correct path
function set_decaydata () {
	local decay_dir="DATA_BASES/DECAY/ALL"
	local decay_databases_path="$(pwd)/${decay_dir}"
	sed -e "s%PATHTOBASE%${decay_databases_path}%" ${decay_dir}/.Decay.tmp > ${decay_dir}/Decay.idx && echo -e "[DB]    decay databases pathes             [ ${c_green}ok${c_default} ]" || (echo -e "[DB]    decay databases pathes             [${c_red}fail${c_default}]"; exit 505)
}

### environement variables ###################################################
# write_shellrc
# write a small file with environment variables, the format depends on the default shell
function write_shellrc () {
	if [[ $SHELL =~ "csh" ]]; then
		export_="setenv"
		equal_=" "
		export_="export"
		equal_="="
	echo "#! $(which $SHELL)
${export_} CLASS_PATH${equal_}${PWD}
${export_} CLASS_include${equal_}\${CLASS_PATH}/source/include
${export_} CLASS_lib${equal_}\${CLASS_PATH}/lib
${export_} PATH${equal_}\${PATH}:\${CLASS_PATH}/gui/bin
${export_} LD_LIBRARY_PATH${equal_}\${LD_LIBRARY_PATH}:\${CLASS_lib}
"
}
#_____________________________________________________________________________
# test_write_shellrc
# write and test the class_env.sh file
function test_write_shellrc () {
	write_shellrc > class_env.sh
	if [[ -f class_env.sh ]]; then
		echo -e "[ENV]   write source file                  [ ${c_green}ok${c_default} ]";
		echo -e "[ENV]   write source file                  [${c_red}fail${c_default}]";
		exit 404
	fi
}

### final information ########################################################
# display_final_info
# display final information to congragulate the user
function display_final_info () {
	echo -e "${c_bold}
Congratulations you are now able to compile your first CLASS .cxx input.
Please read ${PWD}/documentation/Manual/USEGUIDE.pdf
And source ${PWD}/class_env.sh in your \$HOME/.$(echo ${SHELL} | awk -F / '{ print $NF }')rc to finalize installation.${c_default}

echo \"source ${PWD}/class_env.sh\" >> \$HOME/.$(echo ${SHELL} | awk -F / '{ print $NF }')rc
"
}

### procedure of installation ################################################
# CLASS_install
# complet procedure of installation
function CLASS_install () {
	local omp="$1"
	test_root

	if [[ $omp =~ "no" ]]; then
		echo -e "[OMP]   checking for omp.h                 [ ${c_green}no${c_default} ]"
	else
		echo -e "[OMP]   checking for omp.h                 [ ${c_green}ok${c_default} ]"
		test_OMP
	makefileconfig
	confighxx $omp
	compile_class_lib
	compile_class_gui
	
	set_decaydata
	
	test_write_shellrc
	
	display_final_info
}

##############################################################################
### calls of all functions
##############################################################################

# loop on all arguments
for arg in "$@"; do
	case $arg in
		-h|-help|--help )
			usage ;;
		--disable-OMP )
			OMPenable="no" ;;
		--InstallLib-path=* )
			libDir="${arg//--InstallLib-path=/}" ;;
		--InstallGui-path=* )
			guiDir="${arg//--InstallGui-path=/}" ;;
	esac
done
# change default value with argument
LIBDIR=$libDir
Gui_bin_PATH=$guiDir
# call the complet install procedure
CLASS_install $OMPenable
EOF
##############################################################################
# Exit status
In `bash`, a correct exectution of a script return an exit status equals to `0` (that why a *C*/*C++* program end by `return 0;`). There is no standard for other exit status, so I (Josselin Massot) use the list of status code in HTTP for exit status.
* `404` : *Not Found*, a test find a file which doesn't exist.
* `418` : *I'm a teapot*, if only return help (I don't find a correct exit status for this).
* `501` : *Not Implemented*, test a feature which doesn't implemented on OS.
* `505` : *HTTP Version not supported*, the version of a library is not the one is expected.
* `507` : *Insufficient storage*, an error on making a directory, maybe because of the insufficient storage.