1df3bd252SSatish Balay#!/usr/bin/env python3 25b6bfdb9SJed Brownfrom __future__ import print_function 3e551db17SScott Krugerimport os, re, shutil, sys 46e8294f6SStefano 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 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 def setupModules(self): 520ee81e68SLisandro Dalcin self.setCompilers = self.framework.require('config.setCompilers', None) 530ee81e68SLisandro Dalcin self.arch = self.framework.require('PETSc.options.arch', None) 540ee81e68SLisandro Dalcin self.petscdir = self.framework.require('PETSc.options.petscdir', None) 550ee81e68SLisandro Dalcin self.compilers = self.framework.require('config.compilers', None) 5632cabb2fSBarry Smith self.mpi = self.framework.require('config.packages.MPI', None) 570ee81e68SLisandro Dalcin return 580ee81e68SLisandro Dalcin 590ee81e68SLisandro Dalcin def setup(self): 600ee81e68SLisandro Dalcin script.Script.setup(self) 610ee81e68SLisandro Dalcin self.framework = self.loadConfigure() 620ee81e68SLisandro Dalcin self.setupModules() 630ee81e68SLisandro Dalcin return 640ee81e68SLisandro Dalcin 650ee81e68SLisandro Dalcin def setupDirectories(self): 660ee81e68SLisandro Dalcin self.rootDir = self.petscdir.dir 674a08bad0SBarry Smith self.installDir = os.path.abspath(os.path.expanduser(self.framework.argDB['prefix'])) 688727f567SSatish Balay self.destDir = os.path.abspath(self.argDB['destDir']+self.installDir) 690ee81e68SLisandro Dalcin self.arch = self.arch.arch 7002e047dfSSatish Balay self.archDir = os.path.join(self.rootDir, self.arch) 710ee81e68SLisandro Dalcin self.rootIncludeDir = os.path.join(self.rootDir, 'include') 720ee81e68SLisandro Dalcin self.archIncludeDir = os.path.join(self.rootDir, self.arch, 'include') 73af0996ceSBarry Smith self.rootConfDir = os.path.join(self.rootDir, 'lib','petsc','conf') 74af0996ceSBarry Smith self.archConfDir = os.path.join(self.rootDir, self.arch, 'lib','petsc','conf') 75c3a89c15SBarry Smith self.rootBinDir = os.path.join(self.rootDir, 'lib','petsc','bin') 760ee81e68SLisandro Dalcin self.archBinDir = os.path.join(self.rootDir, self.arch, 'bin') 770ee81e68SLisandro Dalcin self.archLibDir = os.path.join(self.rootDir, self.arch, 'lib') 780ee81e68SLisandro Dalcin self.destIncludeDir = os.path.join(self.destDir, 'include') 79af0996ceSBarry Smith self.destConfDir = os.path.join(self.destDir, 'lib','petsc','conf') 800ee81e68SLisandro Dalcin self.destLibDir = os.path.join(self.destDir, 'lib') 81c3a89c15SBarry Smith self.destBinDir = os.path.join(self.destDir, 'lib','petsc','bin') 820ee81e68SLisandro Dalcin self.installIncludeDir = os.path.join(self.installDir, 'include') 832d10696aSSatish Balay self.installLibDir = os.path.join(self.installDir, 'lib') 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 1266e8294f6SStefano Zampini def setupBuild(self): 1276e8294f6SStefano Zampini self.using_build_backend = any( 1286e8294f6SStefano Zampini os.environ.get(prefix + '_BUILD_BACKEND') 1296e8294f6SStefano Zampini for prefix in ('_PYPROJECT_HOOKS', 'PEP517') 1306e8294f6SStefano Zampini ) 1316e8294f6SStefano Zampini self.relocate_py_env = os.environ.get('CIBUILDWHEEL', '0') == '1' 1326e8294f6SStefano Zampini 1330ee81e68SLisandro Dalcin def copyfile(self, src, dst, symlinks = False, copyFunc = shutil.copy2): 1340ee81e68SLisandro Dalcin """Copies a single file """ 1350ee81e68SLisandro Dalcin copies = [] 1360ee81e68SLisandro Dalcin errors = [] 1370ee81e68SLisandro Dalcin if not os.path.exists(dst): 1380ee81e68SLisandro Dalcin os.makedirs(dst) 1390ee81e68SLisandro Dalcin elif not os.path.isdir(dst): 1405b6bfdb9SJed Brown raise shutil.Error('Destination is not a directory') 1410ee81e68SLisandro Dalcin srcname = src 1420ee81e68SLisandro Dalcin dstname = os.path.join(dst, os.path.basename(src)) 1430ee81e68SLisandro Dalcin try: 1440ee81e68SLisandro Dalcin if symlinks and os.path.islink(srcname): 1450ee81e68SLisandro Dalcin linkto = os.readlink(srcname) 1460ee81e68SLisandro Dalcin os.symlink(linkto, dstname) 1470ee81e68SLisandro Dalcin else: 1480ee81e68SLisandro Dalcin copyFunc(srcname, dstname) 1490ee81e68SLisandro Dalcin copies.append((srcname, dstname)) 1505b6bfdb9SJed Brown except (IOError, os.error) as why: 1510ee81e68SLisandro Dalcin errors.append((srcname, dstname, str(why))) 1525b6bfdb9SJed Brown except shutil.Error as err: 1532c852529SBarry Smith errors.append((srcname,dstname,str(err.args[0]))) 1540ee81e68SLisandro Dalcin if errors: 1555b6bfdb9SJed Brown raise shutil.Error(errors) 1560ee81e68SLisandro Dalcin return copies 1570ee81e68SLisandro Dalcin 15826e8aaceSBarry Smith def fixExamplesMakefile(self, src): 159f0b74427SPierre Jolivet '''Change ././${PETSC_ARCH} in makefile in root PETSc directory with ${PETSC_DIR}''' 16026e8aaceSBarry Smith lines = [] 16126e8aaceSBarry Smith oldFile = open(src, 'r') 162e551db17SScott Kruger alllines=oldFile.read() 16326e8aaceSBarry Smith oldFile.close() 164e551db17SScott Kruger newlines=alllines.split('\n')[0]+'\n' # Firstline 165d5b43468SJose E. Roman # Hardcode PETSC_DIR and PETSC_ARCH to avoid users doing the wrong thing 166e551db17SScott Kruger newlines+='PETSC_DIR='+self.installDir+'\n' 167e551db17SScott Kruger newlines+='PETSC_ARCH=\n' 168e551db17SScott Kruger for line in alllines.split('\n')[1:]: 1694ff3c6a1SScott Kruger if line.startswith('TESTLOGFILE'): 170c173c275SScott Kruger newlines+='TESTLOGFILE = $(TESTDIR)/examples-install.log\n' 171e551db17SScott Kruger elif line.startswith('CONFIGDIR'): 172e551db17SScott Kruger newlines+='CONFIGDIR:=$(PETSC_DIR)/$(PETSC_ARCH)/share/petsc/examples/config\n' 173fc46264cSScott Kruger elif line.startswith('$(generatedtest)') and 'petscvariables' in line: 174c173c275SScott Kruger newlines+='all: test\n\n'+line+'\n' 175e551db17SScott Kruger else: 1764ff3c6a1SScott Kruger newlines+=line+'\n' 17726e8aaceSBarry Smith newFile = open(src, 'w') 178e551db17SScott Kruger newFile.write(newlines) 17926e8aaceSBarry Smith newFile.close() 18026e8aaceSBarry Smith return 18126e8aaceSBarry Smith 182e551db17SScott Kruger def copyConfig(self, src, dst): 1832f21b5d8SJed Brown """Copy configuration/testing files 184e551db17SScott Kruger """ 185e551db17SScott Kruger if not os.path.isdir(dst): 1865b6bfdb9SJed Brown raise shutil.Error('Destination is not a directory') 187e551db17SScott Kruger 188adf35c6eSSatish Balay self.copies.extend(self.copyfile('gmakefile.test',dst)) 189e551db17SScott Kruger newConfigDir=os.path.join(dst,'config') # Am not renaming at present 190e551db17SScott Kruger if not os.path.isdir(newConfigDir): os.mkdir(newConfigDir) 191e551db17SScott Kruger testConfFiles="gmakegentest.py gmakegen.py testparse.py example_template.py".split() 19258780e5dSStefano Zampini testConfFiles+="petsc_harness.sh report_tests.py query_tests.py".split() 193e551db17SScott Kruger for tf in testConfFiles: 194adf35c6eSSatish Balay self.copies.extend(self.copyfile(os.path.join('config',tf),newConfigDir)) 195e551db17SScott Kruger return 196e551db17SScott Kruger 19726e8aaceSBarry Smith def copyExamples(self, src, dst): 1984ff3c6a1SScott Kruger """copy the examples directories 19926e8aaceSBarry Smith """ 200ad246c4dSSatish Balay for root, dirs, files in os.walk(src, topdown=False): 2012f21b5d8SJed Brown if os.path.basename(root) not in ("tests", "tutorials"): continue 202ad246c4dSSatish Balay self.copies.extend(self.copytree(root, root.replace(src,dst))) 2034ff3c6a1SScott Kruger return 2040ee81e68SLisandro Dalcin 2050080bb28SSatish Balay def copytree(self, src, dst, symlinks = False, copyFunc = shutil.copy2, exclude = [], exclude_ext= ['.DSYM','.o','.pyc'], recurse = 1): 2060ee81e68SLisandro Dalcin """Recursively copy a directory tree using copyFunc, which defaults to shutil.copy2(). 2070ee81e68SLisandro Dalcin 2080ee81e68SLisandro Dalcin The copyFunc() you provide is only used on the top level, lower levels always use shutil.copy2 2090ee81e68SLisandro Dalcin 2100ee81e68SLisandro Dalcin The destination directory must not already exist. 2110ee81e68SLisandro Dalcin If exception(s) occur, an shutil.Error is raised with a list of reasons. 2120ee81e68SLisandro Dalcin 2130ee81e68SLisandro Dalcin If the optional symlinks flag is true, symbolic links in the 2140ee81e68SLisandro Dalcin source tree result in symbolic links in the destination tree; if 2150ee81e68SLisandro Dalcin it is false, the contents of the files pointed to by symbolic 2160ee81e68SLisandro Dalcin links are copied. 2170ee81e68SLisandro Dalcin """ 2180ee81e68SLisandro Dalcin copies = [] 2190ee81e68SLisandro Dalcin names = os.listdir(src) 2200ee81e68SLisandro Dalcin if not os.path.exists(dst): 2210ee81e68SLisandro Dalcin os.makedirs(dst) 2220ee81e68SLisandro Dalcin elif not os.path.isdir(dst): 2235b6bfdb9SJed Brown raise shutil.Error('Destination is not a directory') 2240ee81e68SLisandro Dalcin errors = [] 2252c72da00SPierre Jolivet srclinks = [] 2262c72da00SPierre Jolivet dstlinks = [] 2270ee81e68SLisandro Dalcin for name in names: 2280ee81e68SLisandro Dalcin srcname = os.path.join(src, name) 2290ee81e68SLisandro Dalcin dstname = os.path.join(dst, name) 2300ee81e68SLisandro Dalcin try: 2310ee81e68SLisandro Dalcin if symlinks and os.path.islink(srcname): 2320ee81e68SLisandro Dalcin linkto = os.readlink(srcname) 2330ee81e68SLisandro Dalcin os.symlink(linkto, dstname) 23432cabb2fSBarry Smith elif os.path.isdir(srcname) and recurse and not os.path.basename(srcname) in exclude: 235adf35c6eSSatish Balay copies.extend(self.copytree(srcname, dstname, symlinks,exclude = exclude, exclude_ext = exclude_ext)) 236adf35c6eSSatish Balay elif os.path.isfile(srcname) and not os.path.basename(srcname) in exclude and os.path.splitext(name)[1] not in exclude_ext : 2372c72da00SPierre Jolivet if os.path.islink(srcname): 2382c72da00SPierre Jolivet srclinks.append(srcname) 2392c72da00SPierre Jolivet dstlinks.append(dstname) 2402c72da00SPierre Jolivet else: 2410ee81e68SLisandro Dalcin copyFunc(srcname, dstname) 2420ee81e68SLisandro Dalcin copies.append((srcname, dstname)) 2430ee81e68SLisandro Dalcin # XXX What about devices, sockets etc.? 2445b6bfdb9SJed Brown except (IOError, os.error) as why: 2450ee81e68SLisandro Dalcin errors.append((srcname, dstname, str(why))) 2460ee81e68SLisandro Dalcin # catch the Error from the recursive copytree so that we can 2470ee81e68SLisandro Dalcin # continue with other files 2485b6bfdb9SJed Brown except shutil.Error as err: 2492c852529SBarry Smith errors.append((srcname,dstname,str(err.args[0]))) 2502c72da00SPierre Jolivet for srcname, dstname in zip(srclinks, dstlinks): 2512c72da00SPierre Jolivet try: 2522c72da00SPierre Jolivet copyFunc(srcname, dstname) 2532c72da00SPierre Jolivet copies.append((srcname, dstname)) 2542c72da00SPierre Jolivet except (IOError, os.error) as why: 2552c72da00SPierre Jolivet errors.append((srcname, dstname, str(why))) 2562c72da00SPierre Jolivet # catch the Error from the recursive copytree so that we can 2572c72da00SPierre Jolivet # continue with other files 2582c72da00SPierre Jolivet except shutil.Error as err: 2592c852529SBarry Smith errors.append((srcname,dstname,str(err.args[0]))) 2600ee81e68SLisandro Dalcin try: 2610ee81e68SLisandro Dalcin shutil.copystat(src, dst) 2625b6bfdb9SJed Brown except OSError as e: 2630ee81e68SLisandro Dalcin if WindowsError is not None and isinstance(e, WindowsError): 2640ee81e68SLisandro Dalcin # Copying file access times may fail on Windows 2650ee81e68SLisandro Dalcin pass 2660ee81e68SLisandro Dalcin else: 2672c852529SBarry Smith errors.append((src, dst, str(e))) 2680ee81e68SLisandro Dalcin if errors: 2695b6bfdb9SJed Brown raise shutil.Error(errors) 2700ee81e68SLisandro Dalcin return copies 2710ee81e68SLisandro Dalcin 2720ee81e68SLisandro Dalcin def fixConfFile(self, src): 2730ee81e68SLisandro Dalcin lines = [] 2740ee81e68SLisandro Dalcin oldFile = open(src, 'r') 2750ee81e68SLisandro Dalcin for line in oldFile.readlines(): 2765a21677cSJed Brown if line.startswith('PETSC_CC_INCLUDES =') or line.startswith('PETSC_FC_INCLUDES ='): 2775a21677cSJed Brown continue 2785a21677cSJed Brown line = line.replace('PETSC_CC_INCLUDES_INSTALL', 'PETSC_CC_INCLUDES') 2795a21677cSJed Brown line = line.replace('PETSC_FC_INCLUDES_INSTALL', 'PETSC_FC_INCLUDES') 2800ee81e68SLisandro Dalcin # remove PETSC_DIR/PETSC_ARCH variables from conf-makefiles. They are no longer necessary 2810ee81e68SLisandro Dalcin line = line.replace('${PETSC_DIR}/${PETSC_ARCH}', self.installDir) 2820ee81e68SLisandro Dalcin line = line.replace('PETSC_ARCH=${PETSC_ARCH}', '') 2830ee81e68SLisandro Dalcin line = line.replace('${PETSC_DIR}', self.installDir) 2842d10696aSSatish Balay # replace PETSC_DIR/PETSC_ARCH/lib (i.e., build location) with prefix/lib 2852d10696aSSatish Balay line = line.replace(self.archLibDir,self.installLibDir) 286011f288aSSatish Balay # replace PETSC_DIR/lib/petsc/bin with prefix/lib/petsc/bin 287011f288aSSatish Balay line = line.replace(self.rootBinDir,self.destBinDir) 2880ee81e68SLisandro Dalcin lines.append(line) 2890ee81e68SLisandro Dalcin oldFile.close() 2900ee81e68SLisandro Dalcin newFile = open(src, 'w') 2910ee81e68SLisandro Dalcin newFile.write(''.join(lines)) 2920ee81e68SLisandro Dalcin newFile.close() 2930ee81e68SLisandro Dalcin return 2940ee81e68SLisandro Dalcin 2950ee81e68SLisandro Dalcin def fixConf(self): 2960ee81e68SLisandro Dalcin import shutil 297cb5db241SBarry Smith for file in ['rules', 'rules_doc.mk', 'rules_util.mk', 'variables', 'petscrules', 'petscvariables']: 2980ee81e68SLisandro Dalcin self.fixConfFile(os.path.join(self.destConfDir,file)) 2990ee81e68SLisandro Dalcin return 3000ee81e68SLisandro Dalcin 3015ee53db2SLisandro Dalcin def fixPythonWheel(self): 3025ee53db2SLisandro Dalcin import glob 3035ee53db2SLisandro Dalcin import shutil 3045ee53db2SLisandro Dalcin # 3055ee53db2SLisandro Dalcin for pattern in ( 3065ee53db2SLisandro Dalcin self.destLibDir + '/*.a', 3075ee53db2SLisandro Dalcin self.destLibDir + '/*.la', 3085ee53db2SLisandro Dalcin self.destLibDir + '/pkgconfig', # TODO: keep? 3095ee53db2SLisandro Dalcin self.destConfDir + '/configure-hash', 3105ee53db2SLisandro Dalcin self.destConfDir + '/uninstall.py', 3115ee53db2SLisandro Dalcin self.destConfDir + '/reconfigure-*.py', 3125ee53db2SLisandro Dalcin self.destConfDir + '/pkg.conf.*', 3135ee53db2SLisandro Dalcin self.destConfDir + '/pkg.git*.*', 3145ee53db2SLisandro Dalcin self.destConfDir + '/modules', # TODO: keep? 3155ee53db2SLisandro Dalcin self.destShareDir + '/*/examples/src/*', 3165ee53db2SLisandro Dalcin self.destShareDir + '/*/datafiles', 3175ee53db2SLisandro Dalcin ): 3185ee53db2SLisandro Dalcin for pathname in glob.glob(pattern): 3195ee53db2SLisandro Dalcin if os.path.isdir(pathname): 3205ee53db2SLisandro Dalcin shutil.rmtree(pathname) 3215ee53db2SLisandro Dalcin elif os.path.exists(pathname): 3225ee53db2SLisandro Dalcin os.remove(pathname) 3235ee53db2SLisandro Dalcin # 3246e8294f6SStefano Zampini if self.relocate_py_env: 3256e8294f6SStefano Zampini pydir = sys.prefix 3266e8294f6SStefano Zampini pylibdir = os.path.join(pydir, 'lib') 3276e8294f6SStefano Zampini pysitedir = sysconfig.get_paths()["platlib"] 3286e8294f6SStefano Zampini # petsc is installed in site-packages 3296e8294f6SStefano Zampini petscdir = os.path.join(pysitedir, 'petsc') 3306e8294f6SStefano Zampini petsclibdir = os.path.join(petscdir, 'lib') 3315ee53db2SLisandro Dalcin for filename in ( 3325ee53db2SLisandro Dalcin self.destIncludeDir + '/petscconf.h', 3335ee53db2SLisandro Dalcin self.destIncludeDir + '/petscconfiginfo.h', 3345ee53db2SLisandro Dalcin self.destIncludeDir + '/petscmachineinfo.h', 3355ee53db2SLisandro Dalcin self.destShareDir + '/petsc/examples/gmakefile.test', 3365ee53db2SLisandro Dalcin self.destConfDir + '/rules', 3375ee53db2SLisandro Dalcin self.destConfDir + '/rules_doc.mk', 3385ee53db2SLisandro Dalcin self.destConfDir + '/rules_util.mk', 3395ee53db2SLisandro Dalcin self.destConfDir + '/petscrules', 3405ee53db2SLisandro Dalcin self.destConfDir + '/variables', 3415ee53db2SLisandro Dalcin self.destConfDir + '/petscvariables', 3425ee53db2SLisandro Dalcin ): 3435ee53db2SLisandro Dalcin with open(filename, 'r') as oldFile: 3445ee53db2SLisandro Dalcin contents = oldFile.read() 3455ee53db2SLisandro Dalcin contents = contents.replace(self.installDir, '${PETSC_DIR}') 3465ee53db2SLisandro Dalcin contents = contents.replace(self.rootDir, '${PETSC_DIR}') 3476e8294f6SStefano Zampini if self.relocate_py_env: 3486e8294f6SStefano Zampini pydir_from_petsc = os.path.relpath(pydir, petscdir) 3496e8294f6SStefano Zampini contents = contents.replace(pydir, os.path.join('${PETSC_DIR}', pydir_from_petsc)) 3505ee53db2SLisandro Dalcin contents = re.sub( 3515ee53db2SLisandro Dalcin r'^(PYTHON(_EXE)?) = (.*)$', 3525ee53db2SLisandro Dalcin r'\1 = python%d' % sys.version_info[0], 3535ee53db2SLisandro Dalcin contents, flags=re.MULTILINE, 3545ee53db2SLisandro Dalcin ) 3555ee53db2SLisandro Dalcin with open(filename, 'w') as newFile: 3565ee53db2SLisandro Dalcin newFile.write(contents) 3575ee53db2SLisandro Dalcin # 3585ee53db2SLisandro Dalcin def lsdir(dirname, *patterns): 3595ee53db2SLisandro Dalcin return glob.glob(os.path.join(dirname, *patterns)) 3605ee53db2SLisandro Dalcin def shell(*args): 3615ee53db2SLisandro Dalcin return self.executeShellCommand(' '.join(args))[0] 3625ee53db2SLisandro Dalcin libdir = os.path.join(self.installDir, 'lib') 3635ee53db2SLisandro Dalcin if sys.platform == 'linux': 3645ee53db2SLisandro Dalcin libraries = [ 3655ee53db2SLisandro Dalcin lib for lib in lsdir(self.destLibDir, 'lib*.so*') 3665ee53db2SLisandro Dalcin if not os.path.islink(lib) 3675ee53db2SLisandro Dalcin ] 3685ee53db2SLisandro Dalcin for shlib in libraries: 3695ee53db2SLisandro Dalcin # fix shared library rpath 3705ee53db2SLisandro Dalcin rpath = shell('patchelf', '--print-rpath', shlib) 3715ee53db2SLisandro Dalcin rpath = rpath.split(os.path.pathsep) 3726e8294f6SStefano Zampini if not self.relocate_py_env: 3735ee53db2SLisandro Dalcin if libdir in rpath: 3745ee53db2SLisandro Dalcin rpath.insert(0, '$ORIGIN') 3755ee53db2SLisandro Dalcin while libdir in rpath: 3765ee53db2SLisandro Dalcin rpath.remove(libdir) 3776e8294f6SStefano Zampini else: 3786e8294f6SStefano Zampini rpathold = rpath 3796e8294f6SStefano Zampini rpath = [] 3806e8294f6SStefano Zampini # strip all rpath info, except for libraries in Python 3816e8294f6SStefano Zampini # sys prefix, site-packages, or petsc/lib 3826e8294f6SStefano Zampini rpath.insert(0, '$ORIGIN') 3836e8294f6SStefano Zampini for libdir in rpathold: 3846e8294f6SStefano Zampini if libdir.startswith(pysitedir): 3856e8294f6SStefano Zampini libdir_from_petsc = os.path.relpath(libdir, petsclibdir) 3866e8294f6SStefano Zampini rpath.insert(0, os.path.join('$ORIGIN',libdir_from_petsc)) 3876e8294f6SStefano Zampini pylibdir_from_petsc = os.path.relpath(pylibdir, petsclibdir) 3886e8294f6SStefano Zampini rpath.insert(0, os.path.join('$ORIGIN',pylibdir_from_petsc)) 3895ee53db2SLisandro Dalcin if rpath: 3905ee53db2SLisandro Dalcin rpath = os.path.pathsep.join(rpath) 3915ee53db2SLisandro Dalcin shell('patchelf', '--set-rpath', "'%s'" % rpath, shlib) 3925ee53db2SLisandro Dalcin # fix shared library file and symlink 3935ee53db2SLisandro Dalcin basename = os.path.basename(shlib) 3945ee53db2SLisandro Dalcin libname, ext, _ = basename.partition('.so') 3955ee53db2SLisandro Dalcin liblink = libname + ext 3965ee53db2SLisandro Dalcin soname = shell('patchelf', '--print-soname', shlib) 3975ee53db2SLisandro Dalcin for symlink in lsdir(self.destLibDir, liblink + '*'): 3985ee53db2SLisandro Dalcin if os.path.islink(symlink): 3995ee53db2SLisandro Dalcin os.unlink(symlink) 4005ee53db2SLisandro Dalcin curdir = os.getcwd() 4015ee53db2SLisandro Dalcin try: 4025ee53db2SLisandro Dalcin os.chdir(os.path.dirname(shlib)) 4035ee53db2SLisandro Dalcin if soname != basename: 4045ee53db2SLisandro Dalcin os.rename(basename, soname) 4055ee53db2SLisandro Dalcin if soname != liblink: 4066e8294f6SStefano Zampini with open(liblink, 'w') as f: 4076e8294f6SStefano Zampini f.write('INPUT(' + soname + ')\n') 4085ee53db2SLisandro Dalcin finally: 4095ee53db2SLisandro Dalcin os.chdir(curdir) 4105ee53db2SLisandro Dalcin if sys.platform == 'darwin': 4115ee53db2SLisandro Dalcin def otool(cmd, dylib): 4125ee53db2SLisandro Dalcin pattern = r''' 4135ee53db2SLisandro Dalcin ^\s+ cmd \s %s$\n 4145ee53db2SLisandro Dalcin ^\s+ cmdsize \s \d+$\n 4155ee53db2SLisandro Dalcin ^\s+ (?:name|path) \s (.*) \s \(offset \s \d+\)$ 4165ee53db2SLisandro Dalcin ''' % cmd 4175ee53db2SLisandro Dalcin return re.findall( 4185ee53db2SLisandro Dalcin pattern, shell('otool', '-l', dylib), 4195ee53db2SLisandro Dalcin flags=re.VERBOSE | re.MULTILINE, 4205ee53db2SLisandro Dalcin ) 4215ee53db2SLisandro Dalcin libraries = [ 4225ee53db2SLisandro Dalcin lib for lib in lsdir(self.destLibDir, 'lib*.dylib') 4235ee53db2SLisandro Dalcin if not os.path.islink(lib) 4245ee53db2SLisandro Dalcin ] 4255ee53db2SLisandro Dalcin for dylib in libraries: 4265ee53db2SLisandro Dalcin install_name = otool('LC_ID_DYLIB', dylib)[0] 4275ee53db2SLisandro Dalcin dependencies = otool('LC_LOAD_DYLIB', dylib) 4285ee53db2SLisandro Dalcin runtime_path = otool('LC_RPATH', dylib) 4295ee53db2SLisandro Dalcin # fix shared library install name and rpath 4305ee53db2SLisandro Dalcin install_name = '@rpath/' + os.path.basename(install_name) 4315ee53db2SLisandro Dalcin shell('install_name_tool', '-id', install_name, dylib) 4325ee53db2SLisandro Dalcin if libdir in runtime_path: 4335ee53db2SLisandro Dalcin shell('install_name_tool', '-delete_rpath', libdir, dylib) 4345ee53db2SLisandro Dalcin for rpath in ('@loader_path',): 4355ee53db2SLisandro Dalcin if rpath not in runtime_path: 4365ee53db2SLisandro Dalcin shell('install_name_tool', '-add_rpath', rpath, dylib) 4375ee53db2SLisandro Dalcin for dep in dependencies: 4385ee53db2SLisandro Dalcin if os.path.dirname(dep) in (libdir,): 4395ee53db2SLisandro Dalcin newid = '@rpath/' + os.path.basename(dep) 4405ee53db2SLisandro Dalcin shell('install_name_tool', '-change', dep, newid, dylib) 4415ee53db2SLisandro Dalcin # fix shared library file and symlink 4425ee53db2SLisandro Dalcin basename = os.path.basename(dylib) 4435ee53db2SLisandro Dalcin libname, ext = os.path.splitext(basename) 4445ee53db2SLisandro Dalcin libname = libname.partition('.')[0] 4455ee53db2SLisandro Dalcin liblink = libname + ext 4465ee53db2SLisandro Dalcin dyname = os.path.basename(install_name) 4475ee53db2SLisandro Dalcin for symlink in lsdir(self.destLibDir, libname + '*' + ext): 4485ee53db2SLisandro Dalcin if os.path.islink(symlink): 4495ee53db2SLisandro Dalcin os.unlink(symlink) 4505ee53db2SLisandro Dalcin curdir = os.getcwd() 4515ee53db2SLisandro Dalcin try: 4525ee53db2SLisandro Dalcin os.chdir(os.path.dirname(dylib)) 4535ee53db2SLisandro Dalcin if dyname != basename: 4545ee53db2SLisandro Dalcin os.rename(basename, dyname) 4555ee53db2SLisandro Dalcin if dyname != liblink: 4565ee53db2SLisandro Dalcin os.symlink(dyname, liblink) 4575ee53db2SLisandro Dalcin finally: 4585ee53db2SLisandro Dalcin os.chdir(curdir) 4595ee53db2SLisandro Dalcin # 4605ee53db2SLisandro Dalcin return 4615ee53db2SLisandro Dalcin 4620ee81e68SLisandro Dalcin def createUninstaller(self): 4630ee81e68SLisandro Dalcin uninstallscript = os.path.join(self.destConfDir, 'uninstall.py') 4640ee81e68SLisandro Dalcin f = open(uninstallscript, 'w') 4650ee81e68SLisandro Dalcin # Could use the Python AST to do this 4660ee81e68SLisandro Dalcin f.write('#!'+sys.executable+'\n') 4670ee81e68SLisandro Dalcin f.write('import os\n') 468d97f9ea1SSatish Balay f.write('prefixdir = "'+self.installDir+'"\n') 469d97f9ea1SSatish Balay files = [dst.replace(self.destDir,self.installDir) for src, dst in self.copies] 470d97f9ea1SSatish Balay files.append(uninstallscript.replace(self.destDir,self.installDir)) 471d97f9ea1SSatish Balay f.write('files = '+repr(files)) 4720ee81e68SLisandro Dalcin f.write(''' 473d97f9ea1SSatish Balayfor file in files: 474d97f9ea1SSatish Balay if os.path.exists(file) or os.path.islink(file): 475d97f9ea1SSatish Balay os.remove(file) 476d97f9ea1SSatish Balay dir = os.path.dirname(file) 4772b39596bSSatish Balay while dir not in [os.path.dirname(prefixdir),'/']: 4782b39596bSSatish Balay try: os.rmdir(dir) 4792b39596bSSatish Balay except: break 480d97f9ea1SSatish Balay dir = os.path.dirname(dir) 4810ee81e68SLisandro Dalcin''') 4820ee81e68SLisandro Dalcin f.close() 4835b6bfdb9SJed Brown os.chmod(uninstallscript,0o744) 4840ee81e68SLisandro Dalcin return 4850ee81e68SLisandro Dalcin 4860ee81e68SLisandro Dalcin def installIncludes(self): 48732cabb2fSBarry Smith exclude = ['makefile'] 48832cabb2fSBarry Smith if not hasattr(self.compilers.setCompilers, 'FC'): 48932cabb2fSBarry Smith exclude.append('finclude') 49032cabb2fSBarry Smith if not self.mpi.usingMPIUni: 49132cabb2fSBarry Smith exclude.append('mpiuni') 49232cabb2fSBarry Smith self.copies.extend(self.copytree(self.rootIncludeDir, self.destIncludeDir,exclude = exclude)) 4930ee81e68SLisandro Dalcin self.copies.extend(self.copytree(self.archIncludeDir, self.destIncludeDir)) 4940ee81e68SLisandro Dalcin return 4950ee81e68SLisandro Dalcin 4960ee81e68SLisandro Dalcin def installConf(self): 497ce78bad3SBarry Smith self.copies.extend(self.copytree(self.rootConfDir, self.destConfDir, exclude = ['test.log'])) 498a035e9faSPierre 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'])) 4990ee81e68SLisandro Dalcin return 5000ee81e68SLisandro Dalcin 5010ee81e68SLisandro Dalcin def installBin(self): 502ce78bad3SBarry Smith exclude = ['bib2html','doc2lt','doctext','mapnames', 'pstogif','pstoxbm','tohtml'] 50332cabb2fSBarry Smith self.copies.extend(self.copytree(self.archBinDir, self.destBinDir, exclude = exclude )) 50432cabb2fSBarry Smith exclude = ['maint'] 50532cabb2fSBarry Smith if not self.mpi.usingMPIUni: 50632cabb2fSBarry Smith exclude.append('petsc-mpiexec.uni') 50732cabb2fSBarry Smith self.setCompilers.pushLanguage('C') 508011f288aSSatish Balay if self.setCompilers.getCompiler().find('win32fe') < 0: 50932cabb2fSBarry Smith exclude.append('win32fe') 51032cabb2fSBarry Smith self.setCompilers.popLanguage() 51132cabb2fSBarry Smith self.copies.extend(self.copytree(self.rootBinDir, self.destBinDir, exclude = exclude )) 5120ee81e68SLisandro Dalcin return 5130ee81e68SLisandro Dalcin 5140ee81e68SLisandro Dalcin def installShare(self): 51523abae74SSatish Balay if self.argDB['no-examples']: exclude = ['datafiles'] 51623abae74SSatish Balay else: exclude = [] 51723abae74SSatish Balay self.copies.extend(self.copytree(self.rootShareDir, self.destShareDir, exclude=exclude)) 518c173c275SScott Kruger examplesdir=os.path.join(self.destShareDir,'petsc','examples') 519c173c275SScott Kruger if os.path.exists(examplesdir): 520c173c275SScott Kruger shutil.rmtree(examplesdir) 521c173c275SScott Kruger os.mkdir(examplesdir) 52279eaf171SScott Kruger os.mkdir(os.path.join(examplesdir,'src')) 523c173c275SScott Kruger self.copyConfig(self.rootDir,examplesdir) 524fad83eadSPatrick Sanan if not self.argDB['no-examples']: 525fad83eadSPatrick Sanan self.copyExamples(self.rootSrcDir,os.path.join(examplesdir,'src')) 526c173c275SScott Kruger self.fixExamplesMakefile(os.path.join(examplesdir,'gmakefile.test')) 5270ee81e68SLisandro Dalcin return 5280ee81e68SLisandro Dalcin 5290ee81e68SLisandro Dalcin def copyLib(self, src, dst): 5300ee81e68SLisandro Dalcin '''Run ranlib on the destination library if it is an archive. Also run install_name_tool on dylib on Mac''' 5310ee81e68SLisandro Dalcin # Symlinks (assumed local) are recreated at dst 5320ee81e68SLisandro Dalcin if os.path.islink(src): 5330ee81e68SLisandro Dalcin linkto = os.readlink(src) 5340ee81e68SLisandro Dalcin try: 5350ee81e68SLisandro Dalcin os.remove(dst) # In case it already exists 5360ee81e68SLisandro Dalcin except OSError: 5370ee81e68SLisandro Dalcin pass 5380ee81e68SLisandro Dalcin os.symlink(linkto, dst) 5390ee81e68SLisandro Dalcin return 5400ee81e68SLisandro Dalcin shutil.copy2(src, dst) 541011f288aSSatish Balay if self.setCompilers.getCompiler().find('win32fe') < 0 and os.path.splitext(dst)[1] == '.'+self.arLibSuffix: 542abf72cf0SSatish Balay import shlex 543abf72cf0SSatish Balay self.executeShellCommand(shlex.split(self.ranlib) + [dst]) 544c9e802c5SMin RK if os.path.splitext(dst)[1] == '.dylib' and shutil.which('otool') and shutil.which('install_name_tool'): 545793d7be8SSatish Balay [output,err,flg] = self.executeShellCommand(['otool', '-D', src]) 546af2c601bSBarry Smith oldname = output[output.find("\n")+1:] 547d4c3e6c5SSatish Balay installName = oldname.replace(os.path.realpath(self.archDir), self.installDir) 548793d7be8SSatish Balay self.executeShellCommand(['install_name_tool', '-id', installName, dst]) 5490ee81e68SLisandro Dalcin # preserve the original timestamps - so that the .a vs .so time order is preserved 5500ee81e68SLisandro Dalcin shutil.copystat(src,dst) 5510ee81e68SLisandro Dalcin return 5520ee81e68SLisandro Dalcin 5530ee81e68SLisandro Dalcin def installLib(self): 55432cabb2fSBarry Smith self.copies.extend(self.copytree(self.archLibDir, self.destLibDir, copyFunc = self.copyLib, exclude = ['.DIR'],recurse = 0)) 55532cabb2fSBarry 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)) 5560ee81e68SLisandro Dalcin return 5570ee81e68SLisandro Dalcin 5580ee81e68SLisandro Dalcin def outputInstallDone(self): 5595b4fc442SVaclav Hapla from config.packages.make import getMakeUserPath 5605b6bfdb9SJed Brown print('''\ 5610ee81e68SLisandro Dalcin==================================== 562*a2dd8f59SBarry SmithTo check if the libraries are working do (in current directory): 5635b4fc442SVaclav Hapla%s PETSC_DIR=%s PETSC_ARCH="" check 5640ee81e68SLisandro Dalcin====================================\ 5655b4fc442SVaclav Hapla''' % (getMakeUserPath(self.arch), self.installDir)) 5660ee81e68SLisandro Dalcin return 5670ee81e68SLisandro Dalcin 5680ee81e68SLisandro Dalcin def outputDestDirDone(self): 5695b6bfdb9SJed Brown print('''\ 5700ee81e68SLisandro Dalcin==================================== 5710ee81e68SLisandro DalcinCopy to DESTDIR %s is now complete. 5720ee81e68SLisandro DalcinBefore use - please copy/install over to specified prefix: %s 5730ee81e68SLisandro Dalcin====================================\ 5745b6bfdb9SJed Brown''' % (self.destDir,self.installDir)) 5750ee81e68SLisandro Dalcin return 5760ee81e68SLisandro Dalcin 5770ee81e68SLisandro Dalcin def runsetup(self): 5780ee81e68SLisandro Dalcin self.setup() 5790ee81e68SLisandro Dalcin self.setupDirectories() 5806e8294f6SStefano Zampini self.setupBuild() 5810ee81e68SLisandro Dalcin self.checkPrefix() 5820ee81e68SLisandro Dalcin self.checkDestdir() 5830ee81e68SLisandro Dalcin return 5840ee81e68SLisandro Dalcin 5850ee81e68SLisandro Dalcin def runcopy(self): 5860ee81e68SLisandro Dalcin if self.destDir == self.installDir: 5875b6bfdb9SJed Brown print('*** Installing PETSc at prefix location:',self.destDir, ' ***') 5880ee81e68SLisandro Dalcin else: 5895b6bfdb9SJed Brown print('*** Copying PETSc to DESTDIR location:',self.destDir, ' ***') 5900ee81e68SLisandro Dalcin if not os.path.exists(self.destDir): 5910ee81e68SLisandro Dalcin try: 5920ee81e68SLisandro Dalcin os.makedirs(self.destDir) 5930ee81e68SLisandro Dalcin except: 5945b6bfdb9SJed Brown print('********************************************************************') 5955b6bfdb9SJed Brown print('Unable to create', self.destDir, 'Perhaps you need to do "sudo make install"') 5965b6bfdb9SJed Brown print('********************************************************************') 5970ee81e68SLisandro Dalcin sys.exit(1) 5980ee81e68SLisandro Dalcin self.installIncludes() 5990ee81e68SLisandro Dalcin self.installConf() 6000ee81e68SLisandro Dalcin self.installBin() 6010ee81e68SLisandro Dalcin self.installLib() 6020ee81e68SLisandro Dalcin self.installShare() 6035ee53db2SLisandro Dalcin self.createUninstaller() 6040ee81e68SLisandro Dalcin return 6050ee81e68SLisandro Dalcin 6060ee81e68SLisandro Dalcin def runfix(self): 6070ee81e68SLisandro Dalcin self.fixConf() 6086e8294f6SStefano Zampini if self.using_build_backend: 6095ee53db2SLisandro Dalcin self.fixPythonWheel() 6100ee81e68SLisandro Dalcin return 6110ee81e68SLisandro Dalcin 6120ee81e68SLisandro Dalcin def rundone(self): 6130ee81e68SLisandro Dalcin if self.destDir == self.installDir: 6140ee81e68SLisandro Dalcin self.outputInstallDone() 6150ee81e68SLisandro Dalcin else: 6160ee81e68SLisandro Dalcin self.outputDestDirDone() 6170ee81e68SLisandro Dalcin return 6180ee81e68SLisandro Dalcin 6190ee81e68SLisandro Dalcin def run(self): 6200ee81e68SLisandro Dalcin self.runsetup() 6210ee81e68SLisandro Dalcin self.runcopy() 6220ee81e68SLisandro Dalcin self.runfix() 6230ee81e68SLisandro Dalcin self.rundone() 6240ee81e68SLisandro Dalcin return 6250ee81e68SLisandro Dalcin 6260ee81e68SLisandro Dalcinif __name__ == '__main__': 6270ee81e68SLisandro Dalcin Installer(sys.argv[1:]).run() 6280ee81e68SLisandro Dalcin # temporary hack - delete log files created by BuildSystem - when 'sudo make install' is invoked 62903e6d329SSatish Balay delfiles=['RDict.db','RDict.log','buildsystem.log','default.log','buildsystem.log.bkp','default.log.bkp'] 6300ee81e68SLisandro Dalcin for delfile in delfiles: 6310ee81e68SLisandro Dalcin if os.path.exists(delfile) and (os.stat(delfile).st_uid==0): 6320ee81e68SLisandro Dalcin os.remove(delfile) 633