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 289cb5db241SBarry 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 2935ee53db2SLisandro Dalcin def fixPythonWheel(self): 2945ee53db2SLisandro Dalcin import glob 2955ee53db2SLisandro Dalcin import shutil 2965ee53db2SLisandro Dalcin # 2975ee53db2SLisandro Dalcin for pattern in ( 2985ee53db2SLisandro Dalcin self.destLibDir + '/*.a', 2995ee53db2SLisandro Dalcin self.destLibDir + '/*.la', 3005ee53db2SLisandro Dalcin self.destLibDir + '/pkgconfig', # TODO: keep? 3015ee53db2SLisandro Dalcin self.destConfDir + '/configure-hash', 3025ee53db2SLisandro Dalcin self.destConfDir + '/uninstall.py', 3035ee53db2SLisandro Dalcin self.destConfDir + '/reconfigure-*.py', 3045ee53db2SLisandro Dalcin self.destConfDir + '/pkg.conf.*', 3055ee53db2SLisandro Dalcin self.destConfDir + '/pkg.git*.*', 3065ee53db2SLisandro Dalcin self.destConfDir + '/modules', # TODO: keep? 3075ee53db2SLisandro Dalcin self.destShareDir + '/*/examples/src/*', 3085ee53db2SLisandro Dalcin self.destShareDir + '/*/datafiles', 3095ee53db2SLisandro Dalcin ): 3105ee53db2SLisandro Dalcin for pathname in glob.glob(pattern): 3115ee53db2SLisandro Dalcin if os.path.isdir(pathname): 3125ee53db2SLisandro Dalcin shutil.rmtree(pathname) 3135ee53db2SLisandro Dalcin elif os.path.exists(pathname): 3145ee53db2SLisandro Dalcin os.remove(pathname) 3155ee53db2SLisandro Dalcin # 3165ee53db2SLisandro Dalcin for filename in ( 3175ee53db2SLisandro Dalcin self.destIncludeDir + '/petscconf.h', 3185ee53db2SLisandro Dalcin self.destIncludeDir + '/petscconfiginfo.h', 3195ee53db2SLisandro Dalcin self.destIncludeDir + '/petscmachineinfo.h', 3205ee53db2SLisandro Dalcin self.destShareDir + '/petsc/examples/gmakefile.test', 3215ee53db2SLisandro Dalcin self.destConfDir + '/rules', 3225ee53db2SLisandro Dalcin self.destConfDir + '/rules_doc.mk', 3235ee53db2SLisandro Dalcin self.destConfDir + '/rules_util.mk', 3245ee53db2SLisandro Dalcin self.destConfDir + '/petscrules', 3255ee53db2SLisandro Dalcin self.destConfDir + '/variables', 3265ee53db2SLisandro Dalcin self.destConfDir + '/petscvariables', 3275ee53db2SLisandro Dalcin ): 3285ee53db2SLisandro Dalcin with open(filename, 'r') as oldFile: 3295ee53db2SLisandro Dalcin contents = oldFile.read() 3305ee53db2SLisandro Dalcin contents = contents.replace(self.installDir, '${PETSC_DIR}') 3315ee53db2SLisandro Dalcin contents = contents.replace(self.rootDir, '${PETSC_DIR}') 3325ee53db2SLisandro Dalcin contents = re.sub( 3335ee53db2SLisandro Dalcin r'^(PYTHON(_EXE)?) = (.*)$', 3345ee53db2SLisandro Dalcin r'\1 = python%d' % sys.version_info[0], 3355ee53db2SLisandro Dalcin contents, flags=re.MULTILINE, 3365ee53db2SLisandro Dalcin ) 3375ee53db2SLisandro Dalcin with open(filename, 'w') as newFile: 3385ee53db2SLisandro Dalcin newFile.write(contents) 3395ee53db2SLisandro Dalcin # 3405ee53db2SLisandro Dalcin def lsdir(dirname, *patterns): 3415ee53db2SLisandro Dalcin return glob.glob(os.path.join(dirname, *patterns)) 3425ee53db2SLisandro Dalcin def shell(*args): 3435ee53db2SLisandro Dalcin return self.executeShellCommand(' '.join(args))[0] 3445ee53db2SLisandro Dalcin libdir = os.path.join(self.installDir, 'lib') 3455ee53db2SLisandro Dalcin if sys.platform == 'linux': 3465ee53db2SLisandro Dalcin libraries = [ 3475ee53db2SLisandro Dalcin lib for lib in lsdir(self.destLibDir, 'lib*.so*') 3485ee53db2SLisandro Dalcin if not os.path.islink(lib) 3495ee53db2SLisandro Dalcin ] 3505ee53db2SLisandro Dalcin for shlib in libraries: 3515ee53db2SLisandro Dalcin # fix shared library rpath 3525ee53db2SLisandro Dalcin rpath = shell('patchelf', '--print-rpath', shlib) 3535ee53db2SLisandro Dalcin rpath = rpath.split(os.path.pathsep) 3545ee53db2SLisandro Dalcin if libdir in rpath: 3555ee53db2SLisandro Dalcin rpath.insert(0, '$ORIGIN') 3565ee53db2SLisandro Dalcin while libdir in rpath: 3575ee53db2SLisandro Dalcin rpath.remove(libdir) 3585ee53db2SLisandro Dalcin if rpath: 3595ee53db2SLisandro Dalcin rpath = os.path.pathsep.join(rpath) 3605ee53db2SLisandro Dalcin shell('patchelf', '--set-rpath', "'%s'" % rpath, shlib) 3615ee53db2SLisandro Dalcin # fix shared library file and symlink 3625ee53db2SLisandro Dalcin basename = os.path.basename(shlib) 3635ee53db2SLisandro Dalcin libname, ext, _ = basename.partition('.so') 3645ee53db2SLisandro Dalcin liblink = libname + ext 3655ee53db2SLisandro Dalcin soname = shell('patchelf', '--print-soname', shlib) 3665ee53db2SLisandro Dalcin for symlink in lsdir(self.destLibDir, liblink + '*'): 3675ee53db2SLisandro Dalcin if os.path.islink(symlink): 3685ee53db2SLisandro Dalcin os.unlink(symlink) 3695ee53db2SLisandro Dalcin curdir = os.getcwd() 3705ee53db2SLisandro Dalcin try: 3715ee53db2SLisandro Dalcin os.chdir(os.path.dirname(shlib)) 3725ee53db2SLisandro Dalcin if soname != basename: 3735ee53db2SLisandro Dalcin os.rename(basename, soname) 3745ee53db2SLisandro Dalcin if soname != liblink: 3755ee53db2SLisandro Dalcin os.symlink(soname, liblink) 3765ee53db2SLisandro Dalcin finally: 3775ee53db2SLisandro Dalcin os.chdir(curdir) 3785ee53db2SLisandro Dalcin if sys.platform == 'darwin': 3795ee53db2SLisandro Dalcin def otool(cmd, dylib): 3805ee53db2SLisandro Dalcin pattern = r''' 3815ee53db2SLisandro Dalcin ^\s+ cmd \s %s$\n 3825ee53db2SLisandro Dalcin ^\s+ cmdsize \s \d+$\n 3835ee53db2SLisandro Dalcin ^\s+ (?:name|path) \s (.*) \s \(offset \s \d+\)$ 3845ee53db2SLisandro Dalcin ''' % cmd 3855ee53db2SLisandro Dalcin return re.findall( 3865ee53db2SLisandro Dalcin pattern, shell('otool', '-l', dylib), 3875ee53db2SLisandro Dalcin flags=re.VERBOSE | re.MULTILINE, 3885ee53db2SLisandro Dalcin ) 3895ee53db2SLisandro Dalcin libraries = [ 3905ee53db2SLisandro Dalcin lib for lib in lsdir(self.destLibDir, 'lib*.dylib') 3915ee53db2SLisandro Dalcin if not os.path.islink(lib) 3925ee53db2SLisandro Dalcin ] 3935ee53db2SLisandro Dalcin for dylib in libraries: 3945ee53db2SLisandro Dalcin install_name = otool('LC_ID_DYLIB', dylib)[0] 3955ee53db2SLisandro Dalcin dependencies = otool('LC_LOAD_DYLIB', dylib) 3965ee53db2SLisandro Dalcin runtime_path = otool('LC_RPATH', dylib) 3975ee53db2SLisandro Dalcin # fix shared library install name and rpath 3985ee53db2SLisandro Dalcin install_name = '@rpath/' + os.path.basename(install_name) 3995ee53db2SLisandro Dalcin shell('install_name_tool', '-id', install_name, dylib) 4005ee53db2SLisandro Dalcin if libdir in runtime_path: 4015ee53db2SLisandro Dalcin shell('install_name_tool', '-delete_rpath', libdir, dylib) 4025ee53db2SLisandro Dalcin for rpath in ('@loader_path',): 4035ee53db2SLisandro Dalcin if rpath not in runtime_path: 4045ee53db2SLisandro Dalcin shell('install_name_tool', '-add_rpath', rpath, dylib) 4055ee53db2SLisandro Dalcin for dep in dependencies: 4065ee53db2SLisandro Dalcin if os.path.dirname(dep) in (libdir,): 4075ee53db2SLisandro Dalcin newid = '@rpath/' + os.path.basename(dep) 4085ee53db2SLisandro Dalcin shell('install_name_tool', '-change', dep, newid, dylib) 4095ee53db2SLisandro Dalcin # fix shared library file and symlink 4105ee53db2SLisandro Dalcin basename = os.path.basename(dylib) 4115ee53db2SLisandro Dalcin libname, ext = os.path.splitext(basename) 4125ee53db2SLisandro Dalcin libname = libname.partition('.')[0] 4135ee53db2SLisandro Dalcin liblink = libname + ext 4145ee53db2SLisandro Dalcin dyname = os.path.basename(install_name) 4155ee53db2SLisandro Dalcin for symlink in lsdir(self.destLibDir, libname + '*' + ext): 4165ee53db2SLisandro Dalcin if os.path.islink(symlink): 4175ee53db2SLisandro Dalcin os.unlink(symlink) 4185ee53db2SLisandro Dalcin curdir = os.getcwd() 4195ee53db2SLisandro Dalcin try: 4205ee53db2SLisandro Dalcin os.chdir(os.path.dirname(dylib)) 4215ee53db2SLisandro Dalcin if dyname != basename: 4225ee53db2SLisandro Dalcin os.rename(basename, dyname) 4235ee53db2SLisandro Dalcin if dyname != liblink: 4245ee53db2SLisandro Dalcin os.symlink(dyname, liblink) 4255ee53db2SLisandro Dalcin finally: 4265ee53db2SLisandro Dalcin os.chdir(curdir) 4275ee53db2SLisandro Dalcin # 4285ee53db2SLisandro Dalcin return 4295ee53db2SLisandro Dalcin 4300ee81e68SLisandro Dalcin def createUninstaller(self): 4310ee81e68SLisandro Dalcin uninstallscript = os.path.join(self.destConfDir, 'uninstall.py') 4320ee81e68SLisandro Dalcin f = open(uninstallscript, 'w') 4330ee81e68SLisandro Dalcin # Could use the Python AST to do this 4340ee81e68SLisandro Dalcin f.write('#!'+sys.executable+'\n') 4350ee81e68SLisandro Dalcin f.write('import os\n') 436d97f9ea1SSatish Balay f.write('prefixdir = "'+self.installDir+'"\n') 437d97f9ea1SSatish Balay files = [dst.replace(self.destDir,self.installDir) for src, dst in self.copies] 438d97f9ea1SSatish Balay files.append(uninstallscript.replace(self.destDir,self.installDir)) 439d97f9ea1SSatish Balay f.write('files = '+repr(files)) 4400ee81e68SLisandro Dalcin f.write(''' 441d97f9ea1SSatish Balayfor file in files: 442d97f9ea1SSatish Balay if os.path.exists(file) or os.path.islink(file): 443d97f9ea1SSatish Balay os.remove(file) 444d97f9ea1SSatish Balay dir = os.path.dirname(file) 4452b39596bSSatish Balay while dir not in [os.path.dirname(prefixdir),'/']: 4462b39596bSSatish Balay try: os.rmdir(dir) 4472b39596bSSatish Balay except: break 448d97f9ea1SSatish Balay dir = os.path.dirname(dir) 4490ee81e68SLisandro Dalcin''') 4500ee81e68SLisandro Dalcin f.close() 4515b6bfdb9SJed Brown os.chmod(uninstallscript,0o744) 4520ee81e68SLisandro Dalcin return 4530ee81e68SLisandro Dalcin 4540ee81e68SLisandro Dalcin def installIncludes(self): 45532cabb2fSBarry Smith exclude = ['makefile'] 45632cabb2fSBarry Smith if not hasattr(self.compilers.setCompilers, 'FC'): 45732cabb2fSBarry Smith exclude.append('finclude') 45832cabb2fSBarry Smith if not self.mpi.usingMPIUni: 45932cabb2fSBarry Smith exclude.append('mpiuni') 46032cabb2fSBarry Smith self.copies.extend(self.copytree(self.rootIncludeDir, self.destIncludeDir,exclude = exclude)) 4610ee81e68SLisandro Dalcin self.copies.extend(self.copytree(self.archIncludeDir, self.destIncludeDir)) 4620ee81e68SLisandro Dalcin return 4630ee81e68SLisandro Dalcin 4640ee81e68SLisandro Dalcin def installConf(self): 46532cabb2fSBarry Smith self.copies.extend(self.copytree(self.rootConfDir, self.destConfDir, exclude = ['uncrustify.cfg','bfort-base.txt','bfort-petsc.txt','bfort-mpi.txt','test.log'])) 466a035e9faSPierre 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'])) 4670ee81e68SLisandro Dalcin return 4680ee81e68SLisandro Dalcin 4690ee81e68SLisandro Dalcin def installBin(self): 47032cabb2fSBarry Smith exclude = ['bfort','bib2html','doc2lt','doctext','mapnames', 'pstogif','pstoxbm','tohtml'] 47132cabb2fSBarry Smith self.copies.extend(self.copytree(self.archBinDir, self.destBinDir, exclude = exclude )) 47232cabb2fSBarry Smith exclude = ['maint'] 47332cabb2fSBarry Smith if not self.mpi.usingMPIUni: 47432cabb2fSBarry Smith exclude.append('petsc-mpiexec.uni') 47532cabb2fSBarry Smith self.setCompilers.pushLanguage('C') 476011f288aSSatish Balay if self.setCompilers.getCompiler().find('win32fe') < 0: 47732cabb2fSBarry Smith exclude.append('win32fe') 47832cabb2fSBarry Smith self.setCompilers.popLanguage() 47932cabb2fSBarry Smith self.copies.extend(self.copytree(self.rootBinDir, self.destBinDir, exclude = exclude )) 4800ee81e68SLisandro Dalcin return 4810ee81e68SLisandro Dalcin 4820ee81e68SLisandro Dalcin def installShare(self): 4830ee81e68SLisandro Dalcin self.copies.extend(self.copytree(self.rootShareDir, self.destShareDir)) 484c173c275SScott Kruger examplesdir=os.path.join(self.destShareDir,'petsc','examples') 485c173c275SScott Kruger if os.path.exists(examplesdir): 486c173c275SScott Kruger shutil.rmtree(examplesdir) 487c173c275SScott Kruger os.mkdir(examplesdir) 48879eaf171SScott Kruger os.mkdir(os.path.join(examplesdir,'src')) 489c173c275SScott Kruger self.copyConfig(self.rootDir,examplesdir) 490fad83eadSPatrick Sanan if not self.argDB['no-examples']: 491fad83eadSPatrick Sanan self.copyExamples(self.rootSrcDir,os.path.join(examplesdir,'src')) 492c173c275SScott Kruger self.fixExamplesMakefile(os.path.join(examplesdir,'gmakefile.test')) 4930ee81e68SLisandro Dalcin return 4940ee81e68SLisandro Dalcin 4950ee81e68SLisandro Dalcin def copyLib(self, src, dst): 4960ee81e68SLisandro Dalcin '''Run ranlib on the destination library if it is an archive. Also run install_name_tool on dylib on Mac''' 4970ee81e68SLisandro Dalcin # Symlinks (assumed local) are recreated at dst 4980ee81e68SLisandro Dalcin if os.path.islink(src): 4990ee81e68SLisandro Dalcin linkto = os.readlink(src) 5000ee81e68SLisandro Dalcin try: 5010ee81e68SLisandro Dalcin os.remove(dst) # In case it already exists 5020ee81e68SLisandro Dalcin except OSError: 5030ee81e68SLisandro Dalcin pass 5040ee81e68SLisandro Dalcin os.symlink(linkto, dst) 5050ee81e68SLisandro Dalcin return 5060ee81e68SLisandro Dalcin shutil.copy2(src, dst) 507011f288aSSatish Balay if self.setCompilers.getCompiler().find('win32fe') < 0 and os.path.splitext(dst)[1] == '.'+self.arLibSuffix: 5080ee81e68SLisandro Dalcin self.executeShellCommand(self.ranlib+' '+dst) 5090ee81e68SLisandro Dalcin if os.path.splitext(dst)[1] == '.dylib' and os.path.isfile('/usr/bin/install_name_tool'): 510af2c601bSBarry Smith [output,err,flg] = self.executeShellCommand("otool -D "+src) 511af2c601bSBarry Smith oldname = output[output.find("\n")+1:] 512d4c3e6c5SSatish Balay installName = oldname.replace(os.path.realpath(self.archDir), self.installDir) 5130ee81e68SLisandro Dalcin self.executeShellCommand('/usr/bin/install_name_tool -id ' + installName + ' ' + dst) 5140ee81e68SLisandro Dalcin # preserve the original timestamps - so that the .a vs .so time order is preserved 5150ee81e68SLisandro Dalcin shutil.copystat(src,dst) 5160ee81e68SLisandro Dalcin return 5170ee81e68SLisandro Dalcin 5180ee81e68SLisandro Dalcin def installLib(self): 51932cabb2fSBarry Smith self.copies.extend(self.copytree(self.archLibDir, self.destLibDir, copyFunc = self.copyLib, exclude = ['.DIR'],recurse = 0)) 52032cabb2fSBarry 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)) 5210ee81e68SLisandro Dalcin return 5220ee81e68SLisandro Dalcin 5230ee81e68SLisandro Dalcin 5240ee81e68SLisandro Dalcin def outputInstallDone(self): 5255b4fc442SVaclav Hapla from config.packages.make import getMakeUserPath 5265b6bfdb9SJed Brown print('''\ 5270ee81e68SLisandro Dalcin==================================== 5280ee81e68SLisandro DalcinInstall complete. 5290ee81e68SLisandro DalcinNow to check if the libraries are working do (in current directory): 5305b4fc442SVaclav Hapla%s PETSC_DIR=%s PETSC_ARCH="" check 5310ee81e68SLisandro Dalcin====================================\ 5325b4fc442SVaclav Hapla''' % (getMakeUserPath(self.arch), self.installDir)) 5330ee81e68SLisandro Dalcin return 5340ee81e68SLisandro Dalcin 5350ee81e68SLisandro Dalcin def outputDestDirDone(self): 5365b6bfdb9SJed Brown print('''\ 5370ee81e68SLisandro Dalcin==================================== 5380ee81e68SLisandro DalcinCopy to DESTDIR %s is now complete. 5390ee81e68SLisandro DalcinBefore use - please copy/install over to specified prefix: %s 5400ee81e68SLisandro Dalcin====================================\ 5415b6bfdb9SJed Brown''' % (self.destDir,self.installDir)) 5420ee81e68SLisandro Dalcin return 5430ee81e68SLisandro Dalcin 5440ee81e68SLisandro Dalcin def runsetup(self): 5450ee81e68SLisandro Dalcin self.setup() 5460ee81e68SLisandro Dalcin self.setupDirectories() 5470ee81e68SLisandro Dalcin self.checkPrefix() 5480ee81e68SLisandro Dalcin self.checkDestdir() 5490ee81e68SLisandro Dalcin return 5500ee81e68SLisandro Dalcin 5510ee81e68SLisandro Dalcin def runcopy(self): 5520ee81e68SLisandro Dalcin if self.destDir == self.installDir: 5535b6bfdb9SJed Brown print('*** Installing PETSc at prefix location:',self.destDir, ' ***') 5540ee81e68SLisandro Dalcin else: 5555b6bfdb9SJed Brown print('*** Copying PETSc to DESTDIR location:',self.destDir, ' ***') 5560ee81e68SLisandro Dalcin if not os.path.exists(self.destDir): 5570ee81e68SLisandro Dalcin try: 5580ee81e68SLisandro Dalcin os.makedirs(self.destDir) 5590ee81e68SLisandro Dalcin except: 5605b6bfdb9SJed Brown print('********************************************************************') 5615b6bfdb9SJed Brown print('Unable to create', self.destDir, 'Perhaps you need to do "sudo make install"') 5625b6bfdb9SJed Brown print('********************************************************************') 5630ee81e68SLisandro Dalcin sys.exit(1) 5640ee81e68SLisandro Dalcin self.installIncludes() 5650ee81e68SLisandro Dalcin self.installConf() 5660ee81e68SLisandro Dalcin self.installBin() 5670ee81e68SLisandro Dalcin self.installLib() 5680ee81e68SLisandro Dalcin self.installShare() 5695ee53db2SLisandro Dalcin self.createUninstaller() 5700ee81e68SLisandro Dalcin return 5710ee81e68SLisandro Dalcin 5720ee81e68SLisandro Dalcin def runfix(self): 5730ee81e68SLisandro Dalcin self.fixConf() 574*1eeab4b4SLisandro Dalcin using_build_backend = any( 575*1eeab4b4SLisandro Dalcin os.environ.get(prefix + '_BUILD_BACKEND') 576*1eeab4b4SLisandro Dalcin for prefix in ('_PYPROJECT_HOOKS', 'PEP517') 577*1eeab4b4SLisandro Dalcin ) 578*1eeab4b4SLisandro Dalcin if using_build_backend: 5795ee53db2SLisandro Dalcin self.fixPythonWheel() 5800ee81e68SLisandro Dalcin return 5810ee81e68SLisandro Dalcin 5820ee81e68SLisandro Dalcin def rundone(self): 5830ee81e68SLisandro Dalcin if self.destDir == self.installDir: 5840ee81e68SLisandro Dalcin self.outputInstallDone() 5850ee81e68SLisandro Dalcin else: 5860ee81e68SLisandro Dalcin self.outputDestDirDone() 5870ee81e68SLisandro Dalcin return 5880ee81e68SLisandro Dalcin 5890ee81e68SLisandro Dalcin def run(self): 5900ee81e68SLisandro Dalcin self.runsetup() 5910ee81e68SLisandro Dalcin self.runcopy() 5920ee81e68SLisandro Dalcin self.runfix() 5930ee81e68SLisandro Dalcin self.rundone() 5940ee81e68SLisandro Dalcin return 5950ee81e68SLisandro Dalcin 5960ee81e68SLisandro Dalcinif __name__ == '__main__': 5970ee81e68SLisandro Dalcin Installer(sys.argv[1:]).run() 5980ee81e68SLisandro Dalcin # temporary hack - delete log files created by BuildSystem - when 'sudo make install' is invoked 59903e6d329SSatish Balay delfiles=['RDict.db','RDict.log','buildsystem.log','default.log','buildsystem.log.bkp','default.log.bkp'] 6000ee81e68SLisandro Dalcin for delfile in delfiles: 6010ee81e68SLisandro Dalcin if os.path.exists(delfile) and (os.stat(delfile).st_uid==0): 6020ee81e68SLisandro Dalcin os.remove(delfile) 603