2019-01-16 19:40:08 +00:00
#!/usr/bin/env python3
#
# This scripts downloads, unpacks and installs the packages required by the
# InSAR Scientific Computing Environment (ISCE). It is called by the bash script
# install.sh and requires the script setup_config.py.
#
# Authors : Eric Gurrola, Kosal Khun, Marco Lavalle
# Date : April 2013
# Version : 2.0
from __future__ import print_function
import sys
import os
2019-11-20 00:40:56 +00:00
import urllib
2019-01-16 19:40:08 +00:00
import getopt
import re
import shutil
import subprocess
import datetime
import time
import platform
import traceback
import barthread
VARENV = [ ' PATH ' , ' PYTHONPATH ' , ' LD_LIBRARY_PATH ' , ' SCONS_CONFIG_DIR ' , ' ISCE_HOME ' ] #environment variables
THIS_FOLDER = os . path . dirname ( os . path . abspath ( __file__ ) ) #folder containing this file
CONFIG_FOLDER = os . path . join ( os . path . dirname ( THIS_FOLDER ) , ' configuration ' ) #name of configuration folder in the ISCE source tree
SCONS_CONFIG_DIR = os . path . join ( os . getenv ( ' HOME ' ) , ' .isce ' ) #folder where config file will be written
CONFIG_FILE = ' SConfigISCE ' #name of config file to be created
BASH_FILE = os . path . join ( SCONS_CONFIG_DIR , ' .isceenv ' ) #source this file in order to define environment variables
SETUP_CONFIG = ' setup_config ' #name of file (without .py) inside THIS_FOLDER, with dependencies to be downloaded
CONTACT = " isceteam@gmail.com " #email address shown when an error happens
SETUP_LOG = os . path . join ( SCONS_CONFIG_DIR , ' setup.log ' ) #log file for the installation (inside the SCONS_CONFIG_DIR)
LOGFILE = None #the log file object referring to SETUP_LOG
VERBOSE = False #default verbose value
WORKING = None #barthread display
def usage ( ) :
"""
Print a message about how to use install . sh
"""
print ( " %s must be called by install.sh \n " % os . path . basename ( __file__ ) )
subprocess . check_call ( os . path . join ( THIS_FOLDER , " install.sh -h " ) , shell = True )
def print2log ( msg , withtime = True , cmd = False ) :
"""
Output the message displayed by the setup script
to LOGFILE and to the standard output
"""
global LOGFILE
print ( msg )
if cmd :
msg = " Issuing command: \n \t %s " % msg
if withtime :
now = datetime . datetime . today ( )
msg = " %s >> %s " % ( now . isoformat ( ) , msg )
2019-11-20 00:40:56 +00:00
LOGFILE . write ( ( msg + ' \n ' ) . encode ( ' utf-8 ' ) )
2019-01-16 19:40:08 +00:00
LOGFILE . flush ( )
os . fsync ( LOGFILE )
def executeCommand ( command , logfile , critical = True , executable = ' bash ' ) :
"""
Take a command and add extra code so that messages are
logged to a file ( logfile ) and displayed on standard output .
The exit status of the command ( and not the exit status of tee ) is returned to subprocess .
If critical , the program exits .
executable is the shell to use .
"""
global WORKING
if logfile is not None :
print2log ( " Output messages of this command can be found in file %s " % logfile )
if VERBOSE :
if logfile is None :
loggedcommand = command
else :
loggedcommand = " %s 2>&1 | tee -a %s ; exit $ {PIPESTATUS[0]} " % ( command , logfile )
else :
if logfile is None :
loggedcommand = " %s > /dev/null " % command
else :
loggedcommand = " %s >> %s 2>&1 " % ( command , logfile )
WORKING = barthread . BarThread ( )
try :
subprocess . check_call ( loggedcommand , shell = True , executable = executable )
if WORKING :
WORKING . stop ( )
WORKING = None
else :
print2log ( " Done " )
except subprocess . CalledProcessError as e :
if WORKING :
WORKING . stop ( False )
WORKING = None
print2log ( " ...An error occurred with exit status %s . You can find more details in the file %s " % ( e . returncode , logfile ) )
if critical :
sys . exit ( 1 )
else :
print2log ( " ...Non critical error, command skipped. " )
def printenv ( msg ) :
msg = " ************ \n " + msg
for var in VARENV :
try :
env = os . environ [ var ]
except KeyError :
env = " "
msg + = " %s = %s \n " % ( var , env )
msg + = " ************ "
print2log ( msg )
def changedir ( folder ) :
print2log ( " cd %s " % folder , cmd = True )
os . chdir ( folder )
def createfolder ( folder ) :
print2log ( " mkdir -p %s " % folder , cmd = True )
os . makedirs ( folder )
def removefolder ( folder ) :
"""
Remove a folder using shutil . rmtree
If fails , use removeall ( )
"""
if os . path . exists ( folder ) :
print2log ( " rm -rf %s " % folder , cmd = True )
try :
shutil . rmtree ( folder )
except OSError :
removeall ( folder )
def removeall ( folder ) :
"""
Remove a folder recursively using os . remove
"""
if not os . path . isdir ( folder ) :
return
files = os . listdir ( folder )
for f in files :
fullpath = os . join ( folder , f )
if os . path . isfile ( fullpath ) :
os . remove ( fullpath )
elif os . path . isdir ( fullpath ) :
removeall ( fullpath )
os . rmdir ( fullpath )
def downloadfile ( url , fname , repeat = 1 ) :
counter = 0
while counter < repeat :
try :
2019-11-20 00:40:56 +00:00
response = urllib . request . urlopen ( url )
2019-01-16 19:40:08 +00:00
break
2019-11-20 00:40:56 +00:00
except urllib . request . URLError as e :
2019-01-16 19:40:08 +00:00
counter + = 1
if hasattr ( e , ' reason ' ) :
print2log ( " Failed to reach server. Reason: %s " % e . reason )
if counter == repeat :
return False
time . sleep ( 1 ) #wait 1 second
elif hasattr ( e , ' code ' ) :
print2log ( " The server couldn ' t fulfill the request. Error code: %s " % e . code )
return False
data = response . read ( )
with open ( fname , ' wb ' ) as code :
code . write ( data )
return True
class InstallItem ( object ) :
"""
This class allows unpacking and installation of a package .
"""
def __init__ ( self , item , paths ) :
self . item = item
self . paths = paths
self . flags = None ;
self . getFlags ( )
self . this_src = None
self . this_bld = None
def getFlags ( self ) :
"""
Get the flags used to install the item .
"""
user_flags = self . item . properties [ ' user_flags ' ]
flags_list = self . item . properties [ ' flags_list ' ]
SPC = " "
if user_flags :
if type ( user_flags ) in ( list , tuple ) :
FL = user_flags
elif type ( flags ) is str :
FL = user_flags . split ( )
else :
print2log ( " ProgError: user_flags for %s must be a list or a string " % self . item . name )
sys . exit ( 1 )
elif flags_list :
if type ( flags_list ) in ( list , tuple ) :
FL = [ SPC , " --prefix= " + self . paths . prefix ]
FL . extend ( flags_list )
else :
print2log ( " ProgError: flags_list for %s must be a list " % self . item . name )
sys . exit ( 1 )
else :
FL = [ SPC , " --prefix= " + self . paths . prefix ]
self . flags = SPC . join ( FL )
def unpack ( self , toUnpack = True ) :
"""
Get the folder where the package will be untarred
Unpack the item if toUnpack = True
"""
global WORKING
destfile = self . item . destfile
destfolder , fname = os . path . split ( destfile )
ns = fname . split ( ' . ' )
if ( ' tar ' in ns ) or ( ' tgz ' in ns ) and ( ns . index ( ' tgz ' ) == len ( ns ) - 1 ) :
if ns [ - 1 ] == ' tar ' :
flag = " xvf "
self . this_src = destfile [ : - 4 ]
elif ns [ - 1 ] in [ ' tgz ' ] :
flag = " xzvf "
self . this_src = destfile [ : - 4 ]
elif ns [ - 1 ] in [ ' gz ' ] :
flag = " xzvf "
self . this_src = destfile [ : - 7 ]
elif ns [ - 1 ] in [ ' bz2 ' ] :
flag = " xjvf "
self . this_src = destfile [ : - 8 ]
else :
print2log ( " Unknown tar file type: %s " % fname )
sys . exit ( 1 )
if toUnpack :
print2log ( " Unpacking %s ... " % fname )
if not os . path . isfile ( destfile ) :
print2log ( " Could not find file %s . Please download it first using -d %s " % ( destfile , self . item . name ) )
sys . exit ( 1 )
changedir ( self . paths . src )
command = " tar - %s %s " % ( flag , destfile )
print2log ( command , cmd = True )
if not VERBOSE :
command + = " > /dev/null "
WORKING = barthread . BarThread ( )
subprocess . check_call ( command , shell = True )
WORKING . stop ( )
WORKING = None
else :
print2log ( " ...unsupported archive scheme for %s " % destfile )
sys . exit ( 1 )
def install ( self ) :
"""
Install the item .
Method can be config ( make ) or setup ( setup . py )
"""
env = self . item . properties [ ' environment ' ]
method = self . item . properties [ ' installation_method ' ]
if env :
self . setEnv ( env )
cwd = self . cd_this_bld ( )
build_folder = os . path . basename ( self . this_bld )
print2log ( " Installing %s ... " % build_folder )
if not os . path . isdir ( self . this_src ) :
print2log ( " Could not find folder %s . Please download and unpack %s first. " % ( self . this_src , self . item . name ) )
sys . exit ( 1 )
if method == ' config ' :
builddir = self . this_bld
if self . item . properties [ ' prestring ' ] :
prestr = self . item . properties [ ' prestring ' ] + " "
else :
prestr = " "
if platform . system ( ) . lower ( ) == " freebsd " :
make = " gmake " #for FreeBSD, use gmake instead of make
else :
make = " make "
commands = [ ( " configure " , prestr + os . path . join ( self . this_src , " configure " ) + self . flags , True ) ,
( " build " , make , True ) ,
( " install " , make + " install " , True ) ]
elif method == ' setup ' :
#we build in src folder rather than in build folder (some setup.py won't work otherwise)
builddir = self . this_src
if " --prefix= " in self . flags :
#replace --prefix=path by --home=path (the python module will be installed in path/lib(64)/python/)
self . flags = self . flags . replace ( " --prefix= " , " --home= " )
#execute: setup.py configure with flags
commands = [ ( " setup " , " python " + os . path . join ( self . this_src , " setup.py configure " + self . flags ) , False ) ]
#previous command gives an error if configure is not needed, the script will then skip "configure"
#execute setup.py install
commands . append ( ( " setup " , " python " + os . path . join ( self . this_src , " setup.py install " + self . flags ) , True ) )
else :
print2log ( " ProgError: Unknown installation method for %s . " % self . item . name )
sys . exit ( 1 )
changedir ( builddir )
printenv ( " Current values of environment variables: \n " )
for ( step , command , critical ) in commands :
print2log ( command , cmd = True )
logfile = " %s _ %s .log " % ( os . path . join ( self . this_bld , self . item . name ) , step )
executeCommand ( command , logfile , critical )
changedir ( cwd )
if env :
self . restoreEnv ( )
print2log ( " Installation of %s done " % self . item . name )
def cd_this_bld ( self ) :
"""
Return the current directory
and create build directory
"""
cwd = os . getenv ( ' PWD ' )
self . this_bld = os . path . join ( self . paths . bld , os . path . basename ( self . this_src ) )
removefolder ( self . this_bld )
createfolder ( self . this_bld )
return cwd
def setEnv ( self , vars_dict ) :
"""
Save current environment and update environment with variables in vars_dict
"""
self . env = { }
for var , val in vars_dict . items ( ) :
self . env [ var ] = os . getenv ( var )
os . environ [ var ] = val
def restoreEnv ( self ) :
"""
Restore environment saved by setEnv
"""
for var , val in self . env . items ( ) :
if val :
os . environ [ var ] = val
else :
os . environ . pop ( var )
class Paths ( object ) :
"""
This class allows the creation of subdirectories below prefix
"""
def __init__ ( self , prefix , python_version ) :
self . prefix = prefix
paths = [ ]
for folder in [ " src " , " bin " , " lib " , " include " , " build " ] :
path = os . path . join ( prefix , folder )
if not os . path . isdir ( path ) :
createfolder ( path )
paths . append ( path )
( self . src , self . bin , self . lib , self . inc , self . bld ) = tuple ( paths )
pkg_dir = ' : ' . join ( [ os . path . join ( self . lib + bits , " python " ) for bits in [ ' 64 ' , ' ' , ' 32 ' ] ] )
self . pkg = pkg_dir
class URLItem ( object ) :
"""
This class defines an item ( i . e . , a dependency ) with its url and properties
"""
def __init__ ( self , name , urls , properties ) :
self . name = name
self . urls = urls
keys = ( ' installation_method ' , ' flags_list ' , ' user_flags ' , ' prestring ' , ' environment ' )
if len ( keys ) != len ( properties ) :
print2log ( " ProgError: Please check that the properties given are correct for %s in class ISCEDeps. " % name )
sys . exit ( 1 )
self . properties = dict ( zip ( keys , properties ) )
class ISCEDeps ( object ) :
"""
This class prepares the environment and installs dependencies ,
before installing ISCE .
"""
dependency_list = [ " GMP " , " MPFR " , " MPC " , " GCC " , " SCONS " , " FFTW " , " SZIP " , " HDF5 " , " NUMPY " , " H5PY " ] #list of packages that can be installed, order matters! use uppercase!
deplog_key = [ " skipped " , " downloaded " , " unpacked " , " installed " ] #dependency log
def __init__ ( self , * * kwargs ) :
global VERBOSE
try :
VERBOSE = kwargs [ " verbose " ]
except :
pass
version = sys . version_info
self . python_version = " {} . {} " . format ( version . major , version . minor )
# p = subprocess.Popen(['python3', '-V'], stdout=subprocess.PIPE)
# x = p.communicate()[0]
# stv = ''.join([e if isinstance(e,str) else e.decode("utf-8") for e in x])
# self.python_version = "%s.%s" % tuple(stv.split(' ')[1].split('.')[:2])
# python_version is now the python3 version (not the sys.version_info)
self . uname = kwargs [ " uname " ]
self . bash_vars = [ ] #environment variables to be written in bash file
self . dependency_log = { }
for key in self . deplog_key :
self . dependency_log [ key ] = [ ]
self . prefix = kwargs [ " prefix " ]
if self . prefix : #if prefix given
self . paths = Paths ( self . prefix , self . python_version )
else :
self . paths = None
try :
#config file is given: skip installation of dependencies
self . config = kwargs [ " config " ]
return
except KeyError :
#config file not given
self . config = None
#read setup_config.py
setup_config = readSetupConfig ( SETUP_CONFIG + ' .py ' )
properties = { } # dictionary of properties for each item to be installed
GCC = kwargs [ " gcc " ]
GXX = kwargs [ " gpp " ]
prestring = " CC= " + GCC + " CXX= " + GXX
env = { #use the latest compilers installed with gcc
' CC ' : os . path . join ( self . paths . bin , " gcc " ) ,
' F77 ' : os . path . join ( self . paths . bin , " gfortran " )
}
#to add a new item:
#properties[name_of_item] = (installation_method, flags_list, user_flags, prestring, environment)
properties [ " GMP " ] = ( " config " , [ " --enable-cxx " ] , None , prestring , None )
properties [ " MPFR " ] = ( " config " , [ " --with-gmp= " + self . prefix ] , None , prestring , None )
properties [ " MPC " ] = ( " config " , [ " --with-gmp= " + self . prefix , " --with-mpfr= " + self . prefix ] , None , None , None )
properties [ " GCC " ] = ( " config " , [ " --with-gmp= " + self . prefix , " --with-mpfr= " + self . prefix , " --enable-languages=c,c++,fortran " , " --enable-threads " ] , None , prestring , None )
properties [ " SCONS " ] = ( " setup " , [ ] , None , None , None )
properties [ " FFTW " ] = ( " config " , [ " --enable-single " , " --enable-shared " ] , None , None , env )
properties [ " SZIP " ] = ( " config " , [ ] , None , None , None )
properties [ " HDF5 " ] = ( " config " , [ " --enable-fortran " , " --enable-cxx " ] , None , None , None )
properties [ " NUMPY " ] = ( " setup " , [ ] , None , None , None )
properties [ " H5PY " ] = ( " setup " , [ " --hdf5= " + self . prefix ] , None , None , None )
""" TODO: we can try to support the installation of the following packages if needed
properties [ " MOTIF " ] = ( " config " , [ ] , None , None , None )
properties [ " SPHINX " ] = ( " setup " , [ ] , None , None , None )
properties [ " XT " ] = ( " config " , [ ] , None , None , None )
properties [ " XP " ] = ( " config " , [ ] , None , None , None )
"""
self . urlitems = { }
#install dependencies
for dep in self . dependency_list :
self . make_urls ( setup_config , dep , properties [ dep ] )
toDownload = kwargs [ " download " ]
toUnpack = kwargs [ " unpack " ]
toInstall = kwargs [ " install " ]
if not ( toDownload + toUnpack + toInstall ) : # none given: do everything
toDownload = self . dependency_list
toUnpack = self . dependency_list
toInstall = self . dependency_list
else : # at least one is given
toDownload = self . getDepList ( toDownload ) # get list of dependencies to download
toUnpack = self . getDepList ( toUnpack ) # get list of dependencies to unpack
toUnpack . extend ( toDownload ) # add depedencies from download list
toUnpack = " , " . join ( toUnpack ) # make list back into a comma-separated string
toUnpack = self . getDepList ( toUnpack ) # remove duplicata and reorder dependencies
toInstall = self . getDepList ( toInstall ) # get list of dependencies to install
toInstall . extend ( toUnpack ) # add dependencies from unpack list (and download list)
toInstall = " , " . join ( toInstall ) # make list into a comma-separated string
toInstall = self . getDepList ( toInstall ) # remove duplicata and reorder dependencies
self . toDownload = toDownload
self . toUnpack = toUnpack
self . toInstall = toInstall
def getDepList ( self , depList ) :
"""
Take a string and return a list of dependencies
The list is ordered according to self . dependency_list
"""
if depList . upper ( ) == " NONE " or depList == " " :
return [ ]
elif depList . upper ( ) == " ALL " :
return list ( self . dependency_list )
else :
fill = False
if depList . endswith ( ' + ' ) : #given string ends with >
fill = True
depList = depList [ : - 1 ]
givenList = depList . upper ( ) . split ( " , " )
if fill :
#get last element of given list
last = givenList [ - 1 ]
#find where last element is located in dependency_list
index = self . dependency_list . index ( givenList [ - 1 ] )
#append all dependencies following last element
givenList . extend ( self . dependency_list [ index + 1 : ] )
depList = [ ]
for dep in self . dependency_list :
if dep in givenList and dep in self . urlitems :
depList . append ( dep )
return depList
def make_urls ( self , config , dependency , properties ) :
"""
Check if a dependency is in config file
And add corresponding URLItem object to self . urlitems
"""
try :
urls = config [ dependency ]
item = URLItem ( dependency , urls , properties )
urlpath , fname = os . path . split ( urls [ 0 ] )
item . destfile = os . path . join ( self . paths . src , fname )
self . urlitems [ dependency ] = item
except AttributeError :
self . dependency_log [ " skipped " ] . append ( dependency )
print2log ( " Item %s not given in %s .py. Proceeding as if it has already been installed and hoping for the best... " % ( dependency , SETUP_CONFIG ) )
def run ( self ) :
"""
Run main script for installing dependencies and ISCE
"""
self . prepare ( ) #prepare environment for installation
self . installIsce ( ) #install isce with Scons
self . createBashFile ( ) #create a bash file with environment variables
def unpackinstall ( self ) :
"""
Unpack the dependencies in self . toUnpack ( if needed )
then install those in self . toInstall
"""
insList = [ ]
for dep in self . toInstall :
item = self . urlitems [ dep ]
ins = InstallItem ( item , self . paths )
if dep in self . toUnpack :
ins . unpack ( True )
self . dependency_log [ " unpacked " ] . append ( ins . item . name )
else :
ins . unpack ( False )
insList . append ( ins )
for ins in insList :
ins . install ( )
self . dependency_log [ " installed " ] . append ( ins . item . name )
def download ( self ) :
"""
Download the dependencies specified in self . toDownload
"""
global WORKING
for dep in self . toDownload :
item = self . urlitems [ dep ]
for url in item . urls :
urlpath , fname = os . path . split ( url )
print2log ( " Downloading %s from %s to %s " % ( fname , urlpath , self . paths . src ) )
WORKING = barthread . BarThread ( )
response = downloadfile ( url , item . destfile , repeat = 2 )
if response :
if os . path . exists ( item . destfile ) :
self . dependency_log [ " downloaded " ] . append ( item . name )
WORKING . stop ( )
WORKING = None
break
else :
continue
if not os . path . exists ( item . destfile ) :
msg = " Cannot download %s . Please check your internet connection and make sure that the download url for %s in %s .py is correct. \n "
msg + = " You might also consider installing the package manually: see tutorial. " % ( fname , item . name , SETUP_CONFIG )
print2log ( msg )
sys . exit ( 1 )
def createConfigFile ( self ) :
"""
Create SConfigISCE file
"""
MANDATORY_VARS = [ ' PRJ_SCONS_BUILD ' , ' PRJ_SCONS_INSTALL ' , ' LIBPATH ' , ' CPPPATH ' , ' FORTRAN ' , ' CC ' , ' CXX ' , ' FORTRANPATH ' ] # ML added FORTRANPATH 2014-04-02
OPTIONAL_VARS = [ ' MOTIFLIBPATH ' , ' X11LIBPATH ' , ' MOTIFINCPATH ' , ' X11INCPATH ' ]
mandatory_ok = True
optional_ok = True
msg = " Creating configuration file... \n "
self . config_values [ ' PRJ_SCONS_BUILD ' ] = os . path . join ( self . paths . bld , ' isce_build ' )
msg + = " ISCE will be built in %s \n " % self . config_values [ ' PRJ_SCONS_BUILD ' ]
self . config_values [ ' PRJ_SCONS_INSTALL ' ] = os . getenv ( ' ISCE_HOME ' )
msg + = " ISCE will be installed in %s \n " % self . config_values [ ' PRJ_SCONS_INSTALL ' ]
libpath = [ ]
for bits in [ " 64 " , " " , " 32 " ] :
if os . path . isdir ( self . paths . lib + bits ) :
libpath . append ( self . paths . lib + bits )
self . updatePath ( ' LD_LIBRARY_PATH ' , libpath )
libpath = os . getenv ( ' LD_LIBRARY_PATH ' ) . split ( ' : ' )
self . config_values [ ' LIBPATH ' ] = " " . join ( libpath )
msg + = " Libraries will be checked inside %s \n " % self . config_values [ ' LIBPATH ' ]
print ( os . path . join ( ' python ' + self . python_version + ' m ' , ' Python.h ' ) )
CPPPATH = self . getFilePath ( os . path . join ( ' python ' + self . python_version + ' m ' , ' Python.h ' ) ) # ML added +'m' on 2014-04-02 to reflect new location
self . config_values [ ' CPPPATH ' ] = os . path . join ( CPPPATH , ' python ' + self . python_version + ' m ' ) # ML added +'m' on 2014-04-02 to reflect new location
print ( os . path . join ( CPPPATH , ' python ' + self . python_version + ' m ' ) )
if CPPPATH :
msg + = " Python.h was found in %s \n " % self . config_values [ ' CPPPATH ' ]
else :
mandatory_ok = False
msg + = " Python.h could NOT be found. Please edit the file %s and add the location of Python.h for the variable CPPPATH \n " % CONFIG_FILE
fortranpath = self . getFilePath ( ' fftw3.f ' )
self . config_values [ ' FORTRANPATH ' ] = fortranpath
if fortranpath :
msg + = " fftw3.f was found in %s \n " % self . config_values [ ' FORTRANPATH ' ]
else :
mandatory_ok = False
msg + = " fftw3.f could NOT be found. Please edit the file %s and add the location of fftw3.f for the variable FORTRANPATH \n " % CONFIG_FILE
COMPILERS = [
( ' Fortran ' , ' FORTRAN ' , ' gfortran ' ) , #(compiler name, variable name, executable name)
( ' C ' , ' CC ' , ' gcc ' ) ,
( ' C++ ' , ' CXX ' , ' g++ ' )
]
for compiler in COMPILERS :
path = self . getFilePath ( compiler [ 2 ] )
self . config_values [ compiler [ 1 ] ] = os . path . join ( path , compiler [ 2 ] )
if path :
msg + = " The path of your %s compiler is %s \n " % ( compiler [ 0 ] , self . config_values [ compiler [ 1 ] ] )
else :
mandatory_ok = False
msg + = " No %s compiler has been found. Please edit the file %s and add the location of your %s compiler for the variable %s \n " % ( compiler [ 0 ] , CONFIG_FILE , compiler [ 0 ] , compiler [ 1 ] )
if self . uname == ' Darwin ' : #Mac OS
ext = ' dylib '
else : #should be Linux (doesn't work with Windows)
ext = ' so '
MDX_DEP = [
( ' MOTIFLIBPATH ' , ' libXm. ' + ext ) , #(variable name, library name)
( ' X11LIBPATH ' , ' libXt. ' + ext ) ,
( ' MOTIFINCPATH ' , os . path . join ( ' Xm ' , ' Xm.h ' ) ) ,
( ' X11INCPATH ' , os . path . join ( ' X11 ' , ' X.h ' ) )
]
for dep in MDX_DEP :
path = self . getFilePath ( dep [ 1 ] )
self . config_values [ dep [ 0 ] ] = path
if path :
msg + = " The path of %s is %s \n " % ( dep [ 1 ] , path )
else :
optional_ok = False
msg + = " %s has NOT been found. Please edit the file %s and add the location of %s for the variable %s \n " % ( dep [ 1 ] , CONFIG_FILE , dep [ 1 ] , dep [ 0 ] )
config_vars = MANDATORY_VARS
if optional_ok :
config_vars . extend ( OPTIONAL_VARS )
else :
print2log ( " Could not find libraries for building mdx. " )
f = open ( os . path . join ( SCONS_CONFIG_DIR , CONFIG_FILE ) , ' wb ' )
for var in config_vars :
f . write ( " %s = %s \n " % ( var , self . config_values [ var ] ) )
f . close ( )
print2log ( msg )
if not mandatory_ok : #config file is not complete...
msg = " You need to edit the file %s located in %s , before going further. \n " % ( CONFIG_FILE , SCONS_CONFIG_DIR )
msg + = " Then run the following command to install ISCE: \n "
msg + = " ./install.sh -p %s -c %s " % ( self . prefix , os . path . join ( SCONS_CONFIG_DIR , CONFIG_FILE ) )
print2log ( msg , False )
sys . exit ( 1 )
def getFilePath ( self , name ) :
"""
Return a path containing the file ' name ' . The path is searched inside env var PATH .
"""
path_found = " "
for path in os . getenv ( ' PATH ' ) . split ( ' : ' ) :
if path_found :
break
if os . path . isfile ( os . path . join ( path , name ) ) : #name found inside path
path_found = path
else :
dirname , basename = os . path . split ( path )
if basename == ' bin ' : #if path ends with 'bin'
for folder in [ ' lib64 ' , ' lib ' , ' lib32 ' , ' include ' ] : #look inside lib and include folders
if os . path . isfile ( os . path . join ( dirname , folder , name ) ) :
path_found = os . path . join ( dirname , folder )
break
return path_found
def installIsce ( self ) :
"""
Install ISCE
"""
print2log ( " Installing ISCE... " )
os . environ [ ' PYTHONPATH ' ] + = " : " + CONFIG_FOLDER #add config folder to pythonpath
if self . paths :
self . updatePath ( ' PATH ' , [ self . paths . bin ] )
changedir ( os . path . dirname ( THIS_FOLDER ) )
command = " scons install "
printenv ( " Current values of environnement variables: \n " )
logfile = " %s .log " % self . config_values [ ' PRJ_SCONS_BUILD ' ]
print2log ( command , cmd = True )
executeCommand ( command , logfile )
def createBashFile ( self ) :
"""
Create file with environment variables
"""
f = open ( BASH_FILE , ' wb ' )
for var in self . bash_vars :
goodpaths = [ ]
exp , val = var . split ( ' = ' )
paths = val . split ( ' : ' )
for path in paths :
if os . path . isdir ( path ) :
goodpaths . append ( path )
f . write ( " %s = %s \n " % ( exp , ' : ' . join ( goodpaths ) ) )
f . close ( )
msg = " ISCE INSTALLATION DONE \n "
msg + = " ISCE has been successfully installed! \n "
msg + = " ISCE applications are located in %s \n " % self . config_values [ ' PRJ_SCONS_INSTALL ' ]
msg + = " Environment variables needed by ISCE are defined in the file %s \n " % BASH_FILE
msg + = " Before running ISCE, source this file in order to add the variables to your environment: \n "
msg + = " source %s \n " % BASH_FILE
msg + = " You can source the file in your .bashrc file so that the variables are automatically defined in your shell. "
print2log ( msg )
def prepare ( self ) :
"""
Prepare environment for installation
"""
self . config_values = { } #variable values to be written to config file (or extracted from config file if given)
if self . config : #config file is given by user (packages are supposed to be pre-installed)
self . readConfigFile ( ) #read file and update self.config_values
self . setEnvironment ( )
else : #config file not given
self . setEnvironment ( )
self . download ( ) #download packages...
self . unpackinstall ( ) #...and install them
self . createConfigFile ( ) #create the config file for Scons
for var in [ ' PATH ' , ' LD_LIBRARY_PATH ' , ' PYTHONPATH ' , ' ISCE_HOME ' ] :
self . bash_vars . append ( " export %s = %s " % ( var , os . getenv ( var ) ) )
def updatePath ( self , varname , pathlist ) :
"""
Append all paths in pathlist at the beginning of env variable varname .
"""
if type ( pathlist ) is list :
oldpath = os . getenv ( varname )
if oldpath : #env not empty
oldpath = oldpath . split ( ' : ' )
for path in oldpath :
if path not in pathlist : #path not in pathlist
pathlist . append ( path ) #add it at the end of pathlist
pathlist = ' : ' . join ( pathlist )
os . environ [ varname ] = pathlist
def setEnvironment ( self ) :
"""
Set environment variables
"""
#Initial values of environment variables
printenv ( " Preparing environment \n Initial values of environment variables: \n " )
pythonpath = [ ]
if self . config :
try :
key = ' PRJ_SCONS_INSTALL '
isce_home = self . config_values [ key ]
key = ' LIBPATH '
lib_path = self . config_values [ key ] . split ( )
except KeyError :
print2log ( " Make sure that %s is present in %s " % ( key , self . config ) )
sys . exit ( 1 )
config_dir , config_file = os . path . split ( self . config )
if config_file != CONFIG_FILE : #make a copy of config file if it's not located in SCONS_CONFIG_DIR
config_copy = os . path . join ( SCONS_CONFIG_DIR , CONFIG_FILE )
shutil . copy ( self . config , config_copy )
if os . path . isfile ( config_copy ) : #check that file has been copied
self . config = config_copy
print2log ( " The config file has been moved to %s " % self . config )
config_dir = SCONS_CONFIG_DIR
else :
msg = " Could not copy %s to %s \n " % ( self . config , config_copy )
msg + = " Please do it manually, then run this command from the setup directory: \n "
msg + = " ./install.sh -c %s " % self . config
print2log ( msg )
sys . exit ( 1 )
else : #config file not given
isce_home = os . path . join ( self . prefix , ' isce ' )
config_dir = SCONS_CONFIG_DIR
lib_path = [ ]
for bits in [ " 64 " , " " , " 32 " ] :
lib_path . append ( self . paths . lib + bits )
if self . paths :
pythonpath . append ( self . paths . pkg )
pythonpath . extend ( [ isce_home , os . path . join ( isce_home , ' applications ' ) , os . path . join ( isce_home , ' components ' ) , self . prefix ] ) # added prefix folder to PYTHONPATH 2/12/13
VAR_TO_UPDATE = {
' PYTHONPATH ' : pythonpath ,
' LD_LIBRARY_PATH ' : lib_path ,
' SCONS_CONFIG_DIR ' : config_dir ,
' ISCE_HOME ' : isce_home ,
}
if self . paths :
VAR_TO_UPDATE [ ' PATH ' ] = [ self . paths . bin ]
if not self . config :
# when installing and using gcc, there's a multiarch problem debuting with Ubuntu Natty and Debian Wheezy
# we need to give explicitly the search path
# http://wiki.debian.org/Multiarch/
if platform . system ( ) . lower ( ) == " linux " :
#distname, version, distid = platform.linux_distribution()
#if (distname.lower() == "ubuntu" and version >= "11") or (distname.lower() == "debian" and version >= "7" ):
machine = platform . machine ( )
if os . path . isdir ( " /usr/lib/ %s -linux-gnu/ " % machine ) :
VAR_TO_UPDATE [ ' LIBRARY_PATH ' ] = [ " /usr/lib/ %s -linux-gnu/ " % machine ] #precompilation search path for libraries
VAR_TO_UPDATE [ ' LD_LIBRARY_PATH ' ] . extend ( VAR_TO_UPDATE [ ' LIBRARY_PATH ' ] )
if os . path . isdir ( " /usr/include/ %s -linux-gnu/ " % machine ) :
VAR_TO_UPDATE [ ' CPATH ' ] = [ " /usr/include/ %s -linux-gnu " % machine ] #precompilation search path for include files
for var , pathlist in VAR_TO_UPDATE . items ( ) :
self . updatePath ( var , pathlist )
os . environ [ ' PATH ' ] + = " : %s " % os . path . join ( os . getenv ( ' ISCE_HOME ' ) , ' applications ' ) #add applications folder to the path
printenv ( " New values of environment variables: \n " )
def readConfigFile ( self ) :
"""
Read config file passed with option - c
"""
f = open ( self . config , ' rb ' )
lines = f . readlines ( )
for line in lines :
2019-11-20 00:40:56 +00:00
m = re . match ( " ([^#].*?)=([^#]+?)$ " , line . strip ( ) . decode ( ' utf-8 ' ) )
2019-01-16 19:40:08 +00:00
if m :
var = m . group ( 1 ) . strip ( )
val = m . group ( 2 ) . strip ( )
self . config_values [ var ] = val
f . close ( )
def readSetupConfig ( setup_config ) :
"""
Read setup_config file where urls are given
"""
params = { }
f = open ( setup_config , ' rb ' )
lines = f . readlines ( )
for line in lines :
2019-11-20 00:40:56 +00:00
m = re . match ( " ([^#].*?)=([^#]+?)$ " , line . strip ( ) . decode ( ' utf-8 ' ) )
2019-01-16 19:40:08 +00:00
if m :
var = m . group ( 1 ) . strip ( )
val = m . group ( 2 ) . strip ( ) . replace ( ' " ' , ' ' )
if var in params . keys ( ) :
params [ var ] . append ( val )
else :
params [ var ] = [ val ]
f . close ( )
return params
def checkArgs ( args ) :
"""
Check arguments passed to this python file
"""
try :
opts , args = getopt . getopt ( args , " h " , [ " help " , " prefix= " , " ping= " , " config= " , " uname= " , " download= " , " unpack= " , " install= " , " gcc= " , " gpp= " , " verbose " ] )
2019-11-20 00:40:56 +00:00
except getopt . GetoptError as err :
2019-01-16 19:40:08 +00:00
print2log ( " ProgError: %s " % str ( err ) )
usage ( )
sys . exit ( 2 )
ok = True
ping = " "
verbose = False
kwargs = { }
for o , a in opts :
if o in ( " -h " , " --help " ) :
ok = False
break
elif o == " --ping " :
ping = a
elif o == " --verbose " :
kwargs [ o [ 2 : ] ] = True
elif o in [ " --prefix " , " --config " , " --uname " ,
" --download " , " --unpack " , " --install " ,
" --gcc " , " --gpp " ] :
kwargs [ o [ 2 : ] ] = a
else :
print2log ( " ProgError: unhandled option: %s " % o )
ok = False
break
if not ( ok and ping == " pong " ) :
usage ( )
sys . exit ( 2 )
try :
kwargs [ " --prefix " ] = os . path . abspath ( kwargs [ " --prefix " ] )
except KeyError :
pass
try :
kwargs [ " --config " ] = os . path . abspath ( kwargs [ " --config " ] )
except KeyError :
pass
return kwargs
if __name__ == " __main__ " :
step = 0
witherror = True
try :
if not os . path . isdir ( SCONS_CONFIG_DIR ) :
createfolder ( SCONS_CONFIG_DIR )
LOGFILE = open ( SETUP_LOG , ' ab ' ) #open SETUP_LOG for appending
print2log ( " = " * 60 , False )
msg = " Starting setup script: \n "
msg + = " " . join ( sys . argv ) + " \n "
msg + = " - " * 60
print2log ( msg )
step = 1
#get arguments from command line
kwargs = checkArgs ( sys . argv [ 1 : ] )
print2log ( " Checking command line... done " )
step = 2
a = ISCEDeps ( * * kwargs )
print2log ( " Initializing script... done " )
step = 3
print2log ( " Starting installation... " )
a . run ( )
witherror = False
except KeyboardInterrupt :
print2log ( " Program interrupted by user. " )
except Exception :
if step == 0 :
msg = " Error when reading script "
elif step == 1 :
msg = " Error when checking command line: "
elif step == 2 :
msg = " Error when initializing script: "
elif step == 3 :
msg = " The script has ended unexpectedly. \n "
msg + = " ##### DEPENDENCIES ##### \n "
for key in a . deplog_key :
try :
msg + = " %s : %s \n " % ( key , " , " . join ( a . dependency_log [ key ] ) )
except KeyError :
msg + = " %s : none \n " % key
msg + = " If you run this installation again, you might want to use advanced options for the script. See tutorial. \n \n "
print2log ( " %s \n %s " % ( msg , traceback . format_exc ( ) ) )
finally :
if WORKING :
WORKING . stop ( False )
WORKING = None
print ( " - " * 60 )
print ( " All the displayed messages have been logged to the file %s . " % SETUP_LOG )
print ( " - " * 60 )
msg = " For any questions, contact %s \n " % CONTACT
if witherror :
msg + = " The setup script ended with errors. "
else :
msg + = " ISCE seems to have been installed correctly. "
print2log ( msg )
LOGFILE . close ( )