xref: /petsc/config/PETSc/options/arch.py (revision fc8a9adeb7fcdc98711d755fa2dc544ddccf0f3e)
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