xref: /petsc/config/PETSc/options/arch.py (revision 2475b7ca256cea2a4b7cbf2d8babcda14e5fa36e)
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 setNativeArchitecture(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    self.nativeArch = arch
41    return
42
43  def configureArchitecture(self):
44    '''Checks PETSC_ARCH and sets if not set'''
45    # Warn if PETSC_ARCH doesnt match env variable
46    if 'PETSC_ARCH' in self.framework.argDB and 'PETSC_ARCH' in os.environ and self.framework.argDB['PETSC_ARCH'] != os.environ['PETSC_ARCH']:
47      self.logPrintBox('''\
48Warning: PETSC_ARCH from environment does not match command-line or name of script.
49Warning: Using from command-line or name of script: %s, ignoring environment: %s''' % (str(self.framework.argDB['PETSC_ARCH']), str(os.environ['PETSC_ARCH'])))
50      os.environ['PETSC_ARCH'] = self.framework.argDB['PETSC_ARCH']
51    if 'with-petsc-arch' in self.framework.argDB:
52      self.arch = self.framework.argDB['with-petsc-arch']
53      msg = 'option -with-petsc-arch='+str(self.arch)
54    elif 'PETSC_ARCH' in self.framework.argDB:
55      self.arch = self.framework.argDB['PETSC_ARCH']
56      msg = 'option PETSC_ARCH='+str(self.arch)
57    elif 'PETSC_ARCH' in os.environ:
58      self.arch = os.environ['PETSC_ARCH']
59      msg = 'environment variable PETSC_ARCH='+str(self.arch)
60    else:
61      self.arch = self.nativeArch
62    if self.arch.find('/') >= 0 or self.arch.find('\\') >= 0:
63      raise RuntimeError('PETSC_ARCH should not contain path characters, but you have specified with '+msg)
64    if self.arch.startswith('-'):
65      raise RuntimeError('PETSC_ARCH should not start with "-", but you have specified with '+msg)
66    if self.arch.startswith('.'):
67      raise RuntimeError('PETSC_ARCH should not start with ".", but you have specified with '+msg)
68    if not len(self.arch):
69      raise RuntimeError('PETSC_ARCH cannot be empty string. Use a valid string or do not set one. Currently set with '+msg)
70    self.archBase = re.sub(r'^(\w+)[-_]?.*$', r'\1', self.arch)
71    return
72
73  def makeDependency(self,hash,hashfile):
74    '''Deletes the current hashfile and saves the hashfile name and its value in framework so that'''
75    '''framework.Configure can create the file upon success of configure'''
76    import os
77    if hash:
78      self.framework.hash = hash
79      self.framework.hashfile = hashfile
80    self.logPrint('Deleting configure hash file: '+hashfile)
81    try:
82      os.remove(hashfile)
83    except:
84      self.logPrint('Unable to delete configure hash file: '+hashfile)
85      return
86    self.logPrint('Deleted configure hash file: '+hashfile)
87
88  def checkDependency(self):
89    '''Checks if configure needs to be run'''
90    '''Checks if files in config have changed, the command line options have changed or the PATH has changed'''
91    import os
92    import sys
93    import hashlib
94    hashfile = os.path.join(self.arch,'lib','petsc','conf','configure-hash')
95    args = sorted(set(filter(lambda x: not (x.startswith('PETSC_ARCH') or x == '--force'),sys.argv[1:])))
96    hash = 'args:\n' + '\n'.join('    '+a for a in args) + '\n'
97    hash += 'PATH=' + os.environ.get('PATH', '') + '\n'
98    try:
99      for root, dirs, files in os.walk('config'):
100        if root == 'config':
101          dirs.remove('examples')
102        for f in files:
103          if not f.endswith('.py') or f.startswith('.') or f.startswith('#'):
104            continue
105          fname = os.path.join(root, f)
106          with open(fname,'rb') as f:
107            hash += hashlib.sha256(f.read()).hexdigest() + '  ' + fname + '\n'
108    except:
109      self.logPrint('Error generating file list/hash from config directory for configure hash, forcing new configuration')
110      self.makeDependency(None,hashfile)
111      return
112    if self.argDB['force']:
113      self.makeDependency(hash,hashfile)
114      return
115    a = ''
116    try:
117      with open(hashfile, 'r') as f:
118        a = f.read()
119    except:
120      # no previous record so write current hash
121      self.makeDependency(hash,hashfile)
122      return
123    if a == hash:
124      self.logPrint('configure hash file: '+hashfile+' matches; no need to run configure.')
125      print('Your configure options and state has not changed; no need to run configure')
126      print('However you can force a configure run using the option: --force')
127      sys.exit()
128    self.makeDependency(hash,hashfile)
129    self.logPrint('configure hash file: '+hashfile+' does not match\n'+a+'\n---\n'+hash+'\n need to run configure')
130
131  def configure(self):
132    self.executeTest(self.setNativeArchitecture)
133    self.executeTest(self.configureArchitecture)
134    # required by top-level configure.py
135    self.framework.arch = self.arch
136    self.checkDependency()
137    return
138