xref: /petsc/config/install.py (revision cb5db2414029547a5ccf00a1710ee072432a08af)
1df3bd252SSatish Balay#!/usr/bin/env python3
25b6bfdb9SJed Brownfrom __future__ import print_function
3e551db17SScott Krugerimport os, re, shutil, sys
40ee81e68SLisandro Dalcin
55b6bfdb9SJed Brownif 'PETSC_DIR' in os.environ:
60ee81e68SLisandro Dalcin  PETSC_DIR = os.environ['PETSC_DIR']
70ee81e68SLisandro Dalcinelse:
8c6ef1b5bSJed Brown  fd = open(os.path.join('lib','petsc','conf','petscvariables'))
90ee81e68SLisandro Dalcin  a = fd.readline()
100ee81e68SLisandro Dalcin  a = fd.readline()
110ee81e68SLisandro Dalcin  PETSC_DIR = a.split('=')[1][0:-1]
120ee81e68SLisandro Dalcin  fd.close()
130ee81e68SLisandro Dalcin
145b6bfdb9SJed Brownif 'PETSC_ARCH' in os.environ:
150ee81e68SLisandro Dalcin  PETSC_ARCH = os.environ['PETSC_ARCH']
160ee81e68SLisandro Dalcinelse:
17c6ef1b5bSJed Brown  fd = open(os.path.join('lib','petsc','conf','petscvariables'))
180ee81e68SLisandro Dalcin  a = fd.readline()
190ee81e68SLisandro Dalcin  PETSC_ARCH = a.split('=')[1][0:-1]
200ee81e68SLisandro Dalcin  fd.close()
210ee81e68SLisandro Dalcin
225b6bfdb9SJed Brownprint('*** Using PETSC_DIR='+PETSC_DIR+' PETSC_ARCH='+PETSC_ARCH+' ***')
230ee81e68SLisandro Dalcinsys.path.insert(0, os.path.join(PETSC_DIR, 'config'))
240ee81e68SLisandro Dalcinsys.path.insert(0, os.path.join(PETSC_DIR, 'config', 'BuildSystem'))
250ee81e68SLisandro Dalcin
260ee81e68SLisandro Dalcinimport script
270ee81e68SLisandro Dalcin
280ee81e68SLisandro Dalcintry:
290ee81e68SLisandro Dalcin  WindowsError
300ee81e68SLisandro Dalcinexcept NameError:
310ee81e68SLisandro Dalcin  WindowsError = None
320ee81e68SLisandro Dalcin
330ee81e68SLisandro Dalcinclass Installer(script.Script):
340ee81e68SLisandro Dalcin  def __init__(self, clArgs = None):
350ee81e68SLisandro Dalcin    import RDict
360ee81e68SLisandro Dalcin    argDB = RDict.RDict(None, None, 0, 0, readonly = True)
37af0996ceSBarry Smith    argDB.saveFilename = os.path.join(PETSC_DIR, PETSC_ARCH, 'lib','petsc','conf', 'RDict.db')
380ee81e68SLisandro Dalcin    argDB.load()
390ee81e68SLisandro Dalcin    script.Script.__init__(self, argDB = argDB)
400ee81e68SLisandro Dalcin    if not clArgs is None: self.clArgs = clArgs
410ee81e68SLisandro Dalcin    self.copies = []
420ee81e68SLisandro Dalcin    return
430ee81e68SLisandro Dalcin
440ee81e68SLisandro Dalcin  def setupHelp(self, help):
450ee81e68SLisandro Dalcin    import nargs
460ee81e68SLisandro Dalcin    script.Script.setupHelp(self, help)
47a26d7103SSatish Balay    help.addArgument('Installer', '-destDir=<path>', nargs.Arg(None, '', 'Destination Directory for install'))
48fad83eadSPatrick Sanan    help.addArgument('Installer', '-no-examples', nargs.Arg(None, '', 'Skip installing examples'))
490ee81e68SLisandro Dalcin    return
500ee81e68SLisandro Dalcin
510ee81e68SLisandro Dalcin
520ee81e68SLisandro Dalcin  def setupModules(self):
530ee81e68SLisandro Dalcin    self.setCompilers  = self.framework.require('config.setCompilers',         None)
540ee81e68SLisandro Dalcin    self.arch          = self.framework.require('PETSc.options.arch',          None)
550ee81e68SLisandro Dalcin    self.petscdir      = self.framework.require('PETSc.options.petscdir',      None)
560ee81e68SLisandro Dalcin    self.compilers     = self.framework.require('config.compilers',            None)
5732cabb2fSBarry Smith    self.mpi           = self.framework.require('config.packages.MPI',         None)
580ee81e68SLisandro Dalcin    return
590ee81e68SLisandro Dalcin
600ee81e68SLisandro Dalcin  def setup(self):
610ee81e68SLisandro Dalcin    script.Script.setup(self)
620ee81e68SLisandro Dalcin    self.framework = self.loadConfigure()
630ee81e68SLisandro Dalcin    self.setupModules()
640ee81e68SLisandro Dalcin    return
650ee81e68SLisandro Dalcin
660ee81e68SLisandro Dalcin  def setupDirectories(self):
670ee81e68SLisandro Dalcin    self.rootDir    = self.petscdir.dir
684a08bad0SBarry Smith    self.installDir = os.path.abspath(os.path.expanduser(self.framework.argDB['prefix']))
698727f567SSatish Balay    self.destDir    = os.path.abspath(self.argDB['destDir']+self.installDir)
700ee81e68SLisandro Dalcin    self.arch       = self.arch.arch
7102e047dfSSatish Balay    self.archDir           = os.path.join(self.rootDir, self.arch)
720ee81e68SLisandro Dalcin    self.rootIncludeDir    = os.path.join(self.rootDir, 'include')
730ee81e68SLisandro Dalcin    self.archIncludeDir    = os.path.join(self.rootDir, self.arch, 'include')
74af0996ceSBarry Smith    self.rootConfDir       = os.path.join(self.rootDir, 'lib','petsc','conf')
75af0996ceSBarry Smith    self.archConfDir       = os.path.join(self.rootDir, self.arch, 'lib','petsc','conf')
76c3a89c15SBarry Smith    self.rootBinDir        = os.path.join(self.rootDir, 'lib','petsc','bin')
770ee81e68SLisandro Dalcin    self.archBinDir        = os.path.join(self.rootDir, self.arch, 'bin')
780ee81e68SLisandro Dalcin    self.archLibDir        = os.path.join(self.rootDir, self.arch, 'lib')
790ee81e68SLisandro Dalcin    self.destIncludeDir    = os.path.join(self.destDir, 'include')
80af0996ceSBarry Smith    self.destConfDir       = os.path.join(self.destDir, 'lib','petsc','conf')
810ee81e68SLisandro Dalcin    self.destLibDir        = os.path.join(self.destDir, 'lib')
82c3a89c15SBarry Smith    self.destBinDir        = os.path.join(self.destDir, 'lib','petsc','bin')
830ee81e68SLisandro Dalcin    self.installIncludeDir = os.path.join(self.installDir, 'include')
84c3a89c15SBarry Smith    self.installBinDir     = os.path.join(self.installDir, 'lib','petsc','bin')
850ee81e68SLisandro Dalcin    self.rootShareDir      = os.path.join(self.rootDir, 'share')
860ee81e68SLisandro Dalcin    self.destShareDir      = os.path.join(self.destDir, 'share')
8779eaf171SScott Kruger    self.rootSrcDir        = os.path.join(self.rootDir, 'src')
880ee81e68SLisandro Dalcin
890ee81e68SLisandro Dalcin    self.ranlib      = self.compilers.RANLIB
900ee81e68SLisandro Dalcin    self.arLibSuffix = self.compilers.AR_LIB_SUFFIX
910ee81e68SLisandro Dalcin    return
920ee81e68SLisandro Dalcin
930ee81e68SLisandro Dalcin  def checkPrefix(self):
940ee81e68SLisandro Dalcin    if not self.installDir:
955b6bfdb9SJed Brown      print('********************************************************************')
965b6bfdb9SJed Brown      print('PETSc is built without prefix option. So "make install" is not appropriate.')
975b6bfdb9SJed Brown      print('If you need a prefix install of PETSc - rerun configure with --prefix option.')
985b6bfdb9SJed Brown      print('********************************************************************')
990ee81e68SLisandro Dalcin      sys.exit(1)
1000ee81e68SLisandro Dalcin    return
1010ee81e68SLisandro Dalcin
1020ee81e68SLisandro Dalcin  def checkDestdir(self):
1030ee81e68SLisandro Dalcin    if os.path.exists(self.destDir):
1040ee81e68SLisandro Dalcin      if os.path.samefile(self.destDir, self.rootDir):
1055b6bfdb9SJed Brown        print('********************************************************************')
1065b6bfdb9SJed Brown        print('Incorrect prefix usage. Specified destDir same as current PETSC_DIR')
1075b6bfdb9SJed Brown        print('********************************************************************')
1080ee81e68SLisandro Dalcin        sys.exit(1)
1090ee81e68SLisandro Dalcin      if os.path.samefile(self.destDir, os.path.join(self.rootDir,self.arch)):
1105b6bfdb9SJed Brown        print('********************************************************************')
1115b6bfdb9SJed Brown        print('Incorrect prefix usage. Specified destDir same as current PETSC_DIR/PETSC_ARCH')
1125b6bfdb9SJed Brown        print('********************************************************************')
1130ee81e68SLisandro Dalcin        sys.exit(1)
1140ee81e68SLisandro Dalcin      if not os.path.isdir(os.path.realpath(self.destDir)):
1155b6bfdb9SJed Brown        print('********************************************************************')
1165b6bfdb9SJed Brown        print('Specified destDir', self.destDir, 'is not a directory. Cannot proceed!')
1175b6bfdb9SJed Brown        print('********************************************************************')
1180ee81e68SLisandro Dalcin        sys.exit(1)
1190ee81e68SLisandro Dalcin      if not os.access(self.destDir, os.W_OK):
1205b6bfdb9SJed Brown        print('********************************************************************')
1215b6bfdb9SJed Brown        print('Unable to write to ', self.destDir, 'Perhaps you need to do "sudo make install"')
1225b6bfdb9SJed Brown        print('********************************************************************')
1230ee81e68SLisandro Dalcin        sys.exit(1)
1240ee81e68SLisandro Dalcin    return
1250ee81e68SLisandro Dalcin
1260ee81e68SLisandro Dalcin  def copyfile(self, src, dst, symlinks = False, copyFunc = shutil.copy2):
1270ee81e68SLisandro Dalcin    """Copies a single file    """
1280ee81e68SLisandro Dalcin    copies = []
1290ee81e68SLisandro Dalcin    errors = []
1300ee81e68SLisandro Dalcin    if not os.path.exists(dst):
1310ee81e68SLisandro Dalcin      os.makedirs(dst)
1320ee81e68SLisandro Dalcin    elif not os.path.isdir(dst):
1335b6bfdb9SJed Brown      raise shutil.Error('Destination is not a directory')
1340ee81e68SLisandro Dalcin    srcname = src
1350ee81e68SLisandro Dalcin    dstname = os.path.join(dst, os.path.basename(src))
1360ee81e68SLisandro Dalcin    try:
1370ee81e68SLisandro Dalcin      if symlinks and os.path.islink(srcname):
1380ee81e68SLisandro Dalcin        linkto = os.readlink(srcname)
1390ee81e68SLisandro Dalcin        os.symlink(linkto, dstname)
1400ee81e68SLisandro Dalcin      else:
1410ee81e68SLisandro Dalcin        copyFunc(srcname, dstname)
1420ee81e68SLisandro Dalcin        copies.append((srcname, dstname))
1435b6bfdb9SJed Brown    except (IOError, os.error) as why:
1440ee81e68SLisandro Dalcin      errors.append((srcname, dstname, str(why)))
1455b6bfdb9SJed Brown    except shutil.Error as err:
1462c852529SBarry Smith      errors.append((srcname,dstname,str(err.args[0])))
1470ee81e68SLisandro Dalcin    if errors:
1485b6bfdb9SJed Brown      raise shutil.Error(errors)
1490ee81e68SLisandro Dalcin    return copies
1500ee81e68SLisandro Dalcin
15126e8aaceSBarry Smith  def fixExamplesMakefile(self, src):
15226e8aaceSBarry Smith    '''Change ././${PETSC_ARCH} in makefile in root petsc directory with ${PETSC_DIR}'''
15326e8aaceSBarry Smith    lines   = []
15426e8aaceSBarry Smith    oldFile = open(src, 'r')
155e551db17SScott Kruger    alllines=oldFile.read()
15626e8aaceSBarry Smith    oldFile.close()
157e551db17SScott Kruger    newlines=alllines.split('\n')[0]+'\n'  # Firstline
158d5b43468SJose E. Roman    # Hardcode PETSC_DIR and PETSC_ARCH to avoid users doing the wrong thing
159e551db17SScott Kruger    newlines+='PETSC_DIR='+self.installDir+'\n'
160e551db17SScott Kruger    newlines+='PETSC_ARCH=\n'
161e551db17SScott Kruger    for line in alllines.split('\n')[1:]:
1624ff3c6a1SScott Kruger      if line.startswith('TESTLOGFILE'):
163c173c275SScott Kruger        newlines+='TESTLOGFILE = $(TESTDIR)/examples-install.log\n'
164e551db17SScott Kruger      elif line.startswith('CONFIGDIR'):
165e551db17SScott Kruger        newlines+='CONFIGDIR:=$(PETSC_DIR)/$(PETSC_ARCH)/share/petsc/examples/config\n'
166fc46264cSScott Kruger      elif line.startswith('$(generatedtest)') and 'petscvariables' in line:
167c173c275SScott Kruger        newlines+='all: test\n\n'+line+'\n'
168e551db17SScott Kruger      else:
1694ff3c6a1SScott Kruger        newlines+=line+'\n'
17026e8aaceSBarry Smith    newFile = open(src, 'w')
171e551db17SScott Kruger    newFile.write(newlines)
17226e8aaceSBarry Smith    newFile.close()
17326e8aaceSBarry Smith    return
17426e8aaceSBarry Smith
175e551db17SScott Kruger  def copyConfig(self, src, dst):
1762f21b5d8SJed Brown    """Copy configuration/testing files
177e551db17SScott Kruger    """
178e551db17SScott Kruger    if not os.path.isdir(dst):
1795b6bfdb9SJed Brown      raise shutil.Error('Destination is not a directory')
180e551db17SScott Kruger
181adf35c6eSSatish Balay    self.copies.extend(self.copyfile('gmakefile.test',dst))
182e551db17SScott Kruger    newConfigDir=os.path.join(dst,'config')  # Am not renaming at present
183e551db17SScott Kruger    if not os.path.isdir(newConfigDir): os.mkdir(newConfigDir)
184e551db17SScott Kruger    testConfFiles="gmakegentest.py gmakegen.py testparse.py example_template.py".split()
18558780e5dSStefano Zampini    testConfFiles+="petsc_harness.sh report_tests.py query_tests.py".split()
186e551db17SScott Kruger    for tf in testConfFiles:
187adf35c6eSSatish Balay      self.copies.extend(self.copyfile(os.path.join('config',tf),newConfigDir))
188e551db17SScott Kruger    return
189e551db17SScott Kruger
19026e8aaceSBarry Smith  def copyExamples(self, src, dst):
1914ff3c6a1SScott Kruger    """copy the examples directories
19226e8aaceSBarry Smith    """
193ad246c4dSSatish Balay    for root, dirs, files in os.walk(src, topdown=False):
1942f21b5d8SJed Brown      if os.path.basename(root) not in ("tests", "tutorials"): continue
195ad246c4dSSatish Balay      self.copies.extend(self.copytree(root, root.replace(src,dst)))
1964ff3c6a1SScott Kruger    return
1970ee81e68SLisandro Dalcin
1980080bb28SSatish Balay  def copytree(self, src, dst, symlinks = False, copyFunc = shutil.copy2, exclude = [], exclude_ext= ['.DSYM','.o','.pyc'], recurse = 1):
1990ee81e68SLisandro Dalcin    """Recursively copy a directory tree using copyFunc, which defaults to shutil.copy2().
2000ee81e68SLisandro Dalcin
2010ee81e68SLisandro Dalcin       The copyFunc() you provide is only used on the top level, lower levels always use shutil.copy2
2020ee81e68SLisandro Dalcin
2030ee81e68SLisandro Dalcin    The destination directory must not already exist.
2040ee81e68SLisandro Dalcin    If exception(s) occur, an shutil.Error is raised with a list of reasons.
2050ee81e68SLisandro Dalcin
2060ee81e68SLisandro Dalcin    If the optional symlinks flag is true, symbolic links in the
2070ee81e68SLisandro Dalcin    source tree result in symbolic links in the destination tree; if
2080ee81e68SLisandro Dalcin    it is false, the contents of the files pointed to by symbolic
2090ee81e68SLisandro Dalcin    links are copied.
2100ee81e68SLisandro Dalcin    """
2110ee81e68SLisandro Dalcin    copies = []
2120ee81e68SLisandro Dalcin    names  = os.listdir(src)
2130ee81e68SLisandro Dalcin    if not os.path.exists(dst):
2140ee81e68SLisandro Dalcin      os.makedirs(dst)
2150ee81e68SLisandro Dalcin    elif not os.path.isdir(dst):
2165b6bfdb9SJed Brown      raise shutil.Error('Destination is not a directory')
2170ee81e68SLisandro Dalcin    errors = []
2182c72da00SPierre Jolivet    srclinks = []
2192c72da00SPierre Jolivet    dstlinks = []
2200ee81e68SLisandro Dalcin    for name in names:
2210ee81e68SLisandro Dalcin      srcname = os.path.join(src, name)
2220ee81e68SLisandro Dalcin      dstname = os.path.join(dst, name)
2230ee81e68SLisandro Dalcin      try:
2240ee81e68SLisandro Dalcin        if symlinks and os.path.islink(srcname):
2250ee81e68SLisandro Dalcin          linkto = os.readlink(srcname)
2260ee81e68SLisandro Dalcin          os.symlink(linkto, dstname)
22732cabb2fSBarry Smith        elif os.path.isdir(srcname) and recurse and not os.path.basename(srcname) in exclude:
228adf35c6eSSatish Balay          copies.extend(self.copytree(srcname, dstname, symlinks,exclude = exclude, exclude_ext = exclude_ext))
229adf35c6eSSatish Balay        elif os.path.isfile(srcname) and not os.path.basename(srcname) in exclude and os.path.splitext(name)[1] not in exclude_ext :
2302c72da00SPierre Jolivet          if os.path.islink(srcname):
2312c72da00SPierre Jolivet            srclinks.append(srcname)
2322c72da00SPierre Jolivet            dstlinks.append(dstname)
2332c72da00SPierre Jolivet          else:
2340ee81e68SLisandro Dalcin            copyFunc(srcname, dstname)
2350ee81e68SLisandro Dalcin            copies.append((srcname, dstname))
2360ee81e68SLisandro Dalcin        # XXX What about devices, sockets etc.?
2375b6bfdb9SJed Brown      except (IOError, os.error) as why:
2380ee81e68SLisandro Dalcin        errors.append((srcname, dstname, str(why)))
2390ee81e68SLisandro Dalcin      # catch the Error from the recursive copytree so that we can
2400ee81e68SLisandro Dalcin      # continue with other files
2415b6bfdb9SJed Brown      except shutil.Error as err:
2422c852529SBarry Smith        errors.append((srcname,dstname,str(err.args[0])))
2432c72da00SPierre Jolivet    for srcname, dstname in zip(srclinks, dstlinks):
2442c72da00SPierre Jolivet      try:
2452c72da00SPierre Jolivet        copyFunc(srcname, dstname)
2462c72da00SPierre Jolivet        copies.append((srcname, dstname))
2472c72da00SPierre Jolivet      except (IOError, os.error) as why:
2482c72da00SPierre Jolivet        errors.append((srcname, dstname, str(why)))
2492c72da00SPierre Jolivet      # catch the Error from the recursive copytree so that we can
2502c72da00SPierre Jolivet      # continue with other files
2512c72da00SPierre Jolivet      except shutil.Error as err:
2522c852529SBarry Smith        errors.append((srcname,dstname,str(err.args[0])))
2530ee81e68SLisandro Dalcin    try:
2540ee81e68SLisandro Dalcin      shutil.copystat(src, dst)
2555b6bfdb9SJed Brown    except OSError as e:
2560ee81e68SLisandro Dalcin      if WindowsError is not None and isinstance(e, WindowsError):
2570ee81e68SLisandro Dalcin        # Copying file access times may fail on Windows
2580ee81e68SLisandro Dalcin        pass
2590ee81e68SLisandro Dalcin      else:
2602c852529SBarry Smith        errors.append((src, dst, str(e)))
2610ee81e68SLisandro Dalcin    if errors:
2625b6bfdb9SJed Brown      raise shutil.Error(errors)
2630ee81e68SLisandro Dalcin    return copies
2640ee81e68SLisandro Dalcin
2650ee81e68SLisandro Dalcin
2660ee81e68SLisandro Dalcin  def fixConfFile(self, src):
2670ee81e68SLisandro Dalcin    lines   = []
2680ee81e68SLisandro Dalcin    oldFile = open(src, 'r')
2690ee81e68SLisandro Dalcin    for line in oldFile.readlines():
2705a21677cSJed Brown      if line.startswith('PETSC_CC_INCLUDES =') or line.startswith('PETSC_FC_INCLUDES ='):
2715a21677cSJed Brown        continue
2725a21677cSJed Brown      line = line.replace('PETSC_CC_INCLUDES_INSTALL', 'PETSC_CC_INCLUDES')
2735a21677cSJed Brown      line = line.replace('PETSC_FC_INCLUDES_INSTALL', 'PETSC_FC_INCLUDES')
2740ee81e68SLisandro Dalcin      # remove PETSC_DIR/PETSC_ARCH variables from conf-makefiles. They are no longer necessary
2750ee81e68SLisandro Dalcin      line = line.replace('${PETSC_DIR}/${PETSC_ARCH}', self.installDir)
2760ee81e68SLisandro Dalcin      line = line.replace('PETSC_ARCH=${PETSC_ARCH}', '')
2770ee81e68SLisandro Dalcin      line = line.replace('${PETSC_DIR}', self.installDir)
278011f288aSSatish Balay      # replace PETSC_DIR/lib/petsc/bin with prefix/lib/petsc/bin
279011f288aSSatish Balay      line = line.replace(self.rootBinDir,self.destBinDir)
2800ee81e68SLisandro Dalcin      lines.append(line)
2810ee81e68SLisandro Dalcin    oldFile.close()
2820ee81e68SLisandro Dalcin    newFile = open(src, 'w')
2830ee81e68SLisandro Dalcin    newFile.write(''.join(lines))
2840ee81e68SLisandro Dalcin    newFile.close()
2850ee81e68SLisandro Dalcin    return
2860ee81e68SLisandro Dalcin
2870ee81e68SLisandro Dalcin  def fixConf(self):
2880ee81e68SLisandro Dalcin    import shutil
289*cb5db241SBarry Smith    for file in ['rules', 'rules_doc.mk', 'rules_util.mk', 'variables', 'petscrules', 'petscvariables']:
2900ee81e68SLisandro Dalcin      self.fixConfFile(os.path.join(self.destConfDir,file))
2910ee81e68SLisandro Dalcin    return
2920ee81e68SLisandro Dalcin
2930ee81e68SLisandro Dalcin  def createUninstaller(self):
2940ee81e68SLisandro Dalcin    uninstallscript = os.path.join(self.destConfDir, 'uninstall.py')
2950ee81e68SLisandro Dalcin    f = open(uninstallscript, 'w')
2960ee81e68SLisandro Dalcin    # Could use the Python AST to do this
2970ee81e68SLisandro Dalcin    f.write('#!'+sys.executable+'\n')
2980ee81e68SLisandro Dalcin    f.write('import os\n')
299d97f9ea1SSatish Balay    f.write('prefixdir = "'+self.installDir+'"\n')
300d97f9ea1SSatish Balay    files = [dst.replace(self.destDir,self.installDir) for src, dst in self.copies]
301d97f9ea1SSatish Balay    files.append(uninstallscript.replace(self.destDir,self.installDir))
302d97f9ea1SSatish Balay    f.write('files = '+repr(files))
3030ee81e68SLisandro Dalcin    f.write('''
304d97f9ea1SSatish Balayfor file in files:
305d97f9ea1SSatish Balay  if os.path.exists(file) or os.path.islink(file):
306d97f9ea1SSatish Balay    os.remove(file)
307d97f9ea1SSatish Balay    dir = os.path.dirname(file)
3082b39596bSSatish Balay    while dir not in [os.path.dirname(prefixdir),'/']:
3092b39596bSSatish Balay      try: os.rmdir(dir)
3102b39596bSSatish Balay      except: break
311d97f9ea1SSatish Balay      dir = os.path.dirname(dir)
3120ee81e68SLisandro Dalcin''')
3130ee81e68SLisandro Dalcin    f.close()
3145b6bfdb9SJed Brown    os.chmod(uninstallscript,0o744)
3150ee81e68SLisandro Dalcin    return
3160ee81e68SLisandro Dalcin
3170ee81e68SLisandro Dalcin  def installIncludes(self):
31832cabb2fSBarry Smith    exclude = ['makefile']
31932cabb2fSBarry Smith    if not hasattr(self.compilers.setCompilers, 'FC'):
32032cabb2fSBarry Smith      exclude.append('finclude')
32132cabb2fSBarry Smith    if not self.mpi.usingMPIUni:
32232cabb2fSBarry Smith      exclude.append('mpiuni')
32332cabb2fSBarry Smith    self.copies.extend(self.copytree(self.rootIncludeDir, self.destIncludeDir,exclude = exclude))
3240ee81e68SLisandro Dalcin    self.copies.extend(self.copytree(self.archIncludeDir, self.destIncludeDir))
3250ee81e68SLisandro Dalcin    return
3260ee81e68SLisandro Dalcin
3270ee81e68SLisandro Dalcin  def installConf(self):
32832cabb2fSBarry Smith    self.copies.extend(self.copytree(self.rootConfDir, self.destConfDir, exclude = ['uncrustify.cfg','bfort-base.txt','bfort-petsc.txt','bfort-mpi.txt','test.log']))
329a035e9faSPierre Jolivet    self.copies.extend(self.copytree(self.archConfDir, self.destConfDir, exclude = ['sowing', 'configure.log.bkp','configure.log','make.log','gmake.log','test.log','error.log','memoryerror.log','files','testfiles','RDict.db']))
3300ee81e68SLisandro Dalcin    return
3310ee81e68SLisandro Dalcin
3320ee81e68SLisandro Dalcin  def installBin(self):
33332cabb2fSBarry Smith    exclude = ['bfort','bib2html','doc2lt','doctext','mapnames', 'pstogif','pstoxbm','tohtml']
33432cabb2fSBarry Smith    self.copies.extend(self.copytree(self.archBinDir, self.destBinDir, exclude = exclude ))
33532cabb2fSBarry Smith    exclude = ['maint']
33632cabb2fSBarry Smith    if not self.mpi.usingMPIUni:
33732cabb2fSBarry Smith      exclude.append('petsc-mpiexec.uni')
33832cabb2fSBarry Smith    self.setCompilers.pushLanguage('C')
339011f288aSSatish Balay    if self.setCompilers.getCompiler().find('win32fe') < 0:
34032cabb2fSBarry Smith      exclude.append('win32fe')
34132cabb2fSBarry Smith    self.setCompilers.popLanguage()
34232cabb2fSBarry Smith    self.copies.extend(self.copytree(self.rootBinDir, self.destBinDir, exclude = exclude ))
3430ee81e68SLisandro Dalcin    return
3440ee81e68SLisandro Dalcin
3450ee81e68SLisandro Dalcin  def installShare(self):
3460ee81e68SLisandro Dalcin    self.copies.extend(self.copytree(self.rootShareDir, self.destShareDir))
347c173c275SScott Kruger    examplesdir=os.path.join(self.destShareDir,'petsc','examples')
348c173c275SScott Kruger    if os.path.exists(examplesdir):
349c173c275SScott Kruger      shutil.rmtree(examplesdir)
350c173c275SScott Kruger    os.mkdir(examplesdir)
35179eaf171SScott Kruger    os.mkdir(os.path.join(examplesdir,'src'))
352c173c275SScott Kruger    self.copyConfig(self.rootDir,examplesdir)
353fad83eadSPatrick Sanan    if not self.argDB['no-examples']:
354fad83eadSPatrick Sanan        self.copyExamples(self.rootSrcDir,os.path.join(examplesdir,'src'))
355c173c275SScott Kruger        self.fixExamplesMakefile(os.path.join(examplesdir,'gmakefile.test'))
3560ee81e68SLisandro Dalcin    return
3570ee81e68SLisandro Dalcin
3580ee81e68SLisandro Dalcin  def copyLib(self, src, dst):
3590ee81e68SLisandro Dalcin    '''Run ranlib on the destination library if it is an archive. Also run install_name_tool on dylib on Mac'''
3600ee81e68SLisandro Dalcin    # Symlinks (assumed local) are recreated at dst
3610ee81e68SLisandro Dalcin    if os.path.islink(src):
3620ee81e68SLisandro Dalcin      linkto = os.readlink(src)
3630ee81e68SLisandro Dalcin      try:
3640ee81e68SLisandro Dalcin        os.remove(dst)            # In case it already exists
3650ee81e68SLisandro Dalcin      except OSError:
3660ee81e68SLisandro Dalcin        pass
3670ee81e68SLisandro Dalcin      os.symlink(linkto, dst)
3680ee81e68SLisandro Dalcin      return
3690ee81e68SLisandro Dalcin    shutil.copy2(src, dst)
370011f288aSSatish Balay    if self.setCompilers.getCompiler().find('win32fe') < 0 and os.path.splitext(dst)[1] == '.'+self.arLibSuffix:
3710ee81e68SLisandro Dalcin      self.executeShellCommand(self.ranlib+' '+dst)
3720ee81e68SLisandro Dalcin    if os.path.splitext(dst)[1] == '.dylib' and os.path.isfile('/usr/bin/install_name_tool'):
373af2c601bSBarry Smith      [output,err,flg] = self.executeShellCommand("otool -D "+src)
374af2c601bSBarry Smith      oldname = output[output.find("\n")+1:]
375d4c3e6c5SSatish Balay      installName = oldname.replace(os.path.realpath(self.archDir), self.installDir)
3760ee81e68SLisandro Dalcin      self.executeShellCommand('/usr/bin/install_name_tool -id ' + installName + ' ' + dst)
3770ee81e68SLisandro Dalcin    # preserve the original timestamps - so that the .a vs .so time order is preserved
3780ee81e68SLisandro Dalcin    shutil.copystat(src,dst)
3790ee81e68SLisandro Dalcin    return
3800ee81e68SLisandro Dalcin
3810ee81e68SLisandro Dalcin  def installLib(self):
38232cabb2fSBarry Smith    self.copies.extend(self.copytree(self.archLibDir, self.destLibDir, copyFunc = self.copyLib, exclude = ['.DIR'],recurse = 0))
38332cabb2fSBarry Smith    self.copies.extend(self.copytree(os.path.join(self.archLibDir,'pkgconfig'), os.path.join(self.destLibDir,'pkgconfig'), copyFunc = self.copyLib, exclude = ['.DIR'],recurse = 0))
3840ee81e68SLisandro Dalcin    return
3850ee81e68SLisandro Dalcin
3860ee81e68SLisandro Dalcin
3870ee81e68SLisandro Dalcin  def outputInstallDone(self):
3885b4fc442SVaclav Hapla    from config.packages.make import getMakeUserPath
3895b6bfdb9SJed Brown    print('''\
3900ee81e68SLisandro Dalcin====================================
3910ee81e68SLisandro DalcinInstall complete.
3920ee81e68SLisandro DalcinNow to check if the libraries are working do (in current directory):
3935b4fc442SVaclav Hapla%s PETSC_DIR=%s PETSC_ARCH="" check
3940ee81e68SLisandro Dalcin====================================\
3955b4fc442SVaclav Hapla''' % (getMakeUserPath(self.arch), self.installDir))
3960ee81e68SLisandro Dalcin    return
3970ee81e68SLisandro Dalcin
3980ee81e68SLisandro Dalcin  def outputDestDirDone(self):
3995b6bfdb9SJed Brown    print('''\
4000ee81e68SLisandro Dalcin====================================
4010ee81e68SLisandro DalcinCopy to DESTDIR %s is now complete.
4020ee81e68SLisandro DalcinBefore use - please copy/install over to specified prefix: %s
4030ee81e68SLisandro Dalcin====================================\
4045b6bfdb9SJed Brown''' % (self.destDir,self.installDir))
4050ee81e68SLisandro Dalcin    return
4060ee81e68SLisandro Dalcin
4070ee81e68SLisandro Dalcin  def runsetup(self):
4080ee81e68SLisandro Dalcin    self.setup()
4090ee81e68SLisandro Dalcin    self.setupDirectories()
4100ee81e68SLisandro Dalcin    self.checkPrefix()
4110ee81e68SLisandro Dalcin    self.checkDestdir()
4120ee81e68SLisandro Dalcin    return
4130ee81e68SLisandro Dalcin
4140ee81e68SLisandro Dalcin  def runcopy(self):
4150ee81e68SLisandro Dalcin    if self.destDir == self.installDir:
4165b6bfdb9SJed Brown      print('*** Installing PETSc at prefix location:',self.destDir, ' ***')
4170ee81e68SLisandro Dalcin    else:
4185b6bfdb9SJed Brown      print('*** Copying PETSc to DESTDIR location:',self.destDir, ' ***')
4190ee81e68SLisandro Dalcin    if not os.path.exists(self.destDir):
4200ee81e68SLisandro Dalcin      try:
4210ee81e68SLisandro Dalcin        os.makedirs(self.destDir)
4220ee81e68SLisandro Dalcin      except:
4235b6bfdb9SJed Brown        print('********************************************************************')
4245b6bfdb9SJed Brown        print('Unable to create', self.destDir, 'Perhaps you need to do "sudo make install"')
4255b6bfdb9SJed Brown        print('********************************************************************')
4260ee81e68SLisandro Dalcin        sys.exit(1)
4270ee81e68SLisandro Dalcin    self.installIncludes()
4280ee81e68SLisandro Dalcin    self.installConf()
4290ee81e68SLisandro Dalcin    self.installBin()
4300ee81e68SLisandro Dalcin    self.installLib()
4310ee81e68SLisandro Dalcin    self.installShare()
4320ee81e68SLisandro Dalcin    return
4330ee81e68SLisandro Dalcin
4340ee81e68SLisandro Dalcin  def runfix(self):
4350ee81e68SLisandro Dalcin    self.fixConf()
4360ee81e68SLisandro Dalcin    return
4370ee81e68SLisandro Dalcin
4380ee81e68SLisandro Dalcin  def rundone(self):
4390ee81e68SLisandro Dalcin    self.createUninstaller()
4400ee81e68SLisandro Dalcin    if self.destDir == self.installDir:
4410ee81e68SLisandro Dalcin      self.outputInstallDone()
4420ee81e68SLisandro Dalcin    else:
4430ee81e68SLisandro Dalcin      self.outputDestDirDone()
4440ee81e68SLisandro Dalcin    return
4450ee81e68SLisandro Dalcin
4460ee81e68SLisandro Dalcin  def run(self):
4470ee81e68SLisandro Dalcin    self.runsetup()
4480ee81e68SLisandro Dalcin    self.runcopy()
4490ee81e68SLisandro Dalcin    self.runfix()
4500ee81e68SLisandro Dalcin    self.rundone()
4510ee81e68SLisandro Dalcin    return
4520ee81e68SLisandro Dalcin
4530ee81e68SLisandro Dalcinif __name__ == '__main__':
4540ee81e68SLisandro Dalcin  Installer(sys.argv[1:]).run()
4550ee81e68SLisandro Dalcin  # temporary hack - delete log files created by BuildSystem - when 'sudo make install' is invoked
45603e6d329SSatish Balay  delfiles=['RDict.db','RDict.log','buildsystem.log','default.log','buildsystem.log.bkp','default.log.bkp']
4570ee81e68SLisandro Dalcin  for delfile in delfiles:
4580ee81e68SLisandro Dalcin    if os.path.exists(delfile) and (os.stat(delfile).st_uid==0):
4590ee81e68SLisandro Dalcin      os.remove(delfile)
460