1import config.package
2import os
3
4def noCheck(command, status, output, error):
5  ''' Do no check result'''
6  return
7
8class Configure(config.package.GNUPackage):
9  def __init__(self, framework):
10    config.package.GNUPackage.__init__(self, framework)
11    self.minversion        = '1.1.26'
12    self.gitcommit         = 'v'+self.minversion+'-p1'
13    self.download          = ['git://https://bitbucket.org/petsc/pkg-sowing.git','https://bitbucket.org/petsc/pkg-sowing/get/'+self.gitcommit+'.tar.gz']
14    self.downloaddirnames  = ['petsc-pkg-sowing']
15    self.complex           = 1
16    self.downloadonWindows = 1
17    self.publicInstall     = 0  # always install in PETSC_DIR/PETSC_ARCH (not --prefix) since this is not used by users
18    self.parallelMake      = 0  # sowing does not support make -j np
19    self.executablename    = 'bfort'
20    return
21
22  def setupHelp(self, help):
23    import nargs
24    config.package.GNUPackage.setupHelp(self, help)
25    help.addArgument('SOWING', '-download-sowing-cc=<prog>',                     nargs.Arg(None, None, 'C compiler for sowing configure'))
26    help.addArgument('SOWING', '-download-sowing-cxx=<prog>',                    nargs.Arg(None, None, 'CXX compiler for sowing configure'))
27    help.addArgument('SOWING', '-download-sowing-cpp=<prog>',                    nargs.Arg(None, None, 'CPP for sowing configure'))
28    help.addArgument('SOWING', '-download-sowing-cxxpp=<prog>',                  nargs.Arg(None, None, 'CXX CPP for sowing configure'))
29    return
30
31  def setupDependencies(self, framework):
32    config.package.GNUPackage.setupDependencies(self, framework)
33    self.petscclone = framework.require('PETSc.options.petscclone', None)
34    return
35
36  def formGNUConfigureArgs(self):
37    '''Does not use the standard arguments at all since this does not use the MPI compilers etc
38       Sowing will chose its own compilers if they are not provided explicitly here'''
39    args = ['--prefix='+self.installDir]
40    if 'download-sowing-cc' in self.argDB and self.argDB['download-sowing-cc']:
41      args.append('CC="'+self.argDB['download-sowing-cc']+'"')
42    if 'download-sowing-cxx' in self.argDB and self.argDB['download-sowing-cxx']:
43      args.append('CXX="'+self.argDB['download-sowing-cxx']+'"')
44    if 'download-sowing-cpp' in self.argDB and self.argDB['download-sowing-cpp']:
45      args.append('CPP="'+self.argDB['download-sowing-cpp']+'"')
46    if 'download-sowing-cxxpp' in self.argDB and self.argDB['download-sowing-cxxpp']:
47      args.append('CXXPP="'+self.argDB['download-sowing-cxxpp']+'"')
48    return args
49
50  def alternateConfigureLibrary(self):
51    self.checkDownload()
52
53  def checkBfortVersion(self):
54    try:
55      import re
56      (output, error, status) = config.base.Configure.executeShellCommand(self.bfort+' -version', checkCommand=noCheck, log = self.log)
57      ver = re.compile('bfort \(sowing\) release ([0-9]+).([0-9]+).([0-9]+)').match(output)
58      foundversion = tuple(map(int,ver.groups()))
59      self.foundversion = ".".join(map(str,foundversion))
60    except RuntimeError as e:
61      self.log.write(self.bfort+' version check failed: '+str(e)+'\n')
62      return
63    version = tuple(map(int, self.minversion.split('.')))
64    if foundversion < version:
65      raise RuntimeError(self.bfort+' version '+".".join(map(str,foundversion))+' is older than required '+self.minversion+'. Perhaps a stale install of sowing?')
66    return
67
68  def configure(self):
69    if ('with-sowing' in self.framework.clArgDB and not self.argDB['with-sowing']):
70      if hasattr(self.compilers, 'FC') and self.framework.argDB['with-fortran-bindings'] and self.petscclone.isClone:
71        raise RuntimeError('Cannot use --with-sowing=0 if using Fortran (bindings) and git repository for PETSc')
72      self.logPrint("Not checking sowing on user request of --with-sowing=0\n")
73      return
74
75    if self.framework.batchBodies:
76      self.logPrint('In --with-batch mode with outstanding batch tests to be made; hence skipping sowing for this configure')
77      return
78
79    if (self.petscclone.isClone and hasattr(self.compilers, 'FC') and self.framework.argDB['with-fortran-bindings']) or ('download-sowing' in self.framework.clArgDB and self.argDB['download-sowing']):
80      self.logPrint('PETSc clone, checking for Sowing \n')
81      self.getExecutable('pdflatex', getFullPath = 1)
82
83      if 'with-sowing-dir' in self.framework.clArgDB and self.argDB['with-sowing-dir']:
84        installDir = os.path.join(self.argDB['with-sowing-dir'],'bin')
85
86        self.getExecutable('bfort',    path=installDir, getFullPath = 1)
87        self.getExecutable('doctext',  path=installDir, getFullPath = 1)
88        self.getExecutable('mapnames', path=installDir, getFullPath = 1)
89        self.getExecutable('bib2html', path=installDir, getFullPath = 1)
90        if hasattr(self, 'bfort'):
91          self.logPrint('Found bfort in user provided directory, not installing sowing')
92          self.found = 1
93        else:
94          raise RuntimeError("You passed --with-sowing-dir='+installDir+' but it does not contain sowing's bfort")
95
96      else:
97        if not self.argDB['download-sowing']:
98          self.getExecutable('bfort', getFullPath = 1)
99          self.getExecutable('doctext', getFullPath = 1)
100          self.getExecutable('mapnames', getFullPath = 1)
101          self.getExecutable('bib2html', getFullPath = 1)
102
103        if hasattr(self, 'bfort'):
104          self.logPrint('Found bfort, not installing sowing')
105          self.found = 1
106        else:
107          self.logPrint('Bfort not found. Installing sowing for FortranStubs')
108          if (not self.argDB['download-sowing']):  self.argDB['download-sowing'] = 1
109          #check cygwin has g++
110          if os.path.exists('/usr/bin/cygcheck.exe') and not os.path.exists('/usr/bin/g++.exe'):
111            raise RuntimeError('Error! sowing on windows requires cygwin/g++. Please install it with cygwin setup.exe')
112          config.package.GNUPackage.configure(self)
113          installDir = os.path.join(self.installDir,'bin')
114          self.getExecutable('bfort',    path=installDir, getFullPath = 1)
115          self.getExecutable('doctext',  path=installDir, getFullPath = 1)
116          self.getExecutable('mapnames', path=installDir, getFullPath = 1)
117          self.getExecutable('bib2html', path=installDir, getFullPath = 1)
118          self.found = 1
119          if not hasattr(self,'bfort'): raise RuntimeError('Unable to locate bfort (part of sowing) in its expected location in '+installDir+'\n\
120Perhaps the installation has been corrupted or changed, remove the directory '+os.path.join(self.petscdir.dir,self.arch)+'\n\
121and run configure again\n')
122
123      self.checkBfortVersion()
124      self.buildFortranStubs()
125    else:
126      self.logPrint("Not a clone of PETSc or no Fortran compiler or fortran-bindings disabled, don't need Sowing\n")
127    return
128
129  def buildFortranStubs(self):
130    if hasattr(self.compilers, 'FC'):
131      if self.argDB['with-batch'] and not hasattr(self,'bfort'):
132        self.logPrintBox('Batch build that could not generate bfort, skipping generating Fortran stubs\n \
133                          you will need to copy them from some other system (src/fortran/auto)')
134      else:
135        self.logWrite('           Running '+self.bfort+' to generate fortran stubs\n')
136        try:
137          import os,sys
138          sys.path.insert(0, os.path.abspath(os.path.join('lib','petsc','bin','maint')))
139          import generatefortranstubs
140          del sys.path[0]
141          generatefortranstubs.main(self.petscdir.dir, self.bfort, self.petscdir.dir,0)
142          if self.fortran.fortranIsF90:
143            generatefortranstubs.processf90interfaces(self.petscdir.dir,0)
144          self.framework.actions.addArgument('PETSc', 'File creation', 'Generated Fortran stubs')
145        except RuntimeError as e:
146          raise RuntimeError('*******Error generating Fortran stubs: '+str(e)+'*******\n')
147    return
148