1df3bd252SSatish Balay#!/usr/bin/env python3 25b6bfdb9SJed Brownfrom __future__ import print_function 3e551db17SScott Krugerimport os, re, shutil, sys 4*6e8294f6SStefano Zampiniimport sysconfig 50ee81e68SLisandro Dalcin 65b6bfdb9SJed Brownif 'PETSC_DIR' in os.environ: 70ee81e68SLisandro Dalcin PETSC_DIR = os.environ['PETSC_DIR'] 80ee81e68SLisandro Dalcinelse: 9c6ef1b5bSJed Brown fd = open(os.path.join('lib','petsc','conf','petscvariables')) 100ee81e68SLisandro Dalcin a = fd.readline() 110ee81e68SLisandro Dalcin a = fd.readline() 120ee81e68SLisandro Dalcin PETSC_DIR = a.split('=')[1][0:-1] 130ee81e68SLisandro Dalcin fd.close() 140ee81e68SLisandro Dalcin 155b6bfdb9SJed Brownif 'PETSC_ARCH' in os.environ: 160ee81e68SLisandro Dalcin PETSC_ARCH = os.environ['PETSC_ARCH'] 170ee81e68SLisandro Dalcinelse: 18c6ef1b5bSJed Brown fd = open(os.path.join('lib','petsc','conf','petscvariables')) 190ee81e68SLisandro Dalcin a = fd.readline() 200ee81e68SLisandro Dalcin PETSC_ARCH = a.split('=')[1][0:-1] 210ee81e68SLisandro Dalcin fd.close() 220ee81e68SLisandro Dalcin 235b6bfdb9SJed Brownprint('*** Using PETSC_DIR='+PETSC_DIR+' PETSC_ARCH='+PETSC_ARCH+' ***') 240ee81e68SLisandro Dalcinsys.path.insert(0, os.path.join(PETSC_DIR, 'config')) 250ee81e68SLisandro Dalcinsys.path.insert(0, os.path.join(PETSC_DIR, 'config', 'BuildSystem')) 260ee81e68SLisandro Dalcin 270ee81e68SLisandro Dalcinimport script 280ee81e68SLisandro Dalcin 290ee81e68SLisandro Dalcintry: 300ee81e68SLisandro Dalcin WindowsError 310ee81e68SLisandro Dalcinexcept NameError: 320ee81e68SLisandro Dalcin WindowsError = None 330ee81e68SLisandro Dalcin 340ee81e68SLisandro Dalcinclass Installer(script.Script): 350ee81e68SLisandro Dalcin def __init__(self, clArgs = None): 360ee81e68SLisandro Dalcin import RDict 370ee81e68SLisandro Dalcin argDB = RDict.RDict(None, None, 0, 0, readonly = True) 38af0996ceSBarry Smith argDB.saveFilename = os.path.join(PETSC_DIR, PETSC_ARCH, 'lib','petsc','conf', 'RDict.db') 390ee81e68SLisandro Dalcin argDB.load() 400ee81e68SLisandro Dalcin script.Script.__init__(self, argDB = argDB) 410ee81e68SLisandro Dalcin if not clArgs is None: self.clArgs = clArgs 420ee81e68SLisandro Dalcin self.copies = [] 430ee81e68SLisandro Dalcin return 440ee81e68SLisandro Dalcin 450ee81e68SLisandro Dalcin def setupHelp(self, help): 460ee81e68SLisandro Dalcin import nargs 470ee81e68SLisandro Dalcin script.Script.setupHelp(self, help) 48a26d7103SSatish Balay help.addArgument('Installer', '-destDir=<path>', nargs.Arg(None, '', 'Destination Directory for install')) 49fad83eadSPatrick Sanan help.addArgument('Installer', '-no-examples', nargs.Arg(None, '', 'Skip installing examples')) 500ee81e68SLisandro Dalcin return 510ee81e68SLisandro Dalcin 520ee81e68SLisandro Dalcin 530ee81e68SLisandro Dalcin def setupModules(self): 540ee81e68SLisandro Dalcin self.setCompilers = self.framework.require('config.setCompilers', None) 550ee81e68SLisandro Dalcin self.arch = self.framework.require('PETSc.options.arch', None) 560ee81e68SLisandro Dalcin self.petscdir = self.framework.require('PETSc.options.petscdir', None) 570ee81e68SLisandro Dalcin self.compilers = self.framework.require('config.compilers', None) 5832cabb2fSBarry Smith self.mpi = self.framework.require('config.packages.MPI', None) 590ee81e68SLisandro Dalcin return 600ee81e68SLisandro Dalcin 610ee81e68SLisandro Dalcin def setup(self): 620ee81e68SLisandro Dalcin script.Script.setup(self) 630ee81e68SLisandro Dalcin self.framework = self.loadConfigure() 640ee81e68SLisandro Dalcin self.setupModules() 650ee81e68SLisandro Dalcin return 660ee81e68SLisandro Dalcin 670ee81e68SLisandro Dalcin def setupDirectories(self): 680ee81e68SLisandro Dalcin self.rootDir = self.petscdir.dir 694a08bad0SBarry Smith self.installDir = os.path.abspath(os.path.expanduser(self.framework.argDB['prefix'])) 708727f567SSatish Balay self.destDir = os.path.abspath(self.argDB['destDir']+self.installDir) 710ee81e68SLisandro Dalcin self.arch = self.arch.arch 7202e047dfSSatish Balay self.archDir = os.path.join(self.rootDir, self.arch) 730ee81e68SLisandro Dalcin self.rootIncludeDir = os.path.join(self.rootDir, 'include') 740ee81e68SLisandro Dalcin self.archIncludeDir = os.path.join(self.rootDir, self.arch, 'include') 75af0996ceSBarry Smith self.rootConfDir = os.path.join(self.rootDir, 'lib','petsc','conf') 76af0996ceSBarry Smith self.archConfDir = os.path.join(self.rootDir, self.arch, 'lib','petsc','conf') 77c3a89c15SBarry Smith self.rootBinDir = os.path.join(self.rootDir, 'lib','petsc','bin') 780ee81e68SLisandro Dalcin self.archBinDir = os.path.join(self.rootDir, self.arch, 'bin') 790ee81e68SLisandro Dalcin self.archLibDir = os.path.join(self.rootDir, self.arch, 'lib') 800ee81e68SLisandro Dalcin self.destIncludeDir = os.path.join(self.destDir, 'include') 81af0996ceSBarry Smith self.destConfDir = os.path.join(self.destDir, 'lib','petsc','conf') 820ee81e68SLisandro Dalcin self.destLibDir = os.path.join(self.destDir, 'lib') 83c3a89c15SBarry Smith self.destBinDir = os.path.join(self.destDir, 'lib','petsc','bin') 840ee81e68SLisandro Dalcin self.installIncludeDir = os.path.join(self.installDir, 'include') 852d10696aSSatish Balay self.installLibDir = os.path.join(self.installDir, 'lib') 86c3a89c15SBarry Smith self.installBinDir = os.path.join(self.installDir, 'lib','petsc','bin') 870ee81e68SLisandro Dalcin self.rootShareDir = os.path.join(self.rootDir, 'share') 880ee81e68SLisandro Dalcin self.destShareDir = os.path.join(self.destDir, 'share') 8979eaf171SScott Kruger self.rootSrcDir = os.path.join(self.rootDir, 'src') 900ee81e68SLisandro Dalcin 910ee81e68SLisandro Dalcin self.ranlib = self.compilers.RANLIB 920ee81e68SLisandro Dalcin self.arLibSuffix = self.compilers.AR_LIB_SUFFIX 930ee81e68SLisandro Dalcin return 940ee81e68SLisandro Dalcin 950ee81e68SLisandro Dalcin def checkPrefix(self): 960ee81e68SLisandro Dalcin if not self.installDir: 975b6bfdb9SJed Brown print('********************************************************************') 985b6bfdb9SJed Brown print('PETSc is built without prefix option. So "make install" is not appropriate.') 995b6bfdb9SJed Brown print('If you need a prefix install of PETSc - rerun configure with --prefix option.') 1005b6bfdb9SJed Brown print('********************************************************************') 1010ee81e68SLisandro Dalcin sys.exit(1) 1020ee81e68SLisandro Dalcin return 1030ee81e68SLisandro Dalcin 1040ee81e68SLisandro Dalcin def checkDestdir(self): 1050ee81e68SLisandro Dalcin if os.path.exists(self.destDir): 1060ee81e68SLisandro Dalcin if os.path.samefile(self.destDir, self.rootDir): 1075b6bfdb9SJed Brown print('********************************************************************') 1085b6bfdb9SJed Brown print('Incorrect prefix usage. Specified destDir same as current PETSC_DIR') 1095b6bfdb9SJed Brown print('********************************************************************') 1100ee81e68SLisandro Dalcin sys.exit(1) 1110ee81e68SLisandro Dalcin if os.path.samefile(self.destDir, os.path.join(self.rootDir,self.arch)): 1125b6bfdb9SJed Brown print('********************************************************************') 1135b6bfdb9SJed Brown print('Incorrect prefix usage. Specified destDir same as current PETSC_DIR/PETSC_ARCH') 1145b6bfdb9SJed Brown print('********************************************************************') 1150ee81e68SLisandro Dalcin sys.exit(1) 1160ee81e68SLisandro Dalcin if not os.path.isdir(os.path.realpath(self.destDir)): 1175b6bfdb9SJed Brown print('********************************************************************') 1185b6bfdb9SJed Brown print('Specified destDir', self.destDir, 'is not a directory. Cannot proceed!') 1195b6bfdb9SJed Brown print('********************************************************************') 1200ee81e68SLisandro Dalcin sys.exit(1) 1210ee81e68SLisandro Dalcin if not os.access(self.destDir, os.W_OK): 1225b6bfdb9SJed Brown print('********************************************************************') 1235b6bfdb9SJed Brown print('Unable to write to ', self.destDir, 'Perhaps you need to do "sudo make install"') 1245b6bfdb9SJed Brown print('********************************************************************') 1250ee81e68SLisandro Dalcin sys.exit(1) 1260ee81e68SLisandro Dalcin return 1270ee81e68SLisandro Dalcin 128*6e8294f6SStefano Zampini def setupBuild(self): 129*6e8294f6SStefano Zampini self.using_build_backend = any( 130*6e8294f6SStefano Zampini os.environ.get(prefix + '_BUILD_BACKEND') 131*6e8294f6SStefano Zampini for prefix in ('_PYPROJECT_HOOKS', 'PEP517') 132*6e8294f6SStefano Zampini ) 133*6e8294f6SStefano Zampini self.relocate_py_env = os.environ.get('CIBUILDWHEEL', '0') == '1' 134*6e8294f6SStefano Zampini 1350ee81e68SLisandro Dalcin def copyfile(self, src, dst, symlinks = False, copyFunc = shutil.copy2): 1360ee81e68SLisandro Dalcin """Copies a single file """ 1370ee81e68SLisandro Dalcin copies = [] 1380ee81e68SLisandro Dalcin errors = [] 1390ee81e68SLisandro Dalcin if not os.path.exists(dst): 1400ee81e68SLisandro Dalcin os.makedirs(dst) 1410ee81e68SLisandro Dalcin elif not os.path.isdir(dst): 1425b6bfdb9SJed Brown raise shutil.Error('Destination is not a directory') 1430ee81e68SLisandro Dalcin srcname = src 1440ee81e68SLisandro Dalcin dstname = os.path.join(dst, os.path.basename(src)) 1450ee81e68SLisandro Dalcin try: 1460ee81e68SLisandro Dalcin if symlinks and os.path.islink(srcname): 1470ee81e68SLisandro Dalcin linkto = os.readlink(srcname) 1480ee81e68SLisandro Dalcin os.symlink(linkto, dstname) 1490ee81e68SLisandro Dalcin else: 1500ee81e68SLisandro Dalcin copyFunc(srcname, dstname) 1510ee81e68SLisandro Dalcin copies.append((srcname, dstname)) 1525b6bfdb9SJed Brown except (IOError, os.error) as why: 1530ee81e68SLisandro Dalcin errors.append((srcname, dstname, str(why))) 1545b6bfdb9SJed Brown except shutil.Error as err: 1552c852529SBarry Smith errors.append((srcname,dstname,str(err.args[0]))) 1560ee81e68SLisandro Dalcin if errors: 1575b6bfdb9SJed Brown raise shutil.Error(errors) 1580ee81e68SLisandro Dalcin return copies 1590ee81e68SLisandro Dalcin 16026e8aaceSBarry Smith def fixExamplesMakefile(self, src): 161f0b74427SPierre Jolivet '''Change ././${PETSC_ARCH} in makefile in root PETSc directory with ${PETSC_DIR}''' 16226e8aaceSBarry Smith lines = [] 16326e8aaceSBarry Smith oldFile = open(src, 'r') 164e551db17SScott Kruger alllines=oldFile.read() 16526e8aaceSBarry Smith oldFile.close() 166e551db17SScott Kruger newlines=alllines.split('\n')[0]+'\n' # Firstline 167d5b43468SJose E. Roman # Hardcode PETSC_DIR and PETSC_ARCH to avoid users doing the wrong thing 168e551db17SScott Kruger newlines+='PETSC_DIR='+self.installDir+'\n' 169e551db17SScott Kruger newlines+='PETSC_ARCH=\n' 170e551db17SScott Kruger for line in alllines.split('\n')[1:]: 1714ff3c6a1SScott Kruger if line.startswith('TESTLOGFILE'): 172c173c275SScott Kruger newlines+='TESTLOGFILE = $(TESTDIR)/examples-install.log\n' 173e551db17SScott Kruger elif line.startswith('CONFIGDIR'): 174e551db17SScott Kruger newlines+='CONFIGDIR:=$(PETSC_DIR)/$(PETSC_ARCH)/share/petsc/examples/config\n' 175fc46264cSScott Kruger elif line.startswith('$(generatedtest)') and 'petscvariables' in line: 176c173c275SScott Kruger newlines+='all: test\n\n'+line+'\n' 177e551db17SScott Kruger else: 1784ff3c6a1SScott Kruger newlines+=line+'\n' 17926e8aaceSBarry Smith newFile = open(src, 'w') 180e551db17SScott Kruger newFile.write(newlines) 18126e8aaceSBarry Smith newFile.close() 18226e8aaceSBarry Smith return 18326e8aaceSBarry Smith 184e551db17SScott Kruger def copyConfig(self, src, dst): 1852f21b5d8SJed Brown """Copy configuration/testing files 186e551db17SScott Kruger """ 187e551db17SScott Kruger if not os.path.isdir(dst): 1885b6bfdb9SJed Brown raise shutil.Error('Destination is not a directory') 189e551db17SScott Kruger 190adf35c6eSSatish Balay self.copies.extend(self.copyfile('gmakefile.test',dst)) 191e551db17SScott Kruger newConfigDir=os.path.join(dst,'config') # Am not renaming at present 192e551db17SScott Kruger if not os.path.isdir(newConfigDir): os.mkdir(newConfigDir) 193e551db17SScott Kruger testConfFiles="gmakegentest.py gmakegen.py testparse.py example_template.py".split() 19458780e5dSStefano Zampini testConfFiles+="petsc_harness.sh report_tests.py query_tests.py".split() 195e551db17SScott Kruger for tf in testConfFiles: 196adf35c6eSSatish Balay self.copies.extend(self.copyfile(os.path.join('config',tf),newConfigDir)) 197e551db17SScott Kruger return 198e551db17SScott Kruger 19926e8aaceSBarry Smith def copyExamples(self, src, dst): 2004ff3c6a1SScott Kruger """copy the examples directories 20126e8aaceSBarry Smith """ 202ad246c4dSSatish Balay for root, dirs, files in os.walk(src, topdown=False): 2032f21b5d8SJed Brown if os.path.basename(root) not in ("tests", "tutorials"): continue 204ad246c4dSSatish Balay self.copies.extend(self.copytree(root, root.replace(src,dst))) 2054ff3c6a1SScott Kruger return 2060ee81e68SLisandro Dalcin 2070080bb28SSatish Balay def copytree(self, src, dst, symlinks = False, copyFunc = shutil.copy2, exclude = [], exclude_ext= ['.DSYM','.o','.pyc'], recurse = 1): 2080ee81e68SLisandro Dalcin """Recursively copy a directory tree using copyFunc, which defaults to shutil.copy2(). 2090ee81e68SLisandro Dalcin 2100ee81e68SLisandro Dalcin The copyFunc() you provide is only used on the top level, lower levels always use shutil.copy2 2110ee81e68SLisandro Dalcin 2120ee81e68SLisandro Dalcin The destination directory must not already exist. 2130ee81e68SLisandro Dalcin If exception(s) occur, an shutil.Error is raised with a list of reasons. 2140ee81e68SLisandro Dalcin 2150ee81e68SLisandro Dalcin If the optional symlinks flag is true, symbolic links in the 2160ee81e68SLisandro Dalcin source tree result in symbolic links in the destination tree; if 2170ee81e68SLisandro Dalcin it is false, the contents of the files pointed to by symbolic 2180ee81e68SLisandro Dalcin links are copied. 2190ee81e68SLisandro Dalcin """ 2200ee81e68SLisandro Dalcin copies = [] 2210ee81e68SLisandro Dalcin names = os.listdir(src) 2220ee81e68SLisandro Dalcin if not os.path.exists(dst): 2230ee81e68SLisandro Dalcin os.makedirs(dst) 2240ee81e68SLisandro Dalcin elif not os.path.isdir(dst): 2255b6bfdb9SJed Brown raise shutil.Error('Destination is not a directory') 2260ee81e68SLisandro Dalcin errors = [] 2272c72da00SPierre Jolivet srclinks = [] 2282c72da00SPierre Jolivet dstlinks = [] 2290ee81e68SLisandro Dalcin for name in names: 2300ee81e68SLisandro Dalcin srcname = os.path.join(src, name) 2310ee81e68SLisandro Dalcin dstname = os.path.join(dst, name) 2320ee81e68SLisandro Dalcin try: 2330ee81e68SLisandro Dalcin if symlinks and os.path.islink(srcname): 2340ee81e68SLisandro Dalcin linkto = os.readlink(srcname) 2350ee81e68SLisandro Dalcin os.symlink(linkto, dstname) 23632cabb2fSBarry Smith elif os.path.isdir(srcname) and recurse and not os.path.basename(srcname) in exclude: 237adf35c6eSSatish Balay copies.extend(self.copytree(srcname, dstname, symlinks,exclude = exclude, exclude_ext = exclude_ext)) 238adf35c6eSSatish Balay elif os.path.isfile(srcname) and not os.path.basename(srcname) in exclude and os.path.splitext(name)[1] not in exclude_ext : 2392c72da00SPierre Jolivet if os.path.islink(srcname): 2402c72da00SPierre Jolivet srclinks.append(srcname) 2412c72da00SPierre Jolivet dstlinks.append(dstname) 2422c72da00SPierre Jolivet else: 2430ee81e68SLisandro Dalcin copyFunc(srcname, dstname) 2440ee81e68SLisandro Dalcin copies.append((srcname, dstname)) 2450ee81e68SLisandro Dalcin # XXX What about devices, sockets etc.? 2465b6bfdb9SJed Brown except (IOError, os.error) as why: 2470ee81e68SLisandro Dalcin errors.append((srcname, dstname, str(why))) 2480ee81e68SLisandro Dalcin # catch the Error from the recursive copytree so that we can 2490ee81e68SLisandro Dalcin # continue with other files 2505b6bfdb9SJed Brown except shutil.Error as err: 2512c852529SBarry Smith errors.append((srcname,dstname,str(err.args[0]))) 2522c72da00SPierre Jolivet for srcname, dstname in zip(srclinks, dstlinks): 2532c72da00SPierre Jolivet try: 2542c72da00SPierre Jolivet copyFunc(srcname, dstname) 2552c72da00SPierre Jolivet copies.append((srcname, dstname)) 2562c72da00SPierre Jolivet except (IOError, os.error) as why: 2572c72da00SPierre Jolivet errors.append((srcname, dstname, str(why))) 2582c72da00SPierre Jolivet # catch the Error from the recursive copytree so that we can 2592c72da00SPierre Jolivet # continue with other files 2602c72da00SPierre Jolivet except shutil.Error as err: 2612c852529SBarry Smith errors.append((srcname,dstname,str(err.args[0]))) 2620ee81e68SLisandro Dalcin try: 2630ee81e68SLisandro Dalcin shutil.copystat(src, dst) 2645b6bfdb9SJed Brown except OSError as e: 2650ee81e68SLisandro Dalcin if WindowsError is not None and isinstance(e, WindowsError): 2660ee81e68SLisandro Dalcin # Copying file access times may fail on Windows 2670ee81e68SLisandro Dalcin pass 2680ee81e68SLisandro Dalcin else: 2692c852529SBarry Smith errors.append((src, dst, str(e))) 2700ee81e68SLisandro Dalcin if errors: 2715b6bfdb9SJed Brown raise shutil.Error(errors) 2720ee81e68SLisandro Dalcin return copies 2730ee81e68SLisandro Dalcin 2740ee81e68SLisandro Dalcin 2750ee81e68SLisandro Dalcin def fixConfFile(self, src): 2760ee81e68SLisandro Dalcin lines = [] 2770ee81e68SLisandro Dalcin oldFile = open(src, 'r') 2780ee81e68SLisandro Dalcin for line in oldFile.readlines(): 2795a21677cSJed Brown if line.startswith('PETSC_CC_INCLUDES =') or line.startswith('PETSC_FC_INCLUDES ='): 2805a21677cSJed Brown continue 2815a21677cSJed Brown line = line.replace('PETSC_CC_INCLUDES_INSTALL', 'PETSC_CC_INCLUDES') 2825a21677cSJed Brown line = line.replace('PETSC_FC_INCLUDES_INSTALL', 'PETSC_FC_INCLUDES') 2830ee81e68SLisandro Dalcin # remove PETSC_DIR/PETSC_ARCH variables from conf-makefiles. They are no longer necessary 2840ee81e68SLisandro Dalcin line = line.replace('${PETSC_DIR}/${PETSC_ARCH}', self.installDir) 2850ee81e68SLisandro Dalcin line = line.replace('PETSC_ARCH=${PETSC_ARCH}', '') 2860ee81e68SLisandro Dalcin line = line.replace('${PETSC_DIR}', self.installDir) 2872d10696aSSatish Balay # replace PETSC_DIR/PETSC_ARCH/lib (i.e., build location) with prefix/lib 2882d10696aSSatish Balay line = line.replace(self.archLibDir,self.installLibDir) 289011f288aSSatish Balay # replace PETSC_DIR/lib/petsc/bin with prefix/lib/petsc/bin 290011f288aSSatish Balay line = line.replace(self.rootBinDir,self.destBinDir) 2910ee81e68SLisandro Dalcin lines.append(line) 2920ee81e68SLisandro Dalcin oldFile.close() 2930ee81e68SLisandro Dalcin newFile = open(src, 'w') 2940ee81e68SLisandro Dalcin newFile.write(''.join(lines)) 2950ee81e68SLisandro Dalcin newFile.close() 2960ee81e68SLisandro Dalcin return 2970ee81e68SLisandro Dalcin 2980ee81e68SLisandro Dalcin def fixConf(self): 2990ee81e68SLisandro Dalcin import shutil 300cb5db241SBarry Smith for file in ['rules', 'rules_doc.mk', 'rules_util.mk', 'variables', 'petscrules', 'petscvariables']: 3010ee81e68SLisandro Dalcin self.fixConfFile(os.path.join(self.destConfDir,file)) 3020ee81e68SLisandro Dalcin return 3030ee81e68SLisandro Dalcin 3045ee53db2SLisandro Dalcin def fixPythonWheel(self): 3055ee53db2SLisandro Dalcin import glob 3065ee53db2SLisandro Dalcin import shutil 3075ee53db2SLisandro Dalcin # 3085ee53db2SLisandro Dalcin for pattern in ( 3095ee53db2SLisandro Dalcin self.destLibDir + '/*.a', 3105ee53db2SLisandro Dalcin self.destLibDir + '/*.la', 3115ee53db2SLisandro Dalcin self.destLibDir + '/pkgconfig', # TODO: keep? 3125ee53db2SLisandro Dalcin self.destConfDir + '/configure-hash', 3135ee53db2SLisandro Dalcin self.destConfDir + '/uninstall.py', 3145ee53db2SLisandro Dalcin self.destConfDir + '/reconfigure-*.py', 3155ee53db2SLisandro Dalcin self.destConfDir + '/pkg.conf.*', 3165ee53db2SLisandro Dalcin self.destConfDir + '/pkg.git*.*', 3175ee53db2SLisandro Dalcin self.destConfDir + '/modules', # TODO: keep? 3185ee53db2SLisandro Dalcin self.destShareDir + '/*/examples/src/*', 3195ee53db2SLisandro Dalcin self.destShareDir + '/*/datafiles', 3205ee53db2SLisandro Dalcin ): 3215ee53db2SLisandro Dalcin for pathname in glob.glob(pattern): 3225ee53db2SLisandro Dalcin if os.path.isdir(pathname): 3235ee53db2SLisandro Dalcin shutil.rmtree(pathname) 3245ee53db2SLisandro Dalcin elif os.path.exists(pathname): 3255ee53db2SLisandro Dalcin os.remove(pathname) 3265ee53db2SLisandro Dalcin # 327*6e8294f6SStefano Zampini if self.relocate_py_env: 328*6e8294f6SStefano Zampini pydir = sys.prefix 329*6e8294f6SStefano Zampini pylibdir = os.path.join(pydir, 'lib') 330*6e8294f6SStefano Zampini pysitedir = sysconfig.get_paths()["platlib"] 331*6e8294f6SStefano Zampini # petsc is installed in site-packages 332*6e8294f6SStefano Zampini petscdir = os.path.join(pysitedir, 'petsc') 333*6e8294f6SStefano Zampini petsclibdir = os.path.join(petscdir, 'lib') 3345ee53db2SLisandro Dalcin for filename in ( 3355ee53db2SLisandro Dalcin self.destIncludeDir + '/petscconf.h', 3365ee53db2SLisandro Dalcin self.destIncludeDir + '/petscconfiginfo.h', 3375ee53db2SLisandro Dalcin self.destIncludeDir + '/petscmachineinfo.h', 3385ee53db2SLisandro Dalcin self.destShareDir + '/petsc/examples/gmakefile.test', 3395ee53db2SLisandro Dalcin self.destConfDir + '/rules', 3405ee53db2SLisandro Dalcin self.destConfDir + '/rules_doc.mk', 3415ee53db2SLisandro Dalcin self.destConfDir + '/rules_util.mk', 3425ee53db2SLisandro Dalcin self.destConfDir + '/petscrules', 3435ee53db2SLisandro Dalcin self.destConfDir + '/variables', 3445ee53db2SLisandro Dalcin self.destConfDir + '/petscvariables', 3455ee53db2SLisandro Dalcin ): 3465ee53db2SLisandro Dalcin with open(filename, 'r') as oldFile: 3475ee53db2SLisandro Dalcin contents = oldFile.read() 3485ee53db2SLisandro Dalcin contents = contents.replace(self.installDir, '${PETSC_DIR}') 3495ee53db2SLisandro Dalcin contents = contents.replace(self.rootDir, '${PETSC_DIR}') 350*6e8294f6SStefano Zampini if self.relocate_py_env: 351*6e8294f6SStefano Zampini pydir_from_petsc = os.path.relpath(pydir, petscdir) 352*6e8294f6SStefano Zampini contents = contents.replace(pydir, os.path.join('${PETSC_DIR}', pydir_from_petsc)) 3535ee53db2SLisandro Dalcin contents = re.sub( 3545ee53db2SLisandro Dalcin r'^(PYTHON(_EXE)?) = (.*)$', 3555ee53db2SLisandro Dalcin r'\1 = python%d' % sys.version_info[0], 3565ee53db2SLisandro Dalcin contents, flags=re.MULTILINE, 3575ee53db2SLisandro Dalcin ) 3585ee53db2SLisandro Dalcin with open(filename, 'w') as newFile: 3595ee53db2SLisandro Dalcin newFile.write(contents) 3605ee53db2SLisandro Dalcin # 3615ee53db2SLisandro Dalcin def lsdir(dirname, *patterns): 3625ee53db2SLisandro Dalcin return glob.glob(os.path.join(dirname, *patterns)) 3635ee53db2SLisandro Dalcin def shell(*args): 3645ee53db2SLisandro Dalcin return self.executeShellCommand(' '.join(args))[0] 3655ee53db2SLisandro Dalcin libdir = os.path.join(self.installDir, 'lib') 3665ee53db2SLisandro Dalcin if sys.platform == 'linux': 3675ee53db2SLisandro Dalcin libraries = [ 3685ee53db2SLisandro Dalcin lib for lib in lsdir(self.destLibDir, 'lib*.so*') 3695ee53db2SLisandro Dalcin if not os.path.islink(lib) 3705ee53db2SLisandro Dalcin ] 3715ee53db2SLisandro Dalcin for shlib in libraries: 3725ee53db2SLisandro Dalcin # fix shared library rpath 3735ee53db2SLisandro Dalcin rpath = shell('patchelf', '--print-rpath', shlib) 3745ee53db2SLisandro Dalcin rpath = rpath.split(os.path.pathsep) 375*6e8294f6SStefano Zampini if not self.relocate_py_env: 3765ee53db2SLisandro Dalcin if libdir in rpath: 3775ee53db2SLisandro Dalcin rpath.insert(0, '$ORIGIN') 3785ee53db2SLisandro Dalcin while libdir in rpath: 3795ee53db2SLisandro Dalcin rpath.remove(libdir) 380*6e8294f6SStefano Zampini else: 381*6e8294f6SStefano Zampini rpathold = rpath 382*6e8294f6SStefano Zampini rpath = [] 383*6e8294f6SStefano Zampini # strip all rpath info, except for libraries in Python 384*6e8294f6SStefano Zampini # sys prefix, site-packages, or petsc/lib 385*6e8294f6SStefano Zampini rpath.insert(0, '$ORIGIN') 386*6e8294f6SStefano Zampini for libdir in rpathold: 387*6e8294f6SStefano Zampini if libdir.startswith(pysitedir): 388*6e8294f6SStefano Zampini libdir_from_petsc = os.path.relpath(libdir, petsclibdir) 389*6e8294f6SStefano Zampini rpath.insert(0, os.path.join('$ORIGIN',libdir_from_petsc)) 390*6e8294f6SStefano Zampini pylibdir_from_petsc = os.path.relpath(pylibdir, petsclibdir) 391*6e8294f6SStefano Zampini rpath.insert(0, os.path.join('$ORIGIN',pylibdir_from_petsc)) 3925ee53db2SLisandro Dalcin if rpath: 3935ee53db2SLisandro Dalcin rpath = os.path.pathsep.join(rpath) 3945ee53db2SLisandro Dalcin shell('patchelf', '--set-rpath', "'%s'" % rpath, shlib) 3955ee53db2SLisandro Dalcin # fix shared library file and symlink 3965ee53db2SLisandro Dalcin basename = os.path.basename(shlib) 3975ee53db2SLisandro Dalcin libname, ext, _ = basename.partition('.so') 3985ee53db2SLisandro Dalcin liblink = libname + ext 3995ee53db2SLisandro Dalcin soname = shell('patchelf', '--print-soname', shlib) 4005ee53db2SLisandro Dalcin for symlink in lsdir(self.destLibDir, liblink + '*'): 4015ee53db2SLisandro Dalcin if os.path.islink(symlink): 4025ee53db2SLisandro Dalcin os.unlink(symlink) 4035ee53db2SLisandro Dalcin curdir = os.getcwd() 4045ee53db2SLisandro Dalcin try: 4055ee53db2SLisandro Dalcin os.chdir(os.path.dirname(shlib)) 4065ee53db2SLisandro Dalcin if soname != basename: 4075ee53db2SLisandro Dalcin os.rename(basename, soname) 4085ee53db2SLisandro Dalcin if soname != liblink: 409*6e8294f6SStefano Zampini with open(liblink, 'w') as f: 410*6e8294f6SStefano Zampini f.write('INPUT(' + soname + ')\n') 4115ee53db2SLisandro Dalcin finally: 4125ee53db2SLisandro Dalcin os.chdir(curdir) 4135ee53db2SLisandro Dalcin if sys.platform == 'darwin': 4145ee53db2SLisandro Dalcin def otool(cmd, dylib): 4155ee53db2SLisandro Dalcin pattern = r''' 4165ee53db2SLisandro Dalcin ^\s+ cmd \s %s$\n 4175ee53db2SLisandro Dalcin ^\s+ cmdsize \s \d+$\n 4185ee53db2SLisandro Dalcin ^\s+ (?:name|path) \s (.*) \s \(offset \s \d+\)$ 4195ee53db2SLisandro Dalcin ''' % cmd 4205ee53db2SLisandro Dalcin return re.findall( 4215ee53db2SLisandro Dalcin pattern, shell('otool', '-l', dylib), 4225ee53db2SLisandro Dalcin flags=re.VERBOSE | re.MULTILINE, 4235ee53db2SLisandro Dalcin ) 4245ee53db2SLisandro Dalcin libraries = [ 4255ee53db2SLisandro Dalcin lib for lib in lsdir(self.destLibDir, 'lib*.dylib') 4265ee53db2SLisandro Dalcin if not os.path.islink(lib) 4275ee53db2SLisandro Dalcin ] 4285ee53db2SLisandro Dalcin for dylib in libraries: 4295ee53db2SLisandro Dalcin install_name = otool('LC_ID_DYLIB', dylib)[0] 4305ee53db2SLisandro Dalcin dependencies = otool('LC_LOAD_DYLIB', dylib) 4315ee53db2SLisandro Dalcin runtime_path = otool('LC_RPATH', dylib) 4325ee53db2SLisandro Dalcin # fix shared library install name and rpath 4335ee53db2SLisandro Dalcin install_name = '@rpath/' + os.path.basename(install_name) 4345ee53db2SLisandro Dalcin shell('install_name_tool', '-id', install_name, dylib) 4355ee53db2SLisandro Dalcin if libdir in runtime_path: 4365ee53db2SLisandro Dalcin shell('install_name_tool', '-delete_rpath', libdir, dylib) 4375ee53db2SLisandro Dalcin for rpath in ('@loader_path',): 4385ee53db2SLisandro Dalcin if rpath not in runtime_path: 4395ee53db2SLisandro Dalcin shell('install_name_tool', '-add_rpath', rpath, dylib) 4405ee53db2SLisandro Dalcin for dep in dependencies: 4415ee53db2SLisandro Dalcin if os.path.dirname(dep) in (libdir,): 4425ee53db2SLisandro Dalcin newid = '@rpath/' + os.path.basename(dep) 4435ee53db2SLisandro Dalcin shell('install_name_tool', '-change', dep, newid, dylib) 4445ee53db2SLisandro Dalcin # fix shared library file and symlink 4455ee53db2SLisandro Dalcin basename = os.path.basename(dylib) 4465ee53db2SLisandro Dalcin libname, ext = os.path.splitext(basename) 4475ee53db2SLisandro Dalcin libname = libname.partition('.')[0] 4485ee53db2SLisandro Dalcin liblink = libname + ext 4495ee53db2SLisandro Dalcin dyname = os.path.basename(install_name) 4505ee53db2SLisandro Dalcin for symlink in lsdir(self.destLibDir, libname + '*' + ext): 4515ee53db2SLisandro Dalcin if os.path.islink(symlink): 4525ee53db2SLisandro Dalcin os.unlink(symlink) 4535ee53db2SLisandro Dalcin curdir = os.getcwd() 4545ee53db2SLisandro Dalcin try: 4555ee53db2SLisandro Dalcin os.chdir(os.path.dirname(dylib)) 4565ee53db2SLisandro Dalcin if dyname != basename: 4575ee53db2SLisandro Dalcin os.rename(basename, dyname) 4585ee53db2SLisandro Dalcin if dyname != liblink: 4595ee53db2SLisandro Dalcin os.symlink(dyname, liblink) 4605ee53db2SLisandro Dalcin finally: 4615ee53db2SLisandro Dalcin os.chdir(curdir) 4625ee53db2SLisandro Dalcin # 4635ee53db2SLisandro Dalcin return 4645ee53db2SLisandro Dalcin 4650ee81e68SLisandro Dalcin def createUninstaller(self): 4660ee81e68SLisandro Dalcin uninstallscript = os.path.join(self.destConfDir, 'uninstall.py') 4670ee81e68SLisandro Dalcin f = open(uninstallscript, 'w') 4680ee81e68SLisandro Dalcin # Could use the Python AST to do this 4690ee81e68SLisandro Dalcin f.write('#!'+sys.executable+'\n') 4700ee81e68SLisandro Dalcin f.write('import os\n') 471d97f9ea1SSatish Balay f.write('prefixdir = "'+self.installDir+'"\n') 472d97f9ea1SSatish Balay files = [dst.replace(self.destDir,self.installDir) for src, dst in self.copies] 473d97f9ea1SSatish Balay files.append(uninstallscript.replace(self.destDir,self.installDir)) 474d97f9ea1SSatish Balay f.write('files = '+repr(files)) 4750ee81e68SLisandro Dalcin f.write(''' 476d97f9ea1SSatish Balayfor file in files: 477d97f9ea1SSatish Balay if os.path.exists(file) or os.path.islink(file): 478d97f9ea1SSatish Balay os.remove(file) 479d97f9ea1SSatish Balay dir = os.path.dirname(file) 4802b39596bSSatish Balay while dir not in [os.path.dirname(prefixdir),'/']: 4812b39596bSSatish Balay try: os.rmdir(dir) 4822b39596bSSatish Balay except: break 483d97f9ea1SSatish Balay dir = os.path.dirname(dir) 4840ee81e68SLisandro Dalcin''') 4850ee81e68SLisandro Dalcin f.close() 4865b6bfdb9SJed Brown os.chmod(uninstallscript,0o744) 4870ee81e68SLisandro Dalcin return 4880ee81e68SLisandro Dalcin 4890ee81e68SLisandro Dalcin def installIncludes(self): 49032cabb2fSBarry Smith exclude = ['makefile'] 49132cabb2fSBarry Smith if not hasattr(self.compilers.setCompilers, 'FC'): 49232cabb2fSBarry Smith exclude.append('finclude') 49332cabb2fSBarry Smith if not self.mpi.usingMPIUni: 49432cabb2fSBarry Smith exclude.append('mpiuni') 49532cabb2fSBarry Smith self.copies.extend(self.copytree(self.rootIncludeDir, self.destIncludeDir,exclude = exclude)) 4960ee81e68SLisandro Dalcin self.copies.extend(self.copytree(self.archIncludeDir, self.destIncludeDir)) 4970ee81e68SLisandro Dalcin return 4980ee81e68SLisandro Dalcin 4990ee81e68SLisandro Dalcin def installConf(self): 500ce78bad3SBarry Smith self.copies.extend(self.copytree(self.rootConfDir, self.destConfDir, exclude = ['test.log'])) 501a035e9faSPierre 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'])) 5020ee81e68SLisandro Dalcin return 5030ee81e68SLisandro Dalcin 5040ee81e68SLisandro Dalcin def installBin(self): 505ce78bad3SBarry Smith exclude = ['bib2html','doc2lt','doctext','mapnames', 'pstogif','pstoxbm','tohtml'] 50632cabb2fSBarry Smith self.copies.extend(self.copytree(self.archBinDir, self.destBinDir, exclude = exclude )) 50732cabb2fSBarry Smith exclude = ['maint'] 50832cabb2fSBarry Smith if not self.mpi.usingMPIUni: 50932cabb2fSBarry Smith exclude.append('petsc-mpiexec.uni') 51032cabb2fSBarry Smith self.setCompilers.pushLanguage('C') 511011f288aSSatish Balay if self.setCompilers.getCompiler().find('win32fe') < 0: 51232cabb2fSBarry Smith exclude.append('win32fe') 51332cabb2fSBarry Smith self.setCompilers.popLanguage() 51432cabb2fSBarry Smith self.copies.extend(self.copytree(self.rootBinDir, self.destBinDir, exclude = exclude )) 5150ee81e68SLisandro Dalcin return 5160ee81e68SLisandro Dalcin 5170ee81e68SLisandro Dalcin def installShare(self): 5180ee81e68SLisandro Dalcin self.copies.extend(self.copytree(self.rootShareDir, self.destShareDir)) 519c173c275SScott Kruger examplesdir=os.path.join(self.destShareDir,'petsc','examples') 520c173c275SScott Kruger if os.path.exists(examplesdir): 521c173c275SScott Kruger shutil.rmtree(examplesdir) 522c173c275SScott Kruger os.mkdir(examplesdir) 52379eaf171SScott Kruger os.mkdir(os.path.join(examplesdir,'src')) 524c173c275SScott Kruger self.copyConfig(self.rootDir,examplesdir) 525fad83eadSPatrick Sanan if not self.argDB['no-examples']: 526fad83eadSPatrick Sanan self.copyExamples(self.rootSrcDir,os.path.join(examplesdir,'src')) 527c173c275SScott Kruger self.fixExamplesMakefile(os.path.join(examplesdir,'gmakefile.test')) 5280ee81e68SLisandro Dalcin return 5290ee81e68SLisandro Dalcin 5300ee81e68SLisandro Dalcin def copyLib(self, src, dst): 5310ee81e68SLisandro Dalcin '''Run ranlib on the destination library if it is an archive. Also run install_name_tool on dylib on Mac''' 5320ee81e68SLisandro Dalcin # Symlinks (assumed local) are recreated at dst 5330ee81e68SLisandro Dalcin if os.path.islink(src): 5340ee81e68SLisandro Dalcin linkto = os.readlink(src) 5350ee81e68SLisandro Dalcin try: 5360ee81e68SLisandro Dalcin os.remove(dst) # In case it already exists 5370ee81e68SLisandro Dalcin except OSError: 5380ee81e68SLisandro Dalcin pass 5390ee81e68SLisandro Dalcin os.symlink(linkto, dst) 5400ee81e68SLisandro Dalcin return 5410ee81e68SLisandro Dalcin shutil.copy2(src, dst) 542011f288aSSatish Balay if self.setCompilers.getCompiler().find('win32fe') < 0 and os.path.splitext(dst)[1] == '.'+self.arLibSuffix: 543abf72cf0SSatish Balay import shlex 544abf72cf0SSatish Balay self.executeShellCommand(shlex.split(self.ranlib) + [dst]) 545c9e802c5SMin RK if os.path.splitext(dst)[1] == '.dylib' and shutil.which('otool') and shutil.which('install_name_tool'): 546793d7be8SSatish Balay [output,err,flg] = self.executeShellCommand(['otool', '-D', src]) 547af2c601bSBarry Smith oldname = output[output.find("\n")+1:] 548d4c3e6c5SSatish Balay installName = oldname.replace(os.path.realpath(self.archDir), self.installDir) 549793d7be8SSatish Balay self.executeShellCommand(['install_name_tool', '-id', installName, dst]) 5500ee81e68SLisandro Dalcin # preserve the original timestamps - so that the .a vs .so time order is preserved 5510ee81e68SLisandro Dalcin shutil.copystat(src,dst) 5520ee81e68SLisandro Dalcin return 5530ee81e68SLisandro Dalcin 5540ee81e68SLisandro Dalcin def installLib(self): 55532cabb2fSBarry Smith self.copies.extend(self.copytree(self.archLibDir, self.destLibDir, copyFunc = self.copyLib, exclude = ['.DIR'],recurse = 0)) 55632cabb2fSBarry 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)) 5570ee81e68SLisandro Dalcin return 5580ee81e68SLisandro Dalcin 5590ee81e68SLisandro Dalcin 5600ee81e68SLisandro Dalcin def outputInstallDone(self): 5615b4fc442SVaclav Hapla from config.packages.make import getMakeUserPath 5625b6bfdb9SJed Brown print('''\ 5630ee81e68SLisandro Dalcin==================================== 5640ee81e68SLisandro DalcinInstall complete. 5650ee81e68SLisandro DalcinNow to check if the libraries are working do (in current directory): 5665b4fc442SVaclav Hapla%s PETSC_DIR=%s PETSC_ARCH="" check 5670ee81e68SLisandro Dalcin====================================\ 5685b4fc442SVaclav Hapla''' % (getMakeUserPath(self.arch), self.installDir)) 5690ee81e68SLisandro Dalcin return 5700ee81e68SLisandro Dalcin 5710ee81e68SLisandro Dalcin def outputDestDirDone(self): 5725b6bfdb9SJed Brown print('''\ 5730ee81e68SLisandro Dalcin==================================== 5740ee81e68SLisandro DalcinCopy to DESTDIR %s is now complete. 5750ee81e68SLisandro DalcinBefore use - please copy/install over to specified prefix: %s 5760ee81e68SLisandro Dalcin====================================\ 5775b6bfdb9SJed Brown''' % (self.destDir,self.installDir)) 5780ee81e68SLisandro Dalcin return 5790ee81e68SLisandro Dalcin 5800ee81e68SLisandro Dalcin def runsetup(self): 5810ee81e68SLisandro Dalcin self.setup() 5820ee81e68SLisandro Dalcin self.setupDirectories() 583*6e8294f6SStefano Zampini self.setupBuild() 5840ee81e68SLisandro Dalcin self.checkPrefix() 5850ee81e68SLisandro Dalcin self.checkDestdir() 5860ee81e68SLisandro Dalcin return 5870ee81e68SLisandro Dalcin 5880ee81e68SLisandro Dalcin def runcopy(self): 5890ee81e68SLisandro Dalcin if self.destDir == self.installDir: 5905b6bfdb9SJed Brown print('*** Installing PETSc at prefix location:',self.destDir, ' ***') 5910ee81e68SLisandro Dalcin else: 5925b6bfdb9SJed Brown print('*** Copying PETSc to DESTDIR location:',self.destDir, ' ***') 5930ee81e68SLisandro Dalcin if not os.path.exists(self.destDir): 5940ee81e68SLisandro Dalcin try: 5950ee81e68SLisandro Dalcin os.makedirs(self.destDir) 5960ee81e68SLisandro Dalcin except: 5975b6bfdb9SJed Brown print('********************************************************************') 5985b6bfdb9SJed Brown print('Unable to create', self.destDir, 'Perhaps you need to do "sudo make install"') 5995b6bfdb9SJed Brown print('********************************************************************') 6000ee81e68SLisandro Dalcin sys.exit(1) 6010ee81e68SLisandro Dalcin self.installIncludes() 6020ee81e68SLisandro Dalcin self.installConf() 6030ee81e68SLisandro Dalcin self.installBin() 6040ee81e68SLisandro Dalcin self.installLib() 6050ee81e68SLisandro Dalcin self.installShare() 6065ee53db2SLisandro Dalcin self.createUninstaller() 6070ee81e68SLisandro Dalcin return 6080ee81e68SLisandro Dalcin 6090ee81e68SLisandro Dalcin def runfix(self): 6100ee81e68SLisandro Dalcin self.fixConf() 611*6e8294f6SStefano Zampini if self.using_build_backend: 6125ee53db2SLisandro Dalcin self.fixPythonWheel() 6130ee81e68SLisandro Dalcin return 6140ee81e68SLisandro Dalcin 6150ee81e68SLisandro Dalcin def rundone(self): 6160ee81e68SLisandro Dalcin if self.destDir == self.installDir: 6170ee81e68SLisandro Dalcin self.outputInstallDone() 6180ee81e68SLisandro Dalcin else: 6190ee81e68SLisandro Dalcin self.outputDestDirDone() 6200ee81e68SLisandro Dalcin return 6210ee81e68SLisandro Dalcin 6220ee81e68SLisandro Dalcin def run(self): 6230ee81e68SLisandro Dalcin self.runsetup() 6240ee81e68SLisandro Dalcin self.runcopy() 6250ee81e68SLisandro Dalcin self.runfix() 6260ee81e68SLisandro Dalcin self.rundone() 6270ee81e68SLisandro Dalcin return 6280ee81e68SLisandro Dalcin 6290ee81e68SLisandro Dalcinif __name__ == '__main__': 6300ee81e68SLisandro Dalcin Installer(sys.argv[1:]).run() 6310ee81e68SLisandro Dalcin # temporary hack - delete log files created by BuildSystem - when 'sudo make install' is invoked 63203e6d329SSatish Balay delfiles=['RDict.db','RDict.log','buildsystem.log','default.log','buildsystem.log.bkp','default.log.bkp'] 6330ee81e68SLisandro Dalcin for delfile in delfiles: 6340ee81e68SLisandro Dalcin if os.path.exists(delfile) and (os.stat(delfile).st_uid==0): 6350ee81e68SLisandro Dalcin os.remove(delfile) 636