xref: /petsc/config/PETSc/options/arch.py (revision 00549fcef0b62cf4c093534a63702a52efe2ea6e)
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,hashfile):
73    '''Deletes the current hashfile and saves the hashfile name and its value in framework so that'''
74    '''framework.Configure can create the file upon success of configure'''
75    import os
76    if hash:
77      self.framework.hash = hash
78      self.framework.hashfile = hashfile
79    self.logPrint('Deleting configure hash file: '+hashfile)
80    try:
81      os.remove(hashfile)
82    except:
83      self.logPrint('Unable to delete configure hash file: '+hashfile)
84      return
85    self.logPrint('Deleted configure hash file: '+hashfile)
86
87  def checkDependency(self):
88    '''Checks if configure needs to be run'''
89    '''Checks if files in config have changed, the command line options have changed or the PATH has changed'''
90    import os
91    import sys
92    import hashlib
93    hashfile = os.path.join(self.arch,'lib','petsc','conf','configure-hash')
94    args = sorted(set(filter(lambda x: not (x.startswith('PETSC_ARCH') or x == '--force'),sys.argv[1:])))
95    hash = 'args:\n' + '\n'.join('    '+a for a in args) + '\n'
96    hash += 'PATH=' + os.environ.get('PATH', '') + '\n'
97    try:
98      for root, dirs, files in os.walk('config'):
99        if root == 'config':
100          dirs.remove('examples')
101        for f in files:
102          if not f.endswith('.py') or f.startswith('.') or f.startswith('#'):
103            continue
104          fname = os.path.join(root, f)
105          with open(fname,'rb') as f:
106            hash += hashlib.sha256(f.read()).hexdigest() + '  ' + fname + '\n'
107    except:
108      self.logPrint('Error generating file list/hash from config directory for configure hash, forcing new configuration')
109      self.makeDependency(None,hashfile)
110      return
111    if self.argDB['force']:
112      self.makeDependency(hash,hashfile)
113      return
114    a = ''
115    try:
116      with open(hashfile, 'r') as f:
117        a = f.read()
118    except:
119      # no previous record so write current hash
120      self.makeDependency(hash,hashfile)
121      return
122    if a == hash:
123      self.logPrint('configure hash file: '+hashfile+' matches; no need to run configure.')
124      print('Your configure options and state has not changed; no need to run configure')
125      print('However you can force a configure run using the option: --force')
126      sys.exit()
127    self.makeDependency(hash,hashfile)
128    self.logPrint('configure hash file: '+hashfile+' does not match\n'+a+'\n---\n'+hash+'\n need to run configure')
129
130  def configure(self):
131    self.executeTest(self.configureArchitecture)
132    # required by top-level configure.py
133    self.framework.arch = self.arch
134    self.checkDependency()
135    return
136