xref: /petsc/config/PETSc/Configure.py (revision d8e4f26e7eadd05aa3d9f3d0f2220b3e914971d9)
1import config.base
2
3import os
4import sys
5import re
6import pickle
7
8class Configure(config.base.Configure):
9  def __init__(self, framework):
10    config.base.Configure.__init__(self, framework)
11    self.headerPrefix = 'PETSC'
12    self.substPrefix  = 'PETSC'
13    self.installed    = 0 # 1 indicates that Configure itself has already compiled and installed PETSc
14    self.found        = 1
15    return
16
17  def __str2__(self):
18    desc = ['  Using GNU make: ' + self.make.make]
19    if not self.installed:
20      desc.append('xxx=========================================================================xxx')
21      desc.append(' Configure stage complete. Now build PETSc libraries with:')
22      desc.append('   %s PETSC_DIR=%s PETSC_ARCH=%s all' % (self.make.make_user, self.petscdir.dir, self.arch.arch))
23      desc.append('xxx=========================================================================xxx')
24    else:
25      desc.append('xxx=========================================================================xxx')
26      desc.append(' Installation complete. You do not need to run make to compile or install the software')
27      desc.append('xxx=========================================================================xxx')
28    return '\n'.join(desc)+'\n'
29
30  def setupHelp(self, help):
31    import nargs
32    help.addArgument('PETSc',  '-prefix=<dir>',                              nargs.Arg(None, '', 'Specifiy location to install PETSc (eg. /usr/local)'))
33    help.addArgument('PETSc',  '-with-prefetch=<bool>',                      nargs.ArgBool(None, 1,'Enable checking for prefetch instructions'))
34    help.addArgument('Windows','-with-windows-graphics=<bool>',              nargs.ArgBool(None, 1,'Enable check for Windows Graphics'))
35    help.addArgument('PETSc', '-with-default-arch=<bool>',                   nargs.ArgBool(None, 1, 'Allow using the last configured arch without setting PETSC_ARCH'))
36    help.addArgument('PETSc','-with-single-library=<bool>',                  nargs.ArgBool(None, 1,'Put all PETSc code into the single -lpetsc library'))
37    help.addArgument('PETSc','-with-fortran-bindings=<bool>',                nargs.ArgBool(None, 1,'Build PETSc fortran bindings in the library and corresponding module files'))
38    help.addArgument('PETSc', '-with-ios=<bool>',                            nargs.ArgBool(None, 0, 'Build an iPhone/iPad version of PETSc library'))
39    help.addArgument('PETSc', '-with-display=<x11display>',                  nargs.Arg(None, '', 'Specifiy DISPLAY env variable for use with matlab test)'))
40    help.addArgument('PETSc', '-with-package-scripts=<pyscripts>',           nargs.ArgFileList(None,None,'Specify configure package scripts for user provided packages'))
41    return
42
43  def registerPythonFile(self,filename,directory):
44    ''' Add a python file to the framework and registers its headerprefix, ... externalpackagedir
45        directory is the directory where the file relative to the BuildSystem or config path in python notation with . '''
46    (utilityName, ext) = os.path.splitext(filename)
47    if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__':
48      if directory: directory = directory+'.'
49      utilityObj                             = self.framework.require(directory+utilityName, self)
50      utilityObj.headerPrefix                = self.headerPrefix
51      utilityObj.archProvider                = self.arch
52      utilityObj.languageProvider            = self.languages
53      utilityObj.installDirProvider          = self.installdir
54      utilityObj.externalPackagesDirProvider = self.externalpackagesdir
55      utilityObj.precisionProvider           = self.scalartypes
56      utilityObj.indexProvider               = self.indexTypes
57      setattr(self, utilityName.lower(), utilityObj)
58      return utilityObj
59    return None
60
61  def setupDependencies(self, framework):
62    config.base.Configure.setupDependencies(self, framework)
63    self.programs      = framework.require('config.programs',           self)
64    self.setCompilers  = framework.require('config.setCompilers',       self)
65    self.compilers     = framework.require('config.compilers',          self)
66    self.arch          = framework.require('PETSc.options.arch',        self.setCompilers)
67    self.petscdir      = framework.require('PETSc.options.petscdir',    self.arch)
68    self.installdir    = framework.require('PETSc.options.installDir',  self)
69    self.dataFilesPath = framework.require('PETSc.options.dataFilesPath',self)
70    self.scalartypes   = framework.require('PETSc.options.scalarTypes', self)
71    self.indexTypes    = framework.require('PETSc.options.indexTypes',  self)
72    self.languages     = framework.require('PETSc.options.languages',   self.setCompilers)
73    self.indexTypes    = framework.require('PETSc.options.indexTypes',  self.compilers)
74    self.types         = framework.require('config.types',              self)
75    self.headers       = framework.require('config.headers',            self)
76    self.functions     = framework.require('config.functions',          self)
77    self.libraries     = framework.require('config.libraries',          self)
78    self.atomics       = framework.require('config.atomics',            self)
79    self.make          = framework.require('config.packages.make',      self)
80    self.blasLapack    = framework.require('config.packages.BlasLapack',self)
81    self.mpi           = framework.require('config.packages.MPI',       self)
82    self.fortran       = framework.require('config.compilersFortran',   self)
83    self.externalpackagesdir = framework.require('PETSc.options.externalpackagesdir',self)
84
85    for utility in sorted(os.listdir(os.path.join('config','PETSc','options'))):
86      self.registerPythonFile(utility,'PETSc.options')
87
88    for utility in sorted(os.listdir(os.path.join('config','BuildSystem','config','utilities'))):
89      self.registerPythonFile(utility,'config.utilities')
90
91    for package in sorted(os.listdir(os.path.join('config', 'BuildSystem', 'config', 'packages'))):
92      obj = self.registerPythonFile(package,'config.packages')
93      if obj:
94        obj.archProvider                = self.framework.requireModule(obj.archProvider, obj)
95        obj.languageProvider            = self.framework.requireModule(obj.languageProvider, obj)
96        obj.installDirProvider          = self.framework.requireModule(obj.installDirProvider, obj)
97        obj.externalPackagesDirProvider = self.framework.requireModule(obj.externalPackagesDirProvider, obj)
98        obj.precisionProvider           = self.framework.requireModule(obj.precisionProvider, obj)
99        obj.indexProvider               = self.framework.requireModule(obj.indexProvider, obj)
100
101    # Force blaslapack and opencl to depend on scalarType so precision is set before BlasLapack is built
102    framework.require('PETSc.options.scalarTypes', self.f2cblaslapack)
103    framework.require('PETSc.options.scalarTypes', self.fblaslapack)
104    framework.require('PETSc.options.scalarTypes', self.blaslapack)
105    framework.require('PETSc.options.scalarTypes', self.opencl)
106
107    self.programs.headerPrefix     = self.headerPrefix
108    self.setCompilers.headerPrefix = self.headerPrefix
109    self.compilers.headerPrefix    = self.headerPrefix
110    self.fortran.headerPrefix      = self.headerPrefix
111    self.types.headerPrefix        = self.headerPrefix
112    self.headers.headerPrefix      = self.headerPrefix
113    self.functions.headerPrefix    = self.headerPrefix
114    self.libraries.headerPrefix    = self.headerPrefix
115
116    # Register user provided package scripts
117    if 'with-package-scripts' in self.framework.argDB:
118      for script in self.framework.argDB['with-package-scripts']:
119        if os.path.splitext(script)[1] != '.py':
120          raise RuntimeError('Only python scripts compatible with configure package script format should be specified! Invalid option -with-package-scripts='+script)
121        self.framework.logPrint('User is registering a new package script: '+script)
122        dname,fname = os.path.split(script)
123        if dname: sys.path.append(dname)
124        self.registerPythonFile(fname,'')
125
126    # test for a variety of basic headers and functions
127    headersC = map(lambda name: name+'.h',['setjmp','dos','fcntl','float','io','malloc','pwd','strings',
128                                            'unistd','sys/sysinfo','machine/endian','sys/param','sys/procfs','sys/resource',
129                                            'sys/systeminfo','sys/times','sys/utsname',
130                                            'sys/socket','sys/wait','netinet/in','netdb','direct','time','Ws2tcpip','sys/types',
131                                            'WindowsX','float','ieeefp','stdint','pthread','inttypes','immintrin','zmmintrin'])
132    functions = ['access','_access','clock','drand48','getcwd','_getcwd','getdomainname','gethostname',
133                 'getwd','posix_memalign','popen','PXFGETARG','rand','getpagesize',
134                 'readlink','realpath','usleep','sleep','_sleep',
135                 'uname','snprintf','_snprintf','lseek','_lseek','time','fork','stricmp',
136                 'strcasecmp','bzero','dlopen','dlsym','dlclose','dlerror',
137                 '_set_output_format','_mkdir','socket','gethostbyname','_pipe','fpresetsticky',
138                 'fpsetsticky','__gcov_dump','fstatat']
139    libraries = [(['fpe'],'handle_sigfpes')]
140    librariessock = [(['socket','nsl'],'socket')]
141    self.headers.headers.extend(headersC)
142    self.functions.functions.extend(functions)
143    self.libraries.libraries.extend(libraries)
144    if not hasattr(self,'socket'):
145      self.libraries.libraries.extend(librariessock)
146    return
147
148  def DumpPkgconfig(self, petsc_pc):
149    ''' Create a pkg-config file '''
150    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig')):
151      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig'))
152    with open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig',petsc_pc),'w') as fd:
153      cflags_inc = ['-I${includedir}']
154      if self.framework.argDB['prefix']:
155        fd.write('prefix='+self.installdir.dir+'\n')
156      else:
157        fd.write('prefix='+os.path.join(self.petscdir.dir, self.arch.arch)+'\n')
158        cflags_inc.append('-I' + os.path.join(self.petscdir.dir, 'include'))
159      fd.write('exec_prefix=${prefix}\n')
160      fd.write('includedir=${prefix}/include\n')
161      fd.write('libdir=${prefix}/lib\n')
162
163      with self.setCompilers.Language('C'):
164        fd.write('ccompiler='+self.setCompilers.getCompiler()+'\n')
165        fd.write('cflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
166        fd.write('cflags_dep='+self.compilers.dependenciesGenerationFlag.get('C','')+'\n')
167        fd.write('ldflag_rpath='+self.setCompilers.CSharedLinkerFlag+'\n')
168      if hasattr(self.compilers, 'CXX'):
169        with self.setCompilers.Language('C++'):
170          fd.write('cxxcompiler='+self.setCompilers.getCompiler()+'\n')
171          fd.write('cxxflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
172      if hasattr(self.compilers, 'FC'):
173        with self.setCompilers.Language('FC'):
174          fd.write('fcompiler='+self.setCompilers.getCompiler()+'\n')
175          fd.write('fflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
176      if hasattr(self.compilers, 'CUDAC'):
177        with self.setCompilers.Language('CUDA'):
178          fd.write('cudacompiler='+self.setCompilers.getCompiler()+'\n')
179          fd.write('cudaflags_extra='+self.setCompilers.getCompilerFlags().strip()+'\n')
180          p = self.framework.require('config.packages.cuda')
181          fd.write('cudalib='+self.libraries.toStringNoDupes(p.lib)+'\n')
182          fd.write('cudainclude='+self.headers.toStringNoDupes(p.include)+'\n')
183          if hasattr(self.setCompilers,'CUDA_CXX'):
184            fd.write('cuda_cxx='+self.setCompilers.CUDA_CXX+'\n')
185            fd.write('cuda_cxxflags='+self.setCompilers.CUDA_CXXFLAGS+'\n')
186
187      fd.write('\n')
188      fd.write('Name: PETSc\n')
189      fd.write('Description: Library to solve ODEs and algebraic equations\n')
190      fd.write('Version: %s\n' % self.petscdir.version)
191      fd.write('Cflags: ' + ' '.join([self.setCompilers.CPPFLAGS] + cflags_inc) + '\n')
192      fd.write('Libs: '+self.libraries.toStringNoDupes(['-L${libdir}', self.petsclib], with_rpath=False)+'\n')
193      # Remove RPATH flags from library list.  User can add them using
194      # pkg-config --variable=ldflag_rpath and pkg-config --libs-only-L
195      fd.write('Libs.private: '+self.libraries.toStringNoDupes([f for f in self.packagelibs+self.complibs if not f.startswith(self.setCompilers.CSharedLinkerFlag)], with_rpath=False)+'\n')
196    return
197
198  def DumpModule(self):
199    ''' Create a module file '''
200    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules')):
201      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules'))
202    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc')):
203      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc'))
204    if self.framework.argDB['prefix']:
205      installdir  = self.installdir.dir
206      installarch = ''
207      installpath = os.path.join(installdir,'bin')
208    else:
209      installdir  = self.petscdir.dir
210      installarch = self.arch.arch
211      installpath = os.path.join(installdir,installarch,'bin')+':'+os.path.join(installdir,'bin')
212    fd = open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc',self.petscdir.version),'w')
213    fd.write('''\
214#%%Module
215
216proc ModulesHelp { } {
217    puts stderr "This module sets the path and environment variables for petsc-%s"
218    puts stderr "     see https://petsc.org/ for more information      "
219    puts stderr ""
220}
221module-whatis "PETSc - Portable, Extensible Toolkit for Scientific Computation"
222
223set petsc_dir   "%s"
224set petsc_arch  "%s"
225
226setenv PETSC_ARCH "$petsc_arch"
227setenv PETSC_DIR "$petsc_dir"
228prepend-path PATH "%s"
229''' % (self.petscdir.version, installdir, installarch, installpath))
230    fd.close()
231    return
232
233  def Dump(self):
234    ''' Actually put the values into the configuration files '''
235    # eventually everything between -- should be gone
236    if self.mpi.usingMPIUni:
237      #
238      # Remove any MPI/MPICH include files that may have been put here by previous runs of ./configure
239      self.executeShellCommand('rm -rf  '+os.path.join(self.petscdir.dir,self.arch.arch,'include','mpi*')+' '+os.path.join(self.petscdir.dir,self.arch.arch,'include','opa*'), log = self.log)
240
241    self.logPrintDivider()
242    # Test for compiler-specific macros that need to be defined.
243    if self.setCompilers.isCrayVector('CC', self.log):
244      self.addDefine('HAVE_CRAY_VECTOR','1')
245
246    if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket') and self.headers.haveHeader('netinet/in.h'):
247      self.addDefine('USE_SOCKET_VIEWER','1')
248      if self.checkCompile('#include <sys/socket.h>','setsockopt(0,SOL_SOCKET,SO_REUSEADDR,0,0)'):
249        self.addDefine('HAVE_SO_REUSEADDR','1')
250
251    self.logPrintDivider()
252    self.setCompilers.pushLanguage('C')
253    compiler = self.setCompilers.getCompiler()
254    if [s for s in ['mpicc','mpiicc'] if os.path.basename(compiler).find(s)>=0]:
255      try:
256        output   = self.executeShellCommand(compiler + ' -show', log = self.log)[0]
257        compiler = output.split(' ')[0]
258        self.addDefine('MPICC_SHOW','"'+output.strip().replace('\n','\\\\n').replace('"','')+'"')
259      except:
260        self.addDefine('MPICC_SHOW','"Unavailable"')
261    else:
262      self.addDefine('MPICC_SHOW','"Unavailable"')
263    self.setCompilers.popLanguage()
264#-----------------------------------------------------------------------------------------------------
265
266    # Sometimes we need C compiler, even if built with C++
267    self.setCompilers.pushLanguage('C')
268    # do not use getCompilerFlags() because that automatically includes the CPPFLAGS so one ends up with duplication flags in makefile usage
269    self.addMakeMacro('CC_FLAGS',self.setCompilers.CFLAGS)
270    self.setCompilers.popLanguage()
271
272    # And sometimes we need a C++ compiler even when PETSc is built with C
273    if hasattr(self.compilers, 'CXX'):
274      self.setCompilers.pushLanguage('Cxx')
275      self.addDefine('HAVE_CXX','1')
276      self.addMakeMacro('CXXPP_FLAGS',self.setCompilers.CXXPPFLAGS)
277      # do not use getCompilerFlags() because that automatically includes the CXXPPFLAGS so one ends up with duplication flags in makefile usage
278      self.addMakeMacro('CXX_FLAGS',self.setCompilers.CXXFLAGS+' '+self.setCompilers.CXX_CXXFLAGS)
279      cxx_linker = self.setCompilers.getLinker()
280      self.addMakeMacro('CXX_LINKER',cxx_linker)
281      self.addMakeMacro('CXX_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
282      self.setCompilers.popLanguage()
283    else:
284      self.addMakeMacro('CXX','')
285
286    # C preprocessor values
287    self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS)
288
289    # compiler values
290    self.setCompilers.pushLanguage(self.languages.clanguage)
291    self.addMakeMacro('PCC',self.setCompilers.getCompiler())
292    # do not use getCompilerFlags() because that automatically includes the preprocessor flags so one ends up with duplication flags in makefile usage
293    if self.languages.clanguage == 'C':
294      self.addMakeMacro('PCC_FLAGS','$(CC_FLAGS)')
295    else:
296      self.addMakeMacro('PCC_FLAGS','$(CXX_FLAGS)')
297    self.setCompilers.popLanguage()
298    # .o or .obj
299    self.addMakeMacro('CC_SUFFIX','o')
300
301    # executable linker values
302    self.setCompilers.pushLanguage(self.languages.clanguage)
303    pcc_linker = self.setCompilers.getLinker()
304    self.addMakeMacro('PCC_LINKER',pcc_linker)
305    self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
306    self.setCompilers.popLanguage()
307    # '' for Unix, .exe for Windows
308    self.addMakeMacro('CC_LINKER_SUFFIX','')
309
310    if hasattr(self.compilers, 'FC'):
311      if self.framework.argDB['with-fortran-bindings']:
312        if not self.fortran.fortranIsF90:
313          raise RuntimeError('Error! Fortran compiler "'+self.compilers.FC+'" does not support F90! PETSc fortran bindings require a F90 compiler')
314        self.addDefine('HAVE_FORTRAN','1')
315      self.setCompilers.pushLanguage('FC')
316      # need FPPFLAGS in config/setCompilers
317      self.addMakeMacro('FPP_FLAGS',self.setCompilers.FPPFLAGS)
318
319      # compiler values
320      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
321      self.setCompilers.popLanguage()
322      # .o or .obj
323      self.addMakeMacro('FC_SUFFIX','o')
324
325      # executable linker values
326      self.setCompilers.pushLanguage('FC')
327      self.addMakeMacro('FC_LINKER',self.setCompilers.getLinker())
328      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
329      # apple requires this shared library linker flag on SOME versions of the os
330      if self.setCompilers.getLinkerFlags().find('-Wl,-commons,use_dylibs') > -1:
331        self.addMakeMacro('DARWIN_COMMONS_USE_DYLIBS',' -Wl,-commons,use_dylibs ')
332      self.setCompilers.popLanguage()
333
334      # F90 Modules
335      if self.setCompilers.fortranModuleIncludeFlag:
336        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
337      else: # for non-f90 compilers like g77
338        self.addMakeMacro('FC_MODULE_FLAG', '-I')
339      if self.setCompilers.fortranModuleIncludeFlag:
340        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
341    else:
342      self.addMakeMacro('FC','')
343
344    if hasattr(self.compilers, 'CUDAC'):
345      self.setCompilers.pushLanguage('CUDA')
346      self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags())
347      self.addMakeMacro('CUDAPP_FLAGS',self.setCompilers.CUDAPPFLAGS)
348      self.setCompilers.popLanguage()
349
350    if hasattr(self.compilers, 'HIPC'):
351      self.setCompilers.pushLanguage('HIP')
352      self.addMakeMacro('HIPC_FLAGS',self.setCompilers.getCompilerFlags())
353      self.addMakeMacro('HIPPP_FLAGS',self.setCompilers.HIPPPFLAGS)
354      self.setCompilers.popLanguage()
355
356    if hasattr(self.compilers, 'SYCLC'):
357      self.setCompilers.pushLanguage('SYCL')
358      self.addMakeMacro('SYCLC_FLAGS',self.setCompilers.getCompilerFlags())
359      self.addMakeMacro('SYCLPP_FLAGS',self.setCompilers.SYCLPPFLAGS)
360      self.setCompilers.popLanguage()
361
362    # shared library linker values
363    self.setCompilers.pushLanguage(self.languages.clanguage)
364    # need to fix BuildSystem to collect these separately
365    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
366    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
367    self.setCompilers.popLanguage()
368    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
369    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
370    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
371      self.addMakeMacro('SL_LINKER_SUFFIX', '')
372      self.addDefine('SLSUFFIX','""')
373    else:
374      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
375      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
376
377    self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}')
378
379#-----------------------------------------------------------------------------------------------------
380
381    # CONLY or CPP. We should change the PETSc makefiles to do this better
382    if self.languages.clanguage == 'C': lang = 'CONLY'
383    else: lang = 'CXXONLY'
384    self.addMakeMacro('PETSC_LANGUAGE',lang)
385
386    # real or complex
387    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
388    # double or float
389    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
390
391    if self.framework.argDB['with-batch']:
392      self.addMakeMacro('PETSC_WITH_BATCH','1')
393
394#-----------------------------------------------------------------------------------------------------
395    # print include and lib for makefiles
396    self.logPrintDivider()
397    self.framework.packages.reverse()
398    petscincludes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')]
399    petscincludes_install = [os.path.join(self.installdir.dir, 'include')] if self.framework.argDB['prefix'] else petscincludes
400    includes = []
401    self.packagelibs = []
402    for i in self.framework.packages:
403      if not i.required:
404        if i.devicePackage:
405          self.addDefine('HAVE_DEVICE',1)
406        self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
407      if not isinstance(i.lib, list):
408        i.lib = [i.lib]
409      if i.linkedbypetsc: self.packagelibs.extend(i.lib)
410      self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib))
411      if hasattr(i,'include'):
412        if not isinstance(i.include,list):
413          i.include = [i.include]
414        includes.extend(i.include)
415        self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include))
416    if self.framework.argDB['with-single-library']:
417      self.petsclib = '-lpetsc'
418    else:
419      self.petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
420    self.complibs = self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split()
421    self.PETSC_WITH_EXTERNAL_LIB = self.libraries.toStringNoDupes(['-L${PETSC_DIR}/${PETSC_ARCH}/lib', self.petsclib]+self.packagelibs+self.complibs)
422    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(self.packagelibs+self.complibs)
423
424    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.PETSC_EXTERNAL_LIB_BASIC)
425    allincludes = petscincludes + includes
426    allincludes_install = petscincludes_install + includes
427    self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(allincludes)
428    self.PETSC_CC_INCLUDES_INSTALL = self.headers.toStringNoDupes(allincludes_install)
429    self.addMakeMacro('PETSC_CC_INCLUDES',self.PETSC_CC_INCLUDES)
430    self.addMakeMacro('PETSC_CC_INCLUDES_INSTALL', self.PETSC_CC_INCLUDES_INSTALL)
431    if hasattr(self.compilers, 'FC'):
432      def modinc(includes):
433        return includes if self.fortran.fortranIsF90 else []
434      self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(allincludes,modinc(allincludes)))
435      self.addMakeMacro('PETSC_FC_INCLUDES_INSTALL',self.headers.toStringNoDupes(allincludes_install,modinc(allincludes_install)))
436
437    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"')
438
439    if self.framework.argDB['with-single-library']:
440      # overrides the values set in conf/variables
441      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
442      self.addMakeMacro('SHLIBS','libpetsc')
443      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
444      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
445      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
446      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
447      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.PETSC_WITH_EXTERNAL_LIB)
448      self.addDefine('USE_SINGLE_LIBRARY', '1')
449      if self.sharedlibraries.useShared:
450        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
451        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
452        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
453        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
454        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
455        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
456        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
457        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
458        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
459        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
460        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
461      else:
462        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
463        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
464        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
465        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
466        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
467        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
468        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
469        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
470        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
471        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
472        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
473
474    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
475      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
476
477# add a makefile endtry for display
478    if self.framework.argDB['with-display']:
479      self.addMakeMacro('DISPLAY',self.framework.argDB['with-display'])
480
481    # add a makefile entry for configure options
482    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
483    return
484
485  def dumpConfigInfo(self):
486    import time
487    fd = open(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
488    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"').replace('\\ ','\\\\ ')+'";\n')
489    fd.close()
490    return
491
492  def dumpMachineInfo(self):
493    import platform
494    import datetime
495    import time
496    import script
497    def escape(s):
498      return s.replace('"',r'\"').replace(r'\ ',r'\\ ') # novermin
499    fd = open(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
500    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
501    fd.write('\"-----------------------------------------\\n\"\n')
502    buildhost = platform.node()
503    if os.environ.get('SOURCE_DATE_EPOCH'):
504      buildhost = "reproducible"
505    buildtime = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
506    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (buildtime, buildhost))
507    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
508    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir)))
509    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch)))
510    fd.write('\"-----------------------------------------\\n\";\n')
511    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
512    self.setCompilers.pushLanguage(self.languages.clanguage)
513    fd.write('\"Using C compiler: %s %s \\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
514    self.setCompilers.popLanguage()
515    if hasattr(self.compilers, 'FC'):
516      self.setCompilers.pushLanguage('FC')
517      fd.write('\"Using Fortran compiler: %s %s  %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
518      self.setCompilers.popLanguage()
519    fd.write('\"-----------------------------------------\\n\";\n')
520    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
521    fd.write('\"Using include paths: %s\\n\"\n' % (escape(self.PETSC_CC_INCLUDES_INSTALL.replace('${PETSC_DIR}', self.installdir.petscDir))))
522    fd.write('\"-----------------------------------------\\n\";\n')
523    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
524    self.setCompilers.pushLanguage(self.languages.clanguage)
525    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
526    self.setCompilers.popLanguage()
527    if hasattr(self.compilers, 'FC'):
528      self.setCompilers.pushLanguage('FC')
529      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
530      self.setCompilers.popLanguage()
531    fd.write('\"Using libraries: %s%s -L%s %s %s\\n\"\n' % (escape(self.setCompilers.CSharedLinkerFlag), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(os.path.join(self.installdir.petscDir, self.installdir.petscArch, 'lib')), escape(self.petsclib), escape(self.PETSC_EXTERNAL_LIB_BASIC)))
532    fd.write('\"-----------------------------------------\\n\";\n')
533    fd.close()
534    return
535
536  def configurePrefetch(self):
537    '''Sees if there are any prefetch functions supported'''
538    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
539      self.addDefine('Prefetch(a,b,c)', ' ')
540      return
541    self.pushLanguage(self.languages.clanguage)
542    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
543      # The Intel Intrinsics manual [1] specifies the prototype
544      #
545      #   void _mm_prefetch(char const *a, int sel);
546      #
547      # but other vendors seem to insist on using subtly different
548      # prototypes, including void* for the pointer, and an enum for
549      # sel.  These are both reasonable changes, but negatively impact
550      # portability.
551      #
552      # [1] https://software.intel.com/file/6373
553      self.addDefine('HAVE_XMMINTRIN_H', 1)
554      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
555      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
556      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
557      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
558      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
559    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
560      self.addDefine('HAVE_XMMINTRIN_H', 1)
561      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
562      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
563      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
564      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
565      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
566    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
567      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
568      #
569      #   The value of rw is a compile-time constant one or zero; one
570      #   means that the prefetch is preparing for a write to the memory
571      #   address and zero, the default, means that the prefetch is
572      #   preparing for a read. The value locality must be a compile-time
573      #   constant integer between zero and three. A value of zero means
574      #   that the data has no temporal locality, so it need not be left
575      #   in the cache after the access. A value of three means that the
576      #   data has a high degree of temporal locality and should be left
577      #   in all levels of cache possible. Values of one and two mean,
578      #   respectively, a low or moderate degree of temporal locality.
579      #
580      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
581      # hints.  Using macros for these values in necessary since some
582      # compilers require an enum.
583      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
584      self.addDefine('PREFETCH_HINT_NTA', '0')
585      self.addDefine('PREFETCH_HINT_T0',  '3')
586      self.addDefine('PREFETCH_HINT_T1',  '2')
587      self.addDefine('PREFETCH_HINT_T2',  '1')
588    else:
589      self.addDefine('Prefetch(a,b,c)', ' ')
590    self.popLanguage()
591
592  def delGenFiles(self):
593    '''Delete generated files'''
594    delfile = os.path.join(self.arch.arch,'lib','petsc','conf','files')
595    try:
596      os.unlink(delfile)
597    except: pass
598
599  def configureAtoll(self):
600    '''Checks if atoll exists'''
601    if self.checkLink('#define _POSIX_C_SOURCE 200112L\n#include <stdlib.h>','long v = atoll("25");\n(void)v') or self.checkLink ('#include <stdlib.h>','long v = atoll("25");\n(void)v'):
602       self.addDefine('HAVE_ATOLL', '1')
603
604  def configureUnused(self):
605    '''Sees if __attribute((unused)) is supported'''
606    if self.framework.argDB['with-ios']:
607      self.addDefine('UNUSED', ' ')
608      return
609    self.pushLanguage(self.languages.clanguage)
610    if self.checkLink('__attribute((unused)) static int myfunc(__attribute((unused)) void *name){ return 1;}', 'int i = 0;\nint j = myfunc(&i);\n(void)j;\ntypedef void* atype;\n__attribute((unused))  atype a'):
611      self.addDefine('UNUSED', '__attribute((unused))')
612    else:
613      self.addDefine('UNUSED', ' ')
614    self.popLanguage()
615
616  def configureIsatty(self):
617    '''Check if the Unix C function isatty() works correctly
618       Actually just assumes it does not work correctly on batch systems'''
619    if not self.framework.argDB['with-batch']:
620      self.addDefine('USE_ISATTY',1)
621
622  def configureDeprecated(self):
623    '''Check if __attribute((deprecated)) is supported'''
624    def checkDeprecated(macro_base, src, is_intel):
625      '''
626      run through the various attribute deprecated combinations and define MACRO_BAS(why) to the result
627      it if it compiles.
628
629      If none of the combos work, defines MACRO_BASE(why) as empty
630      '''
631      full_macro_name = macro_base + '(why)'
632      for prefix in ('__attribute__', '__attribute','__declspec'):
633        if prefix == '__declspec':
634          # declspec does not have an extra set of brackets around the arguments
635          attr_bodies = ('deprecated(why)', 'deprecated')
636        else:
637          attr_bodies = ('(deprecated(why))', '(deprecated)')
638
639        for attr_body in attr_bodies:
640          attr_def = '{}({})'.format(prefix, attr_body)
641          test_src = '\n'.join((
642            '#define {} {}'.format(full_macro_name, attr_def),
643            src.format(macro_base + '("asdasdadsasd")')
644          ))
645          if self.checkCompile(test_src, ''):
646            self.logPrint('configureDeprecated: \'{}\' appears to work'.format(attr_def))
647            if is_intel and '(why)' in attr_body:
648              self.logPrint('configureDeprecated: Intel has conspired to make a supremely environment-sensitive compiler. The Intel compiler looks at the gcc executable in the environment to determine the language compatibility that it should attempt to emulate. Some important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g. 4.7). Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc found in the default user environment is older and does not support the argument.\n'.format(attr_def))
649              self.logPrint('*** WE WILL THEREFORE REJECT \'{}\' AND CONTINUE TESTING ***'.format(attr_def))
650              continue
651            self.addDefine(full_macro_name, attr_def)
652            return
653
654      self.addDefine(full_macro_name, ' ')
655      return
656
657    lang = self.languages.clanguage
658    with self.Language(lang):
659      is_intel = self.setCompilers.isIntel(self.getCompiler(lang=lang), self.log)
660      checkDeprecated('DEPRECATED_FUNCTION', '{} int myfunc(void) {{ return 1; }}', is_intel)
661      checkDeprecated('DEPRECATED_TYPEDEF', 'typedef int my_int {};', is_intel)
662      checkDeprecated('DEPRECATED_ENUM', 'enum E {{ oldval {}, newval }};', is_intel)
663      # I was unable to make a CPP macro that takes the old and new values as separate
664      # arguments and builds the message needed by _Pragma hence the deprecation message is
665      # handled as it is
666      if self.checkCompile('#define TEST _Pragma("GCC warning \"Testing _Pragma\"") value'):
667        self.addDefine('DEPRECATED_MACRO(why)', '_Pragma(why)')
668      else:
669        self.addDefine('DEPRECATED_MACRO(why)', ' ')
670
671  def configureAlign(self):
672    '''Check if __attribute(aligned) is supported'''
673    code = '''\
674struct mystruct {int myint;} __attribute((aligned(16)));
675char assert_aligned[(sizeof(struct mystruct)==16)*2-1];
676'''
677    self.pushLanguage(self.languages.clanguage)
678    if self.checkCompile(code):
679      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned(size)))')
680      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
681    else:
682      self.framework.logPrint('Incorrect attribute(aligned)')
683      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
684    self.popLanguage()
685    return
686
687  def configureExpect(self):
688    '''Sees if the __builtin_expect directive is supported'''
689    self.pushLanguage(self.languages.clanguage)
690    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
691      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
692    self.popLanguage()
693
694  def configureFunctionName(self):
695    '''Sees if the compiler supports __func__ or a variant.'''
696    def getFunctionName(lang):
697      name = '"unknown"'
698      self.pushLanguage(lang)
699      for fname in ['__func__','__FUNCTION__','__extension__ __func__']:
700        code = "if ("+fname+"[0] != 'm') return 1;"
701        if self.checkCompile('',code) and self.checkLink('',code):
702          name = fname
703          break
704      self.popLanguage()
705      return name
706    langs = []
707
708    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
709    if hasattr(self.compilers, 'CXX'):
710      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
711
712  def configureIntptrt(self):
713    '''Determine what to use for uintptr_t'''
714    def staticAssertSizeMatchesVoidStar(inc,typename):
715      # The declaration is an error if either array size is negative.
716      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
717      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
718                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
719    self.pushLanguage(self.languages.clanguage)
720    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x; (void)i'):
721      self.addDefine('UINTPTR_T', 'uintptr_t')
722    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
723      self.addDefine('UINTPTR_T', 'unsigned long long')
724    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
725      self.addDefine('UINTPTR_T', 'size_t')
726    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
727      self.addDefine('UINTPTR_T', 'unsigned long')
728    elif staticAssertSizeMatchesVoidStar('','unsigned'):
729      self.addDefine('UINTPTR_T', 'unsigned')
730    else:
731      raise RuntimeError('Could not find any unsigned integer type matching void*')
732    self.popLanguage()
733
734  def configureRTLDDefault(self):
735    '''Check for dynamic library feature'''
736    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
737      self.addDefine('HAVE_RTLD_DEFAULT','1')
738    return
739
740  def configureSolaris(self):
741    '''Solaris specific stuff'''
742    if os.path.isdir(os.path.join('/usr','ucblib')):
743      try:
744        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
745      except AttributeError:
746        flag = None
747      if flag is None:
748        self.compilers.LIBS += ' -L/usr/ucblib'
749      else:
750        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
751    return
752
753  def configureDarwin(self):
754    '''Log brew configuration for Apple systems'''
755    try:
756      self.executeShellCommand(['brew', 'config'], log = self.log)
757      self.executeShellCommand(['brew', 'info', 'gcc'], log = self.log)
758    except:
759      pass
760    return
761
762  def configureLinux(self):
763    '''Linux specific stuff'''
764    # TODO: Test for this by mallocing an odd number of floats and checking the address
765    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
766    return
767
768  def configureWin32(self):
769    '''Win32 non-cygwin specific stuff'''
770    kernel32=0
771    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'):
772      self.addDefine('HAVE_WINDOWS_H',1)
773      self.addDefine('HAVE_GETCOMPUTERNAME',1)
774      kernel32=1
775    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'):
776      self.addDefine('HAVE_WINDOWS_H',1)
777      self.addDefine('HAVE_GETCOMPUTERNAME',1)
778      kernel32=1
779    if kernel32:
780      if self.framework.argDB['with-windows-graphics']:
781        self.addDefine('USE_WINDOWS_GRAPHICS',1)
782      if self.checkLink('#include <windows.h>','LoadLibrary(0)'):
783        self.addDefine('HAVE_LOADLIBRARY',1)
784      if self.checkLink('#include <windows.h>','GetProcAddress(0,0)'):
785        self.addDefine('HAVE_GETPROCADDRESS',1)
786      if self.checkLink('#include <windows.h>','FreeLibrary(0)'):
787        self.addDefine('HAVE_FREELIBRARY',1)
788      if self.checkLink('#include <windows.h>','GetLastError()'):
789        self.addDefine('HAVE_GETLASTERROR',1)
790      if self.checkLink('#include <windows.h>','SetLastError(0)'):
791        self.addDefine('HAVE_SETLASTERROR',1)
792      if self.checkLink('#include <windows.h>\n','QueryPerformanceCounter(0);\n'):
793        self.addDefine('USE_MICROSOFT_TIME',1)
794    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'):
795      self.addDefine('HAVE_GET_USER_NAME',1)
796    elif self.libraries.add('advapi32','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'):
797      self.addDefine('HAVE_GET_USER_NAME',1)
798
799    if not self.libraries.add('User32.lib','GetDC',prototype='#include <windows.h>',call='GetDC(0);'):
800      self.libraries.add('user32','GetDC',prototype='#include <windows.h>',call='GetDC(0);')
801    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);'):
802      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);')
803
804    self.types.check('int32_t', 'int')
805    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n(void)u'):
806      self.addTypedef('int', 'uid_t')
807      self.addTypedef('int', 'gid_t')
808    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n(void)a'):
809      self.framework.addDefine('R_OK', '04')
810      self.framework.addDefine('W_OK', '02')
811      self.framework.addDefine('X_OK', '01')
812    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
813      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
814      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
815    if self.checkCompile('#include <windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
816      self.addDefine('HAVE_LARGE_INTEGER_U',1)
817
818    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
819    if self.checkCompile('#include <windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
820      self.addDefine('HAVE_O_BINARY',1)
821
822    if self.compilers.CC.find('win32fe') >= 0:
823      self.addDefine('HAVE_WINDOWS_COMPILERS',1)
824      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
825      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
826      self.addDefine('CANNOT_START_DEBUGGER',1)
827      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log)
828      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
829      (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log)
830      self.addMakeMacro('wPETSC_DIR',petscdir)
831      if self.dataFilesPath.datafilespath:
832        (datafilespath,error,status) = self.executeShellCommand('cygpath -m '+self.dataFilesPath.datafilespath, log = self.log)
833        self.addMakeMacro('DATAFILESPATH',datafilespath)
834
835    else:
836      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
837      self.addDefine('DIR_SEPARATOR','\'/\'')
838      self.addDefine('DIR','"'+self.installdir.petscDir+'"')
839      self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir)
840      if self.dataFilesPath.datafilespath:
841        self.addMakeMacro('DATAFILESPATH',self.dataFilesPath.datafilespath)
842    self.addDefine('ARCH','"'+self.installdir.petscArch+'"')
843    return
844
845#-----------------------------------------------------------------------------------------------------
846  def configureCygwinBrokenPipe(self):
847    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
848    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
849    if config.setCompilers.Configure.isCygwin(self.log):
850      import platform
851      import re
852      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
853      m=r.match(platform.release())
854      major=int(m.group(1))
855      minor=int(m.group(2))
856      subminor=int(m.group(3))
857      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
858        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
859    return
860
861#-----------------------------------------------------------------------------------------------------
862  def configureDefaultArch(self):
863    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
864    if self.framework.argDB['with-default-arch']:
865      fd = open(conffile, 'w')
866      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
867      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
868      fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n')
869      fd.close()
870      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
871    elif os.path.isfile(conffile):
872      try:
873        os.unlink(conffile)
874      except:
875        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
876    return
877
878#-----------------------------------------------------------------------------------------------------
879  def configureScript(self):
880    '''Output a script in the conf directory which will reproduce the configuration'''
881    import nargs
882    import sys
883    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
884    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
885    if 'with-clean' in args:
886      del args['with-clean']
887    if 'force' in args:
888      del args['force']
889    if 'configModules' in args:
890      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
891        del args['configModules']
892    if 'optionsModule' in args:
893      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
894        del args['optionsModule']
895    if not 'PETSC_ARCH' in args:
896      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
897    f = open(scriptName, 'w')
898    f.write('#!'+sys.executable+'\n')
899    f.write('if __name__ == \'__main__\':\n')
900    f.write('  import sys\n')
901    f.write('  import os\n')
902    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
903    f.write('  import configure\n')
904    # pretty print repr(args.values())
905    f.write('  configure_options = [\n')
906    for itm in sorted(args.values()):
907      f.write('    \''+str(itm)+'\',\n')
908    f.write('  ]\n')
909    f.write('  configure.petsc_configure(configure_options)\n')
910    f.close()
911    try:
912      os.chmod(scriptName, 0o775)
913    except OSError as e:
914      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
915    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
916    return
917
918  def configureInstall(self):
919    '''Setup the directories for installation'''
920    if self.framework.argDB['prefix']:
921      self.addMakeRule('print_mesg_after_build','',
922       ['-@echo "========================================="',
923        '-@echo "Now to install the libraries do:"',
924        '-@echo "%s${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"' % self.installdir.installSudo,
925        '-@echo "========================================="'])
926    else:
927      self.addMakeRule('print_mesg_after_build','',
928       ['-@echo "========================================="',
929        '-@echo "Now to check if the libraries are working do:"',
930        '-@echo "${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"',
931        '-@echo "========================================="'])
932      return
933
934  def configureGCOV(self):
935    '''Checking for configuring with gcov, from --with-gcov'''
936    if self.framework.argDB['with-gcov']:
937      self.addDefine('USE_GCOV','1')
938    return
939
940  def postProcessPackages(self):
941    postPackages=[]
942    for i in self.framework.packages:
943      if hasattr(i,'postProcess'): postPackages.append(i)
944    if postPackages:
945      # ctetgen needs petsc conf files. so attempt to create them early
946      self.framework.dumpConfFiles()
947      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
948      for i in postPackages:
949        if i.name.upper() in ['PFLOTRAN']:
950          i.postProcess()
951          postPackages.remove(i)
952      for i in postPackages: i.postProcess()
953      for i in postPackages:
954        if i.installedpetsc:
955          self.installed = 1
956          break
957    return
958
959  def configure(self):
960    if 'package-prefix-hash' in self.argDB:
961      # turn off prefix if it was only used to for installing external packages.
962      self.framework.argDB['prefix'] = ''
963      self.dir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch))
964      self.installdir.dir = self.dir
965      self.installdir.petscDir = self.petscdir.dir
966      self.petscDir = self.petscdir.dir
967      self.petscArch = self.arch.arch
968      self.addMakeMacro('PREFIXDIR',self.dir)
969      self.confDir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch))
970
971    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
972      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
973    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
974      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
975    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
976      raise RuntimeError('Your --prefix '+self.framework.argDB['prefix']+' has spaces in it; this is not allowed.\n Use a --prefix that does not have spaces in it')
977    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],os.path.join(self.petscdir.dir,self.arch.arch)):
978      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
979    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
980    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
981    self.framework.poisonheader    = os.path.join(self.arch.arch,'include','petscconf_poison.h')
982    self.framework.pkgheader       = os.path.join(self.arch.arch,'include','petscpkg_version.h')
983    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
984    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
985    if self.libraries.math is None:
986      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
987    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
988      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
989    self.executeTest(self.configureRTLDDefault)
990    self.executeTest(self.configurePrefetch)
991    self.executeTest(self.configureUnused)
992    self.executeTest(self.configureDeprecated)
993    self.executeTest(self.configureIsatty)
994    self.executeTest(self.configureExpect)
995    self.executeTest(self.configureAlign)
996    self.executeTest(self.configureFunctionName)
997    self.executeTest(self.configureIntptrt)
998    self.executeTest(self.configureSolaris)
999    self.executeTest(self.configureLinux)
1000    self.executeTest(self.configureDarwin)
1001    self.executeTest(self.configureWin32)
1002    self.executeTest(self.configureCygwinBrokenPipe)
1003    self.executeTest(self.configureDefaultArch)
1004    self.executeTest(self.configureScript)
1005    self.executeTest(self.configureInstall)
1006    self.executeTest(self.configureGCOV)
1007    self.executeTest(self.configureAtoll)
1008
1009    self.Dump()
1010    self.dumpConfigInfo()
1011    self.dumpMachineInfo()
1012    self.delGenFiles()
1013    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
1014    self.framework.storeSubstitutions(self.framework.argDB)
1015    self.framework.argDB['configureCache'] = pickle.dumps(self.framework)
1016    self.framework.argDB.save(force = True)
1017    self.DumpPkgconfig('PETSc.pc')
1018    self.DumpPkgconfig('petsc.pc')
1019    self.DumpModule()
1020    self.postProcessPackages()
1021    self.framework.log.write('================================================================================\n')
1022    self.logClear()
1023    return
1024