xref: /petsc/config/PETSc/options/arch.py (revision f83574080d258f3d17cc42114b176092766ffb60)
19d310bb7SBarry Smithimport config.base
29d310bb7SBarry Smithimport os
39d310bb7SBarry Smithimport re
49d310bb7SBarry Smith
59d310bb7SBarry Smithclass Configure(config.base.Configure):
69d310bb7SBarry Smith  def __init__(self, framework):
79d310bb7SBarry Smith    config.base.Configure.__init__(self, framework)
89d310bb7SBarry Smith    self.headerPrefix = 'PETSC'
99d310bb7SBarry Smith    self.substPrefix  = 'PETSC'
109d310bb7SBarry Smith    return
119d310bb7SBarry Smith
129d310bb7SBarry Smith  def __str1__(self):
139d310bb7SBarry Smith    if not hasattr(self, 'arch'):
149d310bb7SBarry Smith      return ''
159d310bb7SBarry Smith    desc = ['PETSc:']
169d310bb7SBarry Smith    desc.append('  PETSC_ARCH: '+str(self.arch))
179d310bb7SBarry Smith    return '\n'.join(desc)+'\n'
189d310bb7SBarry Smith
199d310bb7SBarry Smith  def setupHelp(self, help):
209d310bb7SBarry Smith    import nargs
219d310bb7SBarry Smith    help.addArgument('PETSc', '-PETSC_ARCH=<string>',     nargs.Arg(None, None, 'The configuration name'))
229d310bb7SBarry Smith    help.addArgument('PETSc', '-with-petsc-arch=<string>',nargs.Arg(None, None, 'The configuration name'))
23dd328ec0SBarry Smith    help.addArgument('PETSc', '-force=<bool>',            nargs.ArgBool(None, 0, 'Bypass configure hash caching, and run to completion'))
24dd328ec0SBarry Smith    return
25dd328ec0SBarry Smith
26dd328ec0SBarry Smith  def setupDependencies(self, framework):
27dd328ec0SBarry Smith    self.sourceControl = framework.require('config.sourceControl',self)
28dd328ec0SBarry Smith    self.petscdir = framework.require('PETSc.options.petscdir', self)
299d310bb7SBarry Smith    return
309d310bb7SBarry Smith
3170211a5bSSatish Balay  def createArchitecture(self):
3270211a5bSSatish Balay    import sys
3370211a5bSSatish Balay    arch = 'arch-' + sys.platform.replace('cygwin','mswin')
3470211a5bSSatish Balay    # use opt/debug, c/c++ tags.s
3570211a5bSSatish Balay    arch+= '-'+self.framework.argDB['with-clanguage'].lower().replace('+','x')
3670211a5bSSatish Balay    if self.framework.argDB['with-debugging']:
3770211a5bSSatish Balay      arch += '-debug'
3870211a5bSSatish Balay    else:
3970211a5bSSatish Balay      arch += '-opt'
4070211a5bSSatish Balay    return arch
4170211a5bSSatish Balay
429d310bb7SBarry Smith  def configureArchitecture(self):
439d310bb7SBarry Smith    '''Checks PETSC_ARCH and sets if not set'''
449d310bb7SBarry Smith    # Warn if PETSC_ARCH doesnt match env variable
459d310bb7SBarry Smith    if 'PETSC_ARCH' in self.framework.argDB and 'PETSC_ARCH' in os.environ and self.framework.argDB['PETSC_ARCH'] != os.environ['PETSC_ARCH']:
469d310bb7SBarry Smith      self.logPrintBox('''\
479d310bb7SBarry SmithWarning: PETSC_ARCH from environment does not match command-line or name of script.
489d310bb7SBarry SmithWarning: Using from command-line or name of script: %s, ignoring environment: %s''' % (str(self.framework.argDB['PETSC_ARCH']), str(os.environ['PETSC_ARCH'])))
4957ea55fdSJed Brown      os.environ['PETSC_ARCH'] = self.framework.argDB['PETSC_ARCH']
509d310bb7SBarry Smith    if 'with-petsc-arch' in self.framework.argDB:
519d310bb7SBarry Smith      self.arch = self.framework.argDB['with-petsc-arch']
5270211a5bSSatish Balay      msg = 'option -with-petsc-arch='+str(self.arch)
539d310bb7SBarry Smith    elif 'PETSC_ARCH' in self.framework.argDB:
549d310bb7SBarry Smith      self.arch = self.framework.argDB['PETSC_ARCH']
5570211a5bSSatish Balay      msg = 'option PETSC_ARCH='+str(self.arch)
5670211a5bSSatish Balay    elif 'PETSC_ARCH' in os.environ:
579d310bb7SBarry Smith      self.arch = os.environ['PETSC_ARCH']
5870211a5bSSatish Balay      msg = 'environment variable PETSC_ARCH='+str(self.arch)
599d310bb7SBarry Smith    else:
6070211a5bSSatish Balay      self.arch = self.createArchitecture()
619d310bb7SBarry Smith    if self.arch.find('/') >= 0 or self.arch.find('\\') >= 0:
6270211a5bSSatish Balay      raise RuntimeError('PETSC_ARCH should not contain path characters, but you have specified with '+msg)
63002ae2c9SLisandro Dalcin    if self.arch.startswith('-'):
6470211a5bSSatish Balay      raise RuntimeError('PETSC_ARCH should not start with "-", but you have specified with '+msg)
6570211a5bSSatish Balay    if self.arch.startswith('.'):
6670211a5bSSatish Balay      raise RuntimeError('PETSC_ARCH should not start with ".", but you have specified with '+msg)
6770211a5bSSatish Balay    if not len(self.arch):
6870211a5bSSatish Balay      raise RuntimeError('PETSC_ARCH cannot be empty string. Use a valid string or do not set one. Currently set with '+msg)
699d310bb7SBarry Smith    self.archBase = re.sub(r'^(\w+)[-_]?.*$', r'\1', self.arch)
709d310bb7SBarry Smith    return
719d310bb7SBarry Smith
72*f8357408SBarry Smith  def makeDependency(self,hash,hashfile):
73*f8357408SBarry Smith    '''Deletes the current hashfile and saves the hashfile name and its value in framework so that'''
74*f8357408SBarry Smith    '''framework.Configure can create the file upon success of configure'''
75dd328ec0SBarry Smith    import os
76*f8357408SBarry Smith    if hash:
77*f8357408SBarry Smith      self.framework.hash = hash
78*f8357408SBarry Smith      self.framework.hashfile = hashfile
79*f8357408SBarry Smith    self.logPrint('Deleting configure hash file: '+hashfile)
80dd328ec0SBarry Smith    try:
81*f8357408SBarry Smith      os.remove(hashfile)
82dd328ec0SBarry Smith    except:
83*f8357408SBarry Smith      self.logPrint('Unable to delete configure hash file: '+hashfile)
84dd328ec0SBarry Smith      return
85*f8357408SBarry Smith    self.logPrint('Deleted configure hash file: '+hashfile)
86dd328ec0SBarry Smith
87dd328ec0SBarry Smith  def checkDependency(self):
88dd328ec0SBarry Smith    '''Checks if configure needs to be run'''
89dd328ec0SBarry Smith    '''Checks if files in config have changed, the command line options have changed or the PATH has changed'''
90dd328ec0SBarry Smith    import os
91dd328ec0SBarry Smith    import sys
92dd328ec0SBarry Smith    import hashlib
93*f8357408SBarry Smith    hashfile = os.path.join(self.arch,'lib','petsc','conf','configure-hash')
94b60faad8SJed Brown    args = sorted(set(filter(lambda x: not (x.startswith('PETSC_ARCH') or x == '--force'),sys.argv[1:])))
95b60faad8SJed Brown    hash = 'args:\n' + '\n'.join('    '+a for a in args) + '\n'
96b60faad8SJed Brown    hash += 'PATH=' + os.environ.get('PATH', '') + '\n'
97dd328ec0SBarry Smith    try:
98dd328ec0SBarry Smith      for root, dirs, files in os.walk('config'):
99b60faad8SJed Brown        if root == 'config':
100b60faad8SJed Brown          dirs.remove('examples')
101dd328ec0SBarry Smith        for f in files:
102b60faad8SJed Brown          if not f.endswith('.py') or f.startswith('.') or f.startswith('#'):
103b60faad8SJed Brown            continue
104dd328ec0SBarry Smith          fname = os.path.join(root, f)
105b60faad8SJed Brown          with open(fname,'rb') as f:
106b60faad8SJed Brown            hash += hashlib.sha256(f.read()).hexdigest() + '  ' + fname + '\n'
107dd328ec0SBarry Smith    except:
108b60faad8SJed Brown      self.logPrint('Error generating file list/hash from config directory for configure hash, forcing new configuration')
109*f8357408SBarry Smith      self.makeDependency(None,hashfile)
110dd328ec0SBarry Smith      return
111dd328ec0SBarry Smith    if self.argDB['force']:
112*f8357408SBarry Smith      self.makeDependency(hash,hashfile)
113dd328ec0SBarry Smith      return
114dd328ec0SBarry Smith    a = ''
115dd328ec0SBarry Smith    try:
116*f8357408SBarry Smith      with open(hashfile, 'r') as f:
117dd328ec0SBarry Smith        a = f.read()
118dd328ec0SBarry Smith    except:
119dd328ec0SBarry Smith      # no previous record so write current hash
120*f8357408SBarry Smith      self.makeDependency(hash,hashfile)
121dd328ec0SBarry Smith      return
122dd328ec0SBarry Smith    if a == hash:
123*f8357408SBarry Smith      self.logPrint('configure hash file: '+hashfile+' matches; no need to run configure.')
124dd328ec0SBarry Smith      print('Your configure options and state has not changed; no need to run configure')
125dd328ec0SBarry Smith      print('However you can force a configure run using the option: --force')
126dd328ec0SBarry Smith      sys.exit()
127*f8357408SBarry Smith    self.makeDependency(hash,hashfile)
128*f8357408SBarry Smith    self.logPrint('configure hash file: '+hashfile+' does not match\n'+a+'\n---\n'+hash+'\n need to run configure')
129dd328ec0SBarry Smith
1309d310bb7SBarry Smith  def configure(self):
1319d310bb7SBarry Smith    self.executeTest(self.configureArchitecture)
1329d310bb7SBarry Smith    # required by top-level configure.py
1339d310bb7SBarry Smith    self.framework.arch = self.arch
134dd328ec0SBarry Smith    self.checkDependency()
1359d310bb7SBarry Smith    return
136