xref: /petsc/config/PETSc/options/arch.py (revision dd328ec0ac57af7b498731da5d38edef20911fc9)
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 = list(filter(lambda x: not (x.startswith('PETSC_ARCH') or x == '--force'),sys.argv[1:]))
93    args.sort()
94    hash = str(args) + '\n'
95    try: hash += os.environ['PATH'] + '\n'
96    except: pass
97    try:
98      for root, dirs, files in os.walk('config'):
99        for f in files:
100          if f.endswith('.pyc') or f.endswith('~') or f.startswith('.') or f.startswith('#'): continue
101          fname = os.path.join(root,f)
102          md5sum = hashlib.md5(open(fname,'rb').read()).hexdigest()
103          hash += md5sum + ' '+ fname + '\n'
104    except:
105      self.logPrint('Error generating file list/md5 from config directory for configure hash, forcing new configuration')
106      return
107    if self.argDB['force']:
108      self.makeDependency(hash)
109      return
110    a = ''
111    try:
112      with open(os.path.join(self.arch,'lib','petsc','conf','configure-hash'), 'r') as f:
113        a = f.read()
114    except:
115      # no previous record so write current hash
116      self.makeDependency(hash)
117      return
118    if a == hash:
119      self.logPrint('configure hash file: '+os.path.join(self.arch,'lib','petsc','conf','configure-hash')+' matches; no need to run configure.')
120      print('Your configure options and state has not changed; no need to run configure')
121      print('However you can force a configure run using the option: --force')
122      sys.exit()
123    self.makeDependency(hash)
124    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')
125
126  def configure(self):
127    self.executeTest(self.configureArchitecture)
128    # required by top-level configure.py
129    self.framework.arch = self.arch
130    self.checkDependency()
131    return
132