1import config.base 2import os 3import re 4 5class Configure(config.base.Configure): 6 def __init__(self, framework): 7 config.base.Configure.__init__(self, framework) 8 self.headerPrefix = 'PETSC' 9 self.substPrefix = 'PETSC' 10 return 11 12 def __str1__(self): 13 if not hasattr(self, 'arch'): 14 return '' 15 desc = ['PETSc:'] 16 desc.append(' PETSC_ARCH: '+str(self.arch)) 17 return '\n'.join(desc)+'\n' 18 19 def setupHelp(self, help): 20 import nargs 21 help.addArgument('PETSc', '-PETSC_ARCH=<string>', nargs.Arg(None, None, 'The configuration name')) 22 help.addArgument('PETSc', '-with-petsc-arch=<string>',nargs.Arg(None, None, 'The configuration name')) 23 help.addArgument('PETSc', '-force=<bool>', nargs.ArgBool(None, 0, 'Bypass configure hash caching, and run to completion')) 24 return 25 26 def setupDependencies(self, framework): 27 self.sourceControl = framework.require('config.sourceControl',self) 28 self.petscdir = framework.require('PETSc.options.petscdir', self) 29 return 30 31 def createArchitecture(self): 32 import sys 33 arch = 'arch-' + sys.platform.replace('cygwin','mswin') 34 # use opt/debug, c/c++ tags.s 35 arch+= '-'+self.framework.argDB['with-clanguage'].lower().replace('+','x') 36 if self.framework.argDB['with-debugging']: 37 arch += '-debug' 38 else: 39 arch += '-opt' 40 return arch 41 42 def configureArchitecture(self): 43 '''Checks PETSC_ARCH and sets if not set''' 44 # Warn if PETSC_ARCH doesnt match env variable 45 if 'PETSC_ARCH' in self.framework.argDB and 'PETSC_ARCH' in os.environ and self.framework.argDB['PETSC_ARCH'] != os.environ['PETSC_ARCH']: 46 self.logPrintBox('''\ 47Warning: PETSC_ARCH from environment does not match command-line or name of script. 48Warning: Using from command-line or name of script: %s, ignoring environment: %s''' % (str(self.framework.argDB['PETSC_ARCH']), str(os.environ['PETSC_ARCH']))) 49 os.environ['PETSC_ARCH'] = self.framework.argDB['PETSC_ARCH'] 50 if 'with-petsc-arch' in self.framework.argDB: 51 self.arch = self.framework.argDB['with-petsc-arch'] 52 msg = 'option -with-petsc-arch='+str(self.arch) 53 elif 'PETSC_ARCH' in self.framework.argDB: 54 self.arch = self.framework.argDB['PETSC_ARCH'] 55 msg = 'option PETSC_ARCH='+str(self.arch) 56 elif 'PETSC_ARCH' in os.environ: 57 self.arch = os.environ['PETSC_ARCH'] 58 msg = 'environment variable PETSC_ARCH='+str(self.arch) 59 else: 60 self.arch = self.createArchitecture() 61 if self.arch.find('/') >= 0 or self.arch.find('\\') >= 0: 62 raise RuntimeError('PETSC_ARCH should not contain path characters, but you have specified with '+msg) 63 if self.arch.startswith('-'): 64 raise RuntimeError('PETSC_ARCH should not start with "-", but you have specified with '+msg) 65 if self.arch.startswith('.'): 66 raise RuntimeError('PETSC_ARCH should not start with ".", but you have specified with '+msg) 67 if not len(self.arch): 68 raise RuntimeError('PETSC_ARCH cannot be empty string. Use a valid string or do not set one. Currently set with '+msg) 69 self.archBase = re.sub(r'^(\w+)[-_]?.*$', r'\1', self.arch) 70 return 71 72 def makeDependency(self,hash): 73 import os 74 try: 75 os.makedirs(os.path.join(self.arch,'lib','petsc','conf')) 76 except: 77 pass 78 try: 79 with open(os.path.join(self.arch,'lib','petsc','conf','configure-hash'), 'w') as f: 80 f.write(hash) 81 except: 82 self.logPrint('Unable to make configure hash file: '+os.path.join(self.arch,'lib','petsc','conf','configure-hash')) 83 return 84 self.logPrint('Wrote configure hash file: '+os.path.join(self.arch,'lib','petsc','conf','configure-hash')) 85 86 def checkDependency(self): 87 '''Checks if configure needs to be run''' 88 '''Checks if files in config have changed, the command line options have changed or the PATH has changed''' 89 import os 90 import sys 91 import hashlib 92 args = sorted(set(filter(lambda x: not (x.startswith('PETSC_ARCH') or x == '--force'),sys.argv[1:]))) 93 hash = 'args:\n' + '\n'.join(' '+a for a in args) + '\n' 94 hash += 'PATH=' + os.environ.get('PATH', '') + '\n' 95 try: 96 for root, dirs, files in os.walk('config'): 97 if root == 'config': 98 dirs.remove('examples') 99 for f in files: 100 if not f.endswith('.py') or f.startswith('.') or f.startswith('#'): 101 continue 102 fname = os.path.join(root, f) 103 with open(fname,'rb') as f: 104 hash += hashlib.sha256(f.read()).hexdigest() + ' ' + fname + '\n' 105 except: 106 self.logPrint('Error generating file list/hash from config directory for configure hash, forcing new configuration') 107 return 108 if self.argDB['force']: 109 self.makeDependency(hash) 110 return 111 a = '' 112 try: 113 with open(os.path.join(self.arch,'lib','petsc','conf','configure-hash'), 'r') as f: 114 a = f.read() 115 except: 116 # no previous record so write current hash 117 self.makeDependency(hash) 118 return 119 if a == hash: 120 self.logPrint('configure hash file: '+os.path.join(self.arch,'lib','petsc','conf','configure-hash')+' matches; no need to run configure.') 121 print('Your configure options and state has not changed; no need to run configure') 122 print('However you can force a configure run using the option: --force') 123 sys.exit() 124 self.makeDependency(hash) 125 self.logPrint('configure hash file: '+os.path.join(self.arch,'lib','petsc','conf','configure-hash')+' does not match\n'+a+'\n---\n'+hash+'\n need to run configure') 126 127 def configure(self): 128 self.executeTest(self.configureArchitecture) 129 # required by top-level configure.py 130 self.framework.arch = self.arch 131 self.checkDependency() 132 return 133