1#! /bin/bash
2##########################################################################
3# Author : Yvon.Lafranche@univ-rennes1.fr
4#
5# Installation script of XLiFE++ libraries.
6#
7# XLiFE++ may use other libraries (Umfpack, ARPACK, Lapack, Blas) or
8# third party softwares (Gmsh, Paraview), depending on their presence on
9# the computer. This script performs the installation in an automatic way,
10# without any user action. This means that these libraries or softwares
11# are really used only if they are detected.
12#
13# The installation requires a C++ compiler. The C++ compiler to use can
14# be imposed by the mean of the environment variable CPPCMP before calling
15# this script.
16# The Fortran library is needed if ARPACK is used. Thus, the name of the
17# Fortran compiler, from which is deduced the name of the Fortran library,
18# can also be imposed by the mean of the environment variable FCMP.
19#
20# The installation process conforms to the following rules:
21# 1. if they are not found in the file system, Lapack and Blas are not
22#    installed, neither any third party software,
23# 2. the Umfpack and ARPACK libraries present on the system are used first
24#    and foremost,
25# 3. if ARPACK has not been found in the system and if a Fortran compiler
26#    is available, the ARPACK library is built locally,
27# 4. if Umfpack has not been found in the system, the SuiteSparse libraries
28#    are built locally.
29#
30# Some options may be used to alter the default configuration:
31#  -noAmo prevents XLiFE++ to use the Amos library,
32#  -noArp prevents XLiFE++ to use the ARPACK library,
33#  -noOmp prevents XLiFE++ to use OpenMP capabilities,
34#  -noUmf prevents XLiFE++ to use the Umfpack (SuiteSparse) libraries.
35#
36# Indeed, in case of trouble, this script can be relaunched with one or
37# more of these options.
38#
39# Calling sequence : bash installLibs [-noAmo] [-noArp] [-noOmp] [-noUmf]
40##########################################################################
41# Check options
42noAmo=0
43noArp=0
44noOmp=0
45noUmf=0
46while [ $# -gt 0 ]; do
47 case $1 in
48  -noAmo) noAmo=1; shift;;
49  -noArp) noArp=1; shift;;
50  -noOmp) noOmp=1; shift;;
51  -noUmf) noUmf=1; shift;;
52       *) echo "*** Warning. Option $1 is unrecognised and ignored."
53          shift;;
54 esac
55done
56# Absolute location of this script
57dirdist=`dirname $0`
58##if [ ${dirdist:0:1} != "/" ]; then ## Inexistant syntax in dash under Ubuntu
59if [ ${dirdist#/} = $dirdist ]; then
60 dirdist=$PWD/$dirdist
61fi
62dirdist=`echo $dirdist |sed -e "s,/\.,,g"`
63# Current installation directory
64dirinst=`dirname $dirdist`
65# Temporary files
66warnMes=/tmp/warnMes$$
67testerrf=/tmp/temperr$$
68# Names of expected compilers. The default values can be overidden by the
69# environment variables FCMP or CPPCMP.
70FCMPLR=${FCMP:-gfortran}
71CPPCMPLR=${CPPCMP:-g++}
72#-------------------------------------------------------------------------
73#  Functions (in alphabetical order)
74
75# ========
76checkLd_options () {
77# Calling sequence : checkLd_options
78# Check linkage with LAPACK and BLAS libraries with initial content of ld_options.
79# Try to find the libraries in case of failure, and reset ld_options to a correct
80# value if the libraries are finally found.
81# Moreover, the variable failLink (to be tested after this function returns)
82# is set to 0 in case of success, to 1 if a failure has occured.
83failLink=0
84if [ `testCrExec $ld_options` -eq 0 ]; then
85# Initial ld_options are not correct. Trying to locate BLAS and LAPACK libraries.
86  pathToLapa=`findPathToLib lapack`
87  if [ `testCrExec $pathToLapa -llapack` -eq 0 ]; then failLink=1; printWarnLib LAPACK; fi
88# Depending on the distribution, BLAS library may have different names
89  pathToBlas=`findPathToLib blas`
90  pathTofBla=`findPathToLib f77blas`
91  if [ `testCrExec $pathToBlas -lblas` -eq 0  -a  `testCrExec $pathTofBla -lblas` -eq 0 ]; then
92   failLink=1; printWarnLib BLAS
93  fi
94  if [ $failLink -eq 0 ]; then
95   ld_options="$pathToLapa -llapack $pathToBlas $pathTofBla -lblas"
96  else
97   ld_options=""
98  fi
99fi
100}
101
102# ========
103checkLink () {
104# Calling sequence : checkLink Options
105# Check linkage with given Options
106# Moreover, the variable failLink (to be tested after this function returns)
107# is set to 0 in case of success, to 1 if a failure has occured.
108failLink=0
109if [ `testCrExec $1` -eq 0 ]; then
110 failLink=1
111 printf "%s\n" "** WARNING : linkage with $1 failed." \
112               "   Error message:" \
113               "= = = = = ="  | tee -a $warnMes $logfile
114 cat $testerrf | tee -a $warnMes $logfile
115 printf "%s\n" "= = = = = =" | tee -a $warnMes $logfile
116fi
117}
118
119# ========
120checkScript () {
121# Calling sequence : checkScript
122# Preliminary test to make sure this script is consistent with the template file.
123# The following variable names should be those used in the template file since
124# they are used in some fonctions defined in this file.
125# Any change in the template file should be propagated in this script.
126# Returned value: sets the variable scriptOK to 0 if a problem is detected, to 1 otherwise.
127scriptOK=1
128varnamelist=(OS_TYPE PREC_TYPE BITS_TYPE STRING_TYPE ARPACK UMFPACK OMP GMSH XLIFEPP_GMSH_EXECUTABLE PARAVIEW XLIFEPP_PARAVIEW_EXECUTABLE EIGEN AMOS)
129nbvar=`grep '${' $dirinst/etc/templates/setup.cmake.hpp | wc -l`
130let nbvar--
131if [ $nbvar -eq ${#varnamelist[*]} ]; then
132 for var in ${varnamelist[*]} ; do
133  nbvar=`grep {$var} $dirinst/etc/templates/setup.cmake.hpp | wc -l`
134  if [ $nbvar -ne 1 ]; then
135    printWarn "Variable $var not found in template file as expected."
136    scriptOK=0
137  fi
138 done
139# Particular case of INSTALL_PATH whose value depend on a non reliable variable name.
140# Get the name this variable.
141 sourcedir=`grep INSTALL_PATH $dirinst/etc/templates/setup.cmake.hpp | sed -e 's/^.*{//' -e 's/}.*$//'`
142 if [ ${#sourcedir} -eq 0 ]; then
143   printWarn "Variable INSTALL_PATH not found in template file as expected."
144   scriptOK=0
145 fi
146else
147 printWarn "Incorrect number of variables."
148 scriptOK=0
149fi
150}
151printWarn () {
152# Calling sequence : printWarn Mes
153# Print the warning message Mes
154printf "%s\n" "*** $1" \
155              "    This shell-script $0 should be updated. Please inform the author." \
156              "    (template file is: $dirinst/etc/templates/setup.cmake.hpp)" \
157              "*** Abort." \
158  | tee -a $warnMes $logfile
159}
160
161# ========
162checkUmfLink () {
163# Calling sequence : checkUmfLink
164# Check linkage against SuiteSparse libraries if they exist.
165# In this case, initialize the variable umflibs (needs previous intialization of umfdylnk)
166# and update the variable failInq with the value of failLink, which is also relevant.
167if [ $failInq -eq 0 ]; then
168# Umfpack libraries exist: check linkage
169 OK="`$comldd $umflibdir/libumfpack.* | grep metis`"
170 OK="`$comldd $umflibdir/libcholmod.* | grep metis`$OK"
171 if [ ${#OK} -eq 0 ]; then lmetis=""; else lmetis="-lmetis"; fi
172 umflibs="-lumfpack -lcholmod -lamd -lcamd -lcolamd -lccolamd $lmetis -lsuitesparseconfig $umfdylnk"
173 checkLink "-L$umflibdir $umflibs"
174 failInq=$failLink
175 if [ $failLink -eq 1 ]; then
176   printf "\n%s\n" "** Linkage error with SuiteSparse libraries."  >> $logfile
177 fi
178fi
179}
180
181# ========
182configParams () {
183# Calling sequence : configParams INSTALL_DIR
184# Gather the parameters necessary to the configuration file INSTALL_DIR/etc/include/setup.hpp
185# created later by the function crsetup.
186OS_TYPE=OS_IS_UNIX
187INSTALL_PATH=$1
188PREC_TYPE=LONG_TYPES
189BITS_TYPE=64
190STRING_TYPE=STD_STRING
191#
192withORwithout ARPACK $ArpackOk NOASK
193ARPACK=$REPwOw
194#
195withORwithout UMFPACK $UmfpackOk NOASK
196UMFPACK=$REPwOw
197#
198ompOK=0
199if [ $noOmp -eq 0 ]; then
200# Test if the compiler supports OpenMP directives
201testsrcfomp=infileomp$$.c++
202cat > $testsrcfomp << EOD
203#include <omp.h>
204EOD
205cat $testsrcf >> $testsrcfomp
206ompflag=-fopenmp
207$CPPCMPLR -c $ompflag $testsrcfomp -o /dev/null >/dev/null 2>/dev/null && ompOK=1
208\rm $testsrcfomp
209fi
210if [ $ompOK -eq 0 ]; then ompflag=""; fi
211withORwithout OMP $ompOK NOASK
212OMP=$REPwOw
213#
214dirsToScan="/usr/local/bin \
215 `ls -d /usr/local/* 2>/dev/null | grep -i gmsh` \
216 `ls -d /Applications/* 2>/dev/null | grep -i gmsh`"
217locateExtSoft gmsh GMSH "$dirsToScan" "geometry/ioMesh/loadGmsh.cpp term/ioTerm/ioTermVector.cpp"
218GMSH=$REPwOw
219XLIFEPP_GMSH_EXECUTABLE=$softExe
220#
221dirsToScan="/usr/local/bin \
222 `ls -d /usr/local/* 2>/dev/null | grep -i paraview` \
223 `ls -d /Applications/* 2>/dev/null | grep -i paraview`"
224locateExtSoft paraview PARAVIEW "$dirsToScan" "term/ioTerm/ioTermVector.cpp"
225PARAVIEW=$REPwOw
226XLIFEPP_PARAVIEW_EXECUTABLE=$softExe
227#
228withORwithout EIGEN 0 NOASK
229EIGEN=$REPwOw
230#
231withORwithout AMOS $AmosOk NOASK
232AMOS=$REPwOw
233}
234
235# ========
236crLib () {
237# Calling sequence : crLib
238# Compile the source files and create the library. The library is static.
239# Initialization of xlilibs
240dirsrc=${dirinst}/src
241printf "\n%s\n"  ">>> Installation of the library..." >> $logfile
242#
243for reper in `ls $dirsrc`; do
244 cd $dirsrc/$reper
245 printf "\n%s\n" "--> Compilation in $dirsrc/$reper" | tee -a $logfile
246 for fic in `find . -name "*.cpp"`; do
247  dirloc=`dirname $fic`
248  fname=`basename $fic`
249  echo "$CPPCMPLR $CPPflags -o $dirlib/${fname%.*}.o $fic" | tee -a $logfile
250  ($CPPCMPLR $CPPflags -o $dirlib/${fname%.*}.o $fic) 2>&1 | tee -a $logfile
251 done
252 if [ `ls $dirlib/*.o 2>/dev/null | wc -c` -eq 0 ]; then
253  echo "    Nothing to compile, nothing to add to library." | tee -a $logfile
254 else
255  (ar r $dirlib/libxlifepp.a $dirlib/*.o
256  rm -f $dirlib/*.o
257  ) 2>&1 | tee -a $logfile
258  echo "    Files in $dirsrc/$reper compiled." | tee -a $logfile
259 fi
260done
261ranlib $dirlib/libxlifepp.a
262xlilibs="-lxlifepp"
263printf " done." >> $logfile
264}
265
266# ========
267crsetup () {
268# Calling sequence : crsetup
269# Create the configuration file INSTALL_PATH/etc/include/setup.hpp
270# using the parameters initialized by the function configParams.
271printf "\n%s\n" "Create setup file." | tee -a $logfile
272crsetupsh=/tmp/crsetup$$
273cp /dev/null $crsetupsh
274for var in ${varnamelist[*]} ; do
275 echo "$var=${!var}" >> $crsetupsh
276done
277echo "$sourcedir=${INSTALL_PATH}" >> $crsetupsh
278echo "mkdir -p ${INSTALL_PATH}/etc/include" >> $crsetupsh
279echo "cat > ${INSTALL_PATH}/etc/include/setup.hpp << EOD" >> $crsetupsh
280cat ${INSTALL_PATH}/etc/templates/setup.cmake.hpp >> $crsetupsh
281echo "EOD" >> $crsetupsh
282sh $crsetupsh
283\rm $crsetupsh
284}
285
286# ========
287crXLiMk () {
288# Calling sequence : crXLiMk
289# Create a Bourne shell script that can be used to create an executable file using XLiFE++.
290shscr=$dirinst/etc/xlmake
291printf "\n%s\n" "Create shell-script to use XLiFE++ $shscr" | tee -a $logfile
292cat > $shscr << EOD
293#! /bin/sh
294#
295# Script that creates an executable file using XLiFE++.
296# Usage:
297#  Change to the directory containing the source files and enter the command:
298#   sh $shscr
299#
300#  Alternatively, you can make a link in this directory:
301#   ln -s $shscr .
302#  and then enter the command:
303#   `basename $shscr`
304
305XLI_INST_DIR=$dirinst
306if [ ! -d \$XLI_INST_DIR ]; then
307 echo "*** XLiFE++ installation directory not found. Abort."
308 echo "    Check XLI_INST_DIR variable in \$0."
309 exit
310fi
311
312ARP_INC_OPS="$arpincops"
313UMF_INC_OPS="$umfincops"
314XLI_INC_OPS="$xliincops"
315LD_OPTIONS="$ld_options"
316AMO_LIB_DIR="$amolibdir"
317ARP_LIB_DIR="$arplibdir"
318UMF_LIB_DIR="$umflibdir"
319XLI_LIB_DIR="$dirlib"
320FTN_LIB_DIR="$ftnlibdir"
321AMO_LIBS="$amolibs"
322ARP_LIBS="$arplibs"
323UMF_LIBS="$umflibs"
324XLI_LIBS="$xlilibs"
325XLI_FLAGS="$xliflags"
326
327XFILE=xlifeppexec
328CPPCMP=$CPPCMPLR
329EOD
330# For the end of the script, it is easier to deactivate metacharacter interpretation.
331cat >> $shscr << \EOD
332CPPflags="$XLI_FLAGS $XLI_INC_OPS $UMF_INC_OPS $ARP_INC_OPS"
333
334srcfiles=`ls *.c++ *.cpp *.cc *.C *.cxx 2>/dev/null`
335if [ -f $XFILE ]; then \rm $XFILE; fi
336$CPPCMP $CPPflags $srcfiles -o $XFILE -L$XLI_LIB_DIR $XLI_LIBS -L$UMF_LIB_DIR $UMF_LIBS -L$ARP_LIB_DIR -L$FTN_LIB_DIR $ARP_LIBS -L$AMO_LIB_DIR $AMO_LIBS $LD_OPTIONS
337if [ -x $XFILE ]; then
338 echo " XLiFE++ executable file created: $XFILE"
339fi
340EOD
341chmod a+rx $shscr
342}
343
344# ========
345crXLiUp () {
346# Calling sequence : crXLiUp
347# Create a Bourne shell script that can be used to update the library of XLiFE++.
348shscr=$dirinst/etc/updateLib
349cat > $shscr << EOD
350#! /bin/sh
351#
352# Script allowing to update the library of XLiFE++.
353# The arguments should be a list of files, separated by a space, each of them given by
354# their pathname relative to the directory $dirinst/src, e.g. term/ioTerm/ioTermVector.cpp.
355# Usage:
356#   sh $shscr Files
357#
358
359XLI_INST_DIR=$dirinst
360if [ ! -d \$XLI_INST_DIR ]; then
361 echo "*** XLiFE++ installation directory not found. Abort."
362 echo "    Check XLI_INST_DIR variable in \$0."
363 exit
364fi
365
366ARP_INC_OPS="$arpincops"
367UMF_INC_OPS="$umfincops"
368XLI_INC_OPS="$xliincops"
369XLI_LIB_DIR="$dirlib"
370XLI_FLAGS="$xliflags"
371CPPCMP=$CPPCMPLR
372EOD
373# For the end of the script, it is easier to deactivate metacharacter interpretation.
374cat >> $shscr << \EOD
375CPPflags="-c $XLI_FLAGS $XLI_INC_OPS $UMF_INC_OPS $ARP_INC_OPS"
376
377libTOupdate=$XLI_LIB_DIR/libxlifepp.a
378for fic in $*; do
379 reper=`echo $fic | cut -d/ -f1`
380 if [ -d $XLI_INST_DIR/src/$reper ]; then
381  fname=`basename $fic`
382  srcfile=$XLI_INST_DIR/src/$fic
383  if [ -f $srcfile ]; then
384   $CPPCMP $CPPflags $srcfile -o $XLI_LIB_DIR/${fname%.*}.o
385   ar r $libTOupdate $XLI_LIB_DIR/*.o
386   rm -f $XLI_LIB_DIR/*.o
387   echo "Library $libTOupdate updated."
388  else
389   echo "** File $srcfile does not exist. Argument ignored."
390  fi
391 else
392  echo "** Directory $XLI_INST_DIR/src/$reper does not exist. Argument ignored."
393 fi
394done
395ranlib $libTOupdate
396EOD
397chmod a+rx $shscr
398}
399
400# ========
401findPathToInc () {
402# Calling sequence : findPathToInc Name
403# Return the absolute pathname of the file Name if found, nothing otherwise.
404# Several commands are tried successively ; the result obtained by the first
405# successful search is returned.
406# - - - - -
407# 1. Try with find, if available
408 OK=0
409 which find >/dev/null 2>/dev/null && OK=1
410 if [ $OK -eq 1 ]; then
411  pathsToSearch=(/usr/include /usr/local) # /opt ?
412  for reper in ${pathsToSearch[*]}; do
413   path=`searchInPath $reper $1`
414   if [ "X$path" != "X" ]; then break; fi
415  done
416  path=`getDirName "$path"`
417 fi
418# - - - - -
419if [ "X$path" = "X" ]; then
420# 2. Try with locate, if available
421 OK=0
422 locate -S >/dev/null 2>/dev/null && OK=1
423# The database exists, but not necessarily up to date.
424 if [ $OK -eq 1 ]; then
425  path=`locate $1`
426  path=`getDirName "$path"`
427 fi
428fi
429printf "$path"
430}
431
432# ========
433findPathToLib () {
434# Calling sequence : findPathToLib Name
435# Return the absolute pathname of the library libName.* if found, nothing otherwise.
436# The library found may either be a static or a dynamic library. Several commands
437# are tried successively (ldconfig, locate, find) ; the result obtained by the first
438# successful search is returned.
439# - - - - -
440# 1. Try with ldconfig, if available (search for a dynamic library under Unix)
441OK=0
442which /sbin/ldconfig >/dev/null 2>/dev/null && OK=1
443if [ $OK -eq 1 ]; then
444# To be used on Linux-like system only.
445# We should get .../lib$1.so if it exists, .../lib$1.so.n otherwise
446 path=`/sbin/ldconfig -p | grep lib$1 | cut -d\> -f2 | sort | head -1`
447fi
448# - - - - -
449if [ "X$path" = "X" ]; then
450# 2. Try with locate, if available
451 OK=0
452 locate -S >/dev/null 2>/dev/null && OK=1
453# The database exists, but not necessarily up to date.
454 if [ $OK -eq 1 ]; then
455  path=`locate lib$1.`
456  path=`getDirName "$path"`
457 fi
458else
459# Get dirname from ldconfig result
460 path=`dirname $path`
461fi
462# - - - - -
463if [ "X$path" = "X" ]; then
464# 3. Try with find, if available
465 OK=0
466 which find >/dev/null 2>/dev/null && OK=1
467 if [ $OK -eq 1 ]; then
468  pathsToSearch=(/lib64 /usr/lib64 /lib /usr/lib /usr/local/lib /usr/local)  # /opt ?
469  for reper in ${pathsToSearch[*]}; do
470   path=`searchInPath $reper "lib$1.*"`
471   if [ "X$path" != "X" ]; then break; fi
472  done
473  path=`getDirName "$path"`
474 fi
475fi
476printf "$path"
477}
478
479# ========
480getDirName () {
481# Calling sequence : getDirName listOfPaths
482# Select a directory name among the given listOfPaths.
483# The directory part of the path (dirname) is selected in such a way that it is
484# at the highest level in the file hierarchy, among the possibilities derived
485# from the given listOfPaths, leading presumably to the least specific choice, which
486# is the most convenient one, owing to the context in which this function is called
487# (namely locating a file in a part of the file system).
488# If there are several such candidates, the first in the list is arbitrarily
489# selected, given that they are alphabetically sorted.
490 (for fic in $1; do
491  reper=`dirname $fic`
492  reperws=`echo $reper | sed -e "s,/,,g"`
493  let n="${#reper} - ${#reperws}"
494  printf "%s:%s\n" "$n" "$reper"
495 done) | sort -n | head -1 | cut -d : -f2
496}
497
498# ========
499initExtLibPaths () {
500# Calling sequence : initExtLibPaths
501# Sets various variables related to external libraries
502
503# Look for Fortran library and compiler (needed for Arpack and Amos)
504inquireFortran
505#
506inquireAmos
507if [ $failInq -eq 1 ]; then AmosOk=0; else AmosOk=1; fi
508inquireArpack
509if [ $failInq -eq 1 ]; then ArpackOk=0; else ArpackOk=1; fi
510inquireUmfpack
511if [ $failInq -eq 1 ]; then UmfpackOk=0; else UmfpackOk=1; fi
512#
513if [[ $ArpackOk -eq 1 || $UmfpackOk  -eq 1 ]]; then
514# Linker options to be used related to BLAS and LAPACK
515 case $theOS in
516   # MacOS X
517   Darwin)
518     ld_options="-framework Accelerate" ;;
519   # Other systems (Linux,...)
520   *)
521     ld_options="-llapack -lblas" ;;
522 esac
523 checkLd_options
524 if [ $failLink -eq 1 ]; then
525   # None of the packages can be used: disable them
526  ArpackOk=0
527  UmfpackOk=0
528 fi
529else
530 ld_options=""
531fi
532}
533
534# ========
535inquireAmos () {
536# Calling sequence : inquireAmos
537# Initialization of:
538#  - the directory containing the Amos library (amolibdir),
539#  - the list of libraries needed (amolibs).
540# These variables are set to a neutral value in case of failure.
541# Moreover, the variable failInq (to be tested after this function returns)
542# is set to 0 in case of success, to 1 if a failure has occured.
543failInq=0
544if [ $noAmo -eq 1 ]; then
545  echo "-> Amos not used." >> $logfile
546  amolibdir="."
547  amolibs=""
548  failInq=1
549  return
550fi
551if [ "$ftnlibdir" = "." ]; then
552  failInq=1
553else
554  if [ $FCMPLRok -eq 1 ]; then
555    installAmos
556    # Fortran and Amos libraries exist: check linkage
557    amolibs="-lamos -l$FCMPLR"
558    checkLink "-L$amolibdir -L$ftnlibdir $amolibs"
559    failInq=$failLink
560    if [ $failLink -eq 1 ]; then
561     printf "\n%s\n" "** Linkage error with Amos library." >> $logfile
562    fi
563  else
564    failInq=1
565  fi
566fi
567if [ $failInq -eq 1 ]; then
568 printf "%s\n" "   Package Amos will not be used." >> $logfile
569 # Reset to neutral value in case of failure:
570 amolibdir="."
571 amolibs=""
572fi
573}
574
575# ========
576inquireArpack () {
577# Calling sequence : inquireArpack
578# Initialization of:
579#  - the compiler option for Arpack++ (arpincops)
580#  - the directory containing the ARPACK library (arplibdir),
581#  - the list of libraries needed (arplibs).
582# These variables are set to a neutral value in case of failure.
583# Moreover, the variable failInq (to be tested after this function returns)
584# is set to 0 in case of success, to 1 if a failure has occured.
585failInq=0
586if [ $noArp -eq 1 ]; then
587  echo "-> ARPACK not used." >> $logfile
588  arpincops=""
589  arplibdir="."
590  arplibs=""
591  failInq=1
592  return
593fi
594if [ "$ftnlibdir" = "." ]; then
595  failInq=1
596else
597  # Fortran library found: look for ARPACK library
598  arplibdir=`findPathToLib arpack`
599  if [ "X$arplibdir" = "X" ]; then
600    # No ARPACK library found: install one if the Fortran compiler is available
601    printf "\n%s\n" "** No ARPACK library found."  >> $logfile
602    if [ $FCMPLRok -eq 1 ]; then
603      installArpack
604      failInq=$failIns
605    else
606      failInq=1
607    fi
608  else
609    echo "-> ARPACK library found in $arplibdir."  | tee -a $logfile
610  fi
611  if [ $failInq -eq 0 ]; then
612    # Include files for Arpack++
613    arpincops="-I$dirinst/ext/ARPACK++/include"
614    # Fortran and ARPACK libraries exist: check linkage
615    arplibs="-larpack -l$FCMPLR"
616    checkLink "-L$arplibdir -L$ftnlibdir $arplibs"
617    failInq=$failLink
618    if [ $failLink -eq 1 ]; then
619     printf "\n%s\n" "** Linkage error with ARPACK library." >> $logfile
620    fi
621  fi
622fi
623if [ $failInq -eq 1 ]; then
624 printf "%s\n" "   Package ARPACK will not be used." >> $logfile
625 # Reset to neutral value in case of failure:
626 arpincops=""
627 arplibdir="."
628 arplibs=""
629fi
630}
631
632# ========
633inquireFortran () {
634# Calling sequence : inquireFortran
635# Initialization of the directory ftnlibdir containing the Fortran library.
636# If the directory is not found, ftnlibdir is set to ".".
637# The variable FCMPLRok is also set to 1 if the Fortran compiler is available, 0 otherwise.
638# Take note that the library may exist though there is no compiler.
639
640FCMPLRok=0
641ftnlibdir="."
642if [[ $noAmo -eq 1 && $noArp -eq 1 ]]; then return; fi
643#
644# Check if the Fortran compiler is available
645$FCMPLR -v >/dev/null 2>/dev/null && FCMPLRok=1
646if [ $FCMPLRok -eq 0 ]; then
647 printf "\n%s\n" "** No $FCMPLR compiler available."  >> $logfile
648else
649 # Flag to insure compatibility with BLAS and LAPACK system libraries
650 # under MacOS X which use g77 calling conventions
651 if [ $theOS = "Darwin" ]; then compatflag="-ff2c"; else compatflag=""; fi
652fi
653# Locate Fortran library
654ftnlibdir=`findPathToLib $FCMPLR`
655if [ "X$ftnlibdir" = "X" ]; then
656  ftnlibdir="."
657# Fortran library not found: try from compiler information if available
658  if [ $FCMPLRok -eq 1 ]; then
659# Look for a directory containing either a static or a dynamic fortran library
660   listext=(a so dylib)
661   for ext in ${listext}; do
662    ftnlibdir=`$FCMPLR -print-file-name=lib${FCMPLR}.$ext`
663    ftnlibdir=`dirname $ftnlibdir`
664    if [ "$ftnlibdir" != "." ]; then break; fi
665   done
666  fi
667fi
668if [ "$ftnlibdir" = "." ]; then
669  printf "\n%s\n" "** No Fortran library found."  >> $logfile
670else
671  echo "-> Fortran library found in $ftnlibdir."  >> $logfile
672fi
673}
674
675# ========
676inquireUmfpack () {
677# Calling sequence : inquireUmfpack
678# Initialization of:
679#  - the directory containing SuiteSparse include files (umfincops),
680#  - the directory containing SuiteSparse libraries (umflibdir),
681#  - the list of libraries needed (umflibs).
682# These variables are set to a neutral value in case of failure.
683# Moreover, the variable failInq (to be tested after this function returns)
684# is set to 0 in case of success, to 1 if a failure has occured.
685failInq=0
686if [ $noUmf -eq 1 ]; then
687  echo "-> Umfpack (SuiteSparse) not used." >> $logfile
688  umflibdir="."
689  umfincops=""
690  umflibs=""
691  failInq=1
692  return
693fi
694# Look for include file
695umfincops=`findPathToInc umfpack.h`
696if [ "X$umfincops" = "X" ]; then
697 # Include file not found
698 printf "\n%s\n" "** Umfpack include file not found."  >> $logfile
699 failInq=1
700else
701 # Include file found
702 umfincops="-I$umfincops"
703 # Look for Umfpack libraries
704 umflibdir=`findPathToLib umfpack`
705 if [ "X$umflibdir" = "X" ]; then
706   printf "\n%s\n" "** No Umfpack library found."  >> $logfile
707   failInq=1
708 else
709   echo "-> Umfpack library found in $umflibdir."  | tee -a $logfile
710 fi
711fi
712#
713if [ $theOS = "Darwin" ]; then comldd="otool -L"; else comldd="ldd"; fi
714umfdylnk=""
715checkUmfLink
716#
717if [ $failInq -eq 1 ]; then
718 printf "\n%s\n" "** No Umfpack library found, or found but not functional."  >> $logfile
719 installUmfpack
720 failInq=$failIns
721 checkUmfLink
722fi
723#
724if [ $failInq -eq 1 ]; then
725 printf "%s\n" "   Package SuiteSparse will not be used." >> $logfile
726 # Reset to neutral value in case of failure:
727 umflibdir="."
728 umfincops=""
729 umflibs=""
730fi
731}
732
733# ========
734installAmos () {
735# Calling sequence : installAmos
736# Creation of the Amos Fortran library from the source files contained in the
737# distribution archive of XLiFE++.
738# This function also sets the variable amolibdir.
739# If the library is not installed, amolibdir is set to ".", which will cause
740# an error caught later.
741amolibdir=`find $dirinst/ext -name cairy.f`
742amolibdir=`dirname $amolibdir 2>/dev/null`
743if [[ ! -d $amolibdir ]]; then
744 printf "%s\n" "*** Directory \"$amolibdir\" unexpectedly not found." \
745               "    Please inform the authors." \
746 | tee -a $warnMes $logfile
747 amolibdir="."
748 return
749fi
750# Create Amos library
751printf "%s\n" "Building local Amos library" | tee -a $logfile
752(cd $amolibdir
753 $FCMPLR -c $compatflag *.f
754 libName=amos
755 ar r lib$libName.a *.o
756 \rm *.o
757 ranlib lib$libName.a
758 chmod a+r lib$libName.a
759) 2>&1 | tee -a $logfile
760printf "%s\n" "End of building local Amos library" | tee -a $logfile
761}
762
763# ========
764installArpack () {
765# Calling sequence : installArpack
766# Creation of the ARPACK Fortran library from the source files contained in the
767# distribution archive of XLiFE++.
768# The variable failIns (to be tested after this function returns) is set to 0 if the
769# library is installed, in which case this function also sets the variable arplibdir.
770# The variable failIns is set to 1 if the library is not installed.
771failIns=0
772dirutil=`find $dirinst/ext -name second.f`
773dirutil=`dirname $dirutil 2>/dev/null`
774dirsrc=`find $dirinst/ext -name dneupd.f`
775dirsrc=`dirname $dirsrc 2>/dev/null`
776if [[ ! ( -d $dirutil && -d $dirsrc ) ]]; then
777 printf "%s\n" "*** Directory \"$dirutil\" or \"$dirsrc\" unexpectedly not found." \
778               "    Please inform the authors." \
779 | tee -a $warnMes $logfile
780 failIns=1
781 return
782fi
783#
784printf "%s\n" "Building local ARPACK library." | tee -a $logfile
785arplibdir=`dirname $dirsrc`/lib
786mkdir -p $arplibdir
787chmod a+rx $arplibdir
788(cd $arplibdir
789if [ $FCMPLR != gfortran ]; then
790 cp $dirutil/second.f $arplibdir
791 printf "%s\n" \
792      "** WARNING: $FCMPLR compiler used. Check whether ETIME is INTRINSIC" \
793      "   or EXTERNAL and update $dirutil/second.f accordingly." \
794      "   We assume ETIME is EXTERNAL and continue." \
795       | tee -a $warnMes
796else
797 (sed -e '/EXTERNAL/{s/EXTERNAL//
798          a\
799\       INTRINSIC ETIME
800       }' $dirutil/second.f > $arplibdir/second.f
801 ) 2>&1 | tee -a $warnMes
802fi
803$FCMPLR -c $compatflag second.f
804$FCMPLR -c $compatflag `ls $dirutil/*.f | grep -v second`
805$FCMPLR -c $compatflag `ls $dirsrc/*.f | grep -v naupe`
806libName=arpack
807ar r lib$libName.a *.o
808\rm second.f *.o
809ranlib lib$libName.a
810chmod a+r lib$libName.a
811) 2>&1 | tee -a $logfile
812printf "%s\n" "End of building local ARPACK library." | tee -a $logfile
813}
814
815# ========
816installUmfpack () {
817# Calling sequence : installUmfpack
818# Creation of the Umfpack libraries (SuiteSparse) from the source files contained
819# in the distribution archive of XLiFE++.
820# The variable failIns (to be tested after this function returns) is set to 0 if
821# the libraries are installed, in which case this function also sets the variables
822# umfincops, umflibdir and umfdylnk.
823# The variable failIns is set to 1 if the libraries are not installed.
824failIns=0
825SuiteSppkg=`ls $dirinst/ext/SuiteSparse*tar* 2>/dev/null`
826if [ ${#SuiteSppkg} -eq 0 ]; then
827 printf "%s\n" "*** SuiteSparse archive unexpectedly not found." \
828               "    Please inform the authors." \
829 | tee -a $warnMes $logfile
830 failIns=1
831 return
832fi
833printf "%s\n" "Building local Umfpack libraries (SuiteSparse)." | tee -a $logfile
834tar xf $SuiteSppkg -C $dirinst/ext
835SuiteSpDir=`find $dirinst/ext -name UMFPACK`
836SuiteSpDir=`dirname $SuiteSpDir`
837umflibdir=$SuiteSpDir/lib
838umfincops="-I$SuiteSpDir/include"
839(cd $SuiteSpDir
840 make library
841 chmod a+rx $umflibdir $SuiteSpDir/include
842 chmod a+r $umflibdir/* $SuiteSpDir/include/*
843) 2>&1 | tee -a $logfile
844umfdylnk=""
845if [ $theOS = "Linux" ]; then
846# SuiteSparse libraries are dynamic: insure they are found at run time (unuseful for MacOS X).
847   umfdylnk="$umfdylnk -Wl,-rpath,$umflibdir"
848fi
849printf "%s\n" "End of building local Umfpack libraries (SuiteSparse)." | tee -a $logfile
850}
851
852# ========
853locateExtSoft () {
854# Calling sequence : locateExtSoft Software IDENT Dirs XLFiles
855# Try to find Software firstly in user's path, secondly in Dirs.
856# IDENT is the macro name in the setup file.
857# XLFiles are the source files in XLiFE++ that depend on the configuration of this Software.
858# Returns absolute pathname found in softExe (may be empty) and initialize IDENT accordingly.
859
860# 1. Try with which in user's path
861softExe=`which $1 2>/dev/null`
862softFound=1
863if [ "X$softExe" = "X" ]; then
864# 2. Not found: try with find in Dirs
865 for reper in $3; do
866  softExe=`searchInPath $reper $1`
867  if [ "X$softExe" != "X" ]; then
868   echo "-> $1 found ($softExe)" | tee -a $logfile
869   break
870  fi
871 done
872 if [ "X$softExe" = "X" ]; then
873  printf "%s\n" "** WARNING: $1 not found, thus XLiFE++ will not use it." \
874         "   This may not be a problem, since XLiFE++ can however be used without $1." \
875         "   This can be manually changed by setting the macros containing $2 in the file:" \
876         "   ${INSTALL_PATH}/etc/include/setup.hpp" \
877         "   This will then need to update the XLiFE++ library by typing in a terminal:" \
878         "   $dirinst/etc/updateLib $4" | tee -a $warnMes
879  softFound=0
880 fi
881else
882 echo "-> $1 found ($softExe)" | tee -a $logfile
883fi
884withORwithout $2 $softFound NOASK
885}
886
887# ========
888printWarnLib () {
889# Calling sequence : printWarnLib Lib
890printf "%s\n" "** WARNING : $1 library not found." \
891       "   Shell $dirinst/etc/xlmake will be incorrect (check LD_OPTIONS or xxx_LIB_DIR)." \
892       "   Continue installation however." | tee -a $warnMes
893}
894
895# ========
896searchInPath () {
897# Calling sequence : searchInPath Path Name
898# Search for Name in Path using find.
899# The search is restricted to find a regular file or a symbolic link.
900if [ -d $1 ]; then
901 find $1 \( -type f -or -type l \) -name "$2" -print 2>/dev/null
902fi
903}
904
905# ========
906testCrExec () {
907# Calling sequence : testCrExec LibArgs
908# Returns 1 if LibArgs are successfully used, 0 otherwise
909 testoutf=/tmp/tempout$$
910 $CPPCMPLR $testsrcf $* -o $testoutf > $testerrf 2>&1
911# If a library in $* is not found or $* is empty, the executable file is not created.
912 if [ -e $testoutf ]; then
913  \rm $testoutf
914  printf "1"
915 else
916  printf "0"
917 fi
918}
919
920# ========
921withORwithout () {
922# Calling sequence : withORwithout NAME DEFAULT ASK
923# If the third parameter is ASK, this function asks for a choice about NAME
924# else the question is not asked and the DEFAULT choice is made.
925# Returns the corresponding parameter value in REPwOw
926if [ "$3" = "ASK" ]; then
927 read -p "With (1) or without (0) $1 [default=0] : " rep
928else
929 rep=$2
930fi
931case $rep in
932  1) REPwOw=XLIFEPP_WITH_$1 ;;
933  *) REPwOw=XLIFEPP_WITHOUT_$1 ;;
934esac
935}
936
937#-------------------------------------------------------------------------
938#  Preliminary tests and settings
939for compil in $CPPCMPLR; do
940  OK=0
941  $compil -v >/dev/null 2>/dev/null && OK=1
942  if [ $OK -eq 0 ]; then
943   echo "*** $compil compiler not found (required for the installation)."
944   echo "*** Abort."
945   exit
946  fi
947done
948#
949echo "Installation directory : $dirinst"
950#
951# Directory containing the library. This directory may already exist.
952# We need write access on $dirinst and $dirlib.
953dirlib=$dirinst/lib
954OK=0
955mkdir -p $dirlib && OK=1
956if [ $OK -eq 0  -o  ! -w $dirlib ]; then
957  echo "*** Insufficient access rigths on $dirinst or $dirlib."
958  echo "*** Abort."
959  exit
960fi
961chmod a+rx $dirlib
962#-------------------------------------------------------------------------
963#  Installation steps
964#
965# Log file of the installation process
966logfile=$dirinst/`basename $0`.log
967echo "--- `date`" > $logfile
968echo `uname -a` >> $logfile
969
970checkScript
971if [ $scriptOK -eq 1 ]; then
972 printf "\nLooking for libraries and softwares...\n" | tee -a $logfile
973# Create test source file
974 testsrcf=infile$$.c++
975 cat > $testsrcf << EOD
976 int main(){}
977EOD
978# Initilization of pathnames to external libraries if they are found
979 theOS=`uname`
980 initExtLibPaths
981# Initilization of configuration parameters of XLiFE++
982 configParams $dirinst
983 \rm -f $testsrcf
984 printf " done.\n"  | tee -a $logfile
985# Create configuration file
986 crsetup
987
988 printf "\n%s\n" " C++ compiler version:"  >> $logfile
989 $CPPCMPLR -v >> $logfile 2>&1
990 xliincops="-I$dirinst/etc/include -I$dirinst/include -I$dirinst/src"
991 xliflags="$ompflag -O3 -std=c++11"
992 CPPflags="-c $xliflags $xliincops $umfincops $arpincops"
993 printf "\n%s\n" " C++ compiler options used: $CPPflags" >> $logfile
994
995# Create the library
996 crLib
997
998# Create shell-script to make executables from XLiFE++.
999 crXLiMk
1000# Create shell-script to update library of XLiFE++.
1001 crXLiUp
1002fi
1003#
1004# End
1005# ---
1006echo "Terminated." | tee -a $logfile
1007if [ -s $warnMes ]; then
1008  echo "" | tee -a $logfile
1009  printf "%s\n" "-> Some problems have been encountered ; depending on their nature," \
1010       "   they are best to be fixed before trying to use the library." \
1011       "   Recall of warning messages previously printed:" \
1012       "----------" | tee -a $logfile
1013  cat $warnMes | tee -a $logfile
1014  echo "----------" | tee -a $logfile
1015fi
1016rm -f $warnMes $testerrf
1017echo "--- `date`" >> $logfile
1018echo "End of log file." >> $logfile
1019printf "\n%s\n" "Please check installation log file $logfile."
1020# End of file
1021