xref: /petsc/config/PETSc/Configure.py (revision a1cb98fac0cdf0eb4d3e8a0c8b58f3fe8f800bc6)
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
284    # C preprocessor values
285    self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS)
286
287    # compiler values
288    self.setCompilers.pushLanguage(self.languages.clanguage)
289    self.addMakeMacro('PCC',self.setCompilers.getCompiler())
290    # do not use getCompilerFlags() because that automatically includes the preprocessor flags so one ends up with duplication flags in makefile usage
291    if self.languages.clanguage == 'C':
292      self.addMakeMacro('PCC_FLAGS','$(CC_FLAGS)')
293    else:
294      self.addMakeMacro('PCC_FLAGS','$(CXX_FLAGS)')
295    self.setCompilers.popLanguage()
296    # .o or .obj
297    self.addMakeMacro('CC_SUFFIX','o')
298
299    # executable linker values
300    self.setCompilers.pushLanguage(self.languages.clanguage)
301    pcc_linker = self.setCompilers.getLinker()
302    self.addMakeMacro('PCC_LINKER',pcc_linker)
303    self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
304    self.setCompilers.popLanguage()
305    # '' for Unix, .exe for Windows
306    self.addMakeMacro('CC_LINKER_SUFFIX','')
307
308    if hasattr(self.compilers, 'FC'):
309      if self.framework.argDB['with-fortran-bindings']:
310        if not self.fortran.fortranIsF90:
311          raise RuntimeError('Error! Fortran compiler "'+self.compilers.FC+'" does not support F90! PETSc fortran bindings require a F90 compiler')
312        self.addDefine('HAVE_FORTRAN','1')
313      self.setCompilers.pushLanguage('FC')
314      # need FPPFLAGS in config/setCompilers
315      self.addMakeMacro('FPP_FLAGS',self.setCompilers.FPPFLAGS)
316
317      # compiler values
318      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
319      self.setCompilers.popLanguage()
320      # .o or .obj
321      self.addMakeMacro('FC_SUFFIX','o')
322
323      # executable linker values
324      self.setCompilers.pushLanguage('FC')
325      self.addMakeMacro('FC_LINKER',self.setCompilers.getLinker())
326      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
327      # apple requires this shared library linker flag on SOME versions of the os
328      if self.setCompilers.getLinkerFlags().find('-Wl,-commons,use_dylibs') > -1:
329        self.addMakeMacro('DARWIN_COMMONS_USE_DYLIBS',' -Wl,-commons,use_dylibs ')
330      self.setCompilers.popLanguage()
331
332      # F90 Modules
333      if self.setCompilers.fortranModuleIncludeFlag:
334        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
335      else: # for non-f90 compilers like g77
336        self.addMakeMacro('FC_MODULE_FLAG', '-I')
337      if self.setCompilers.fortranModuleIncludeFlag:
338        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
339    else:
340      self.addMakeMacro('FC','')
341
342    if hasattr(self.compilers, 'CUDAC'):
343      self.setCompilers.pushLanguage('CUDA')
344      self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags())
345      self.addMakeMacro('CUDAPP_FLAGS',self.setCompilers.CUDAPPFLAGS)
346      self.setCompilers.popLanguage()
347
348    if hasattr(self.compilers, 'HIPC'):
349      self.setCompilers.pushLanguage('HIP')
350      self.addMakeMacro('HIPC_FLAGS',self.setCompilers.getCompilerFlags())
351      self.addMakeMacro('HIPPP_FLAGS',self.setCompilers.HIPPPFLAGS)
352      self.setCompilers.popLanguage()
353
354    if hasattr(self.compilers, 'SYCLC'):
355      self.setCompilers.pushLanguage('SYCL')
356      self.addMakeMacro('SYCLC_FLAGS',self.setCompilers.getCompilerFlags())
357      self.addMakeMacro('SYCLPP_FLAGS',self.setCompilers.SYCLPPFLAGS)
358      self.setCompilers.popLanguage()
359
360    # shared library linker values
361    self.setCompilers.pushLanguage(self.languages.clanguage)
362    # need to fix BuildSystem to collect these separately
363    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
364    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
365    self.setCompilers.popLanguage()
366    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
367    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
368    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
369      self.addMakeMacro('SL_LINKER_SUFFIX', '')
370      self.addDefine('SLSUFFIX','""')
371    else:
372      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
373      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
374
375    self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}')
376
377#-----------------------------------------------------------------------------------------------------
378
379    # CONLY or CPP. We should change the PETSc makefiles to do this better
380    if self.languages.clanguage == 'C': lang = 'CONLY'
381    else: lang = 'CXXONLY'
382    self.addMakeMacro('PETSC_LANGUAGE',lang)
383
384    # real or complex
385    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
386    # double or float
387    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
388
389    if self.framework.argDB['with-batch']:
390      self.addMakeMacro('PETSC_WITH_BATCH','1')
391
392#-----------------------------------------------------------------------------------------------------
393    # print include and lib for makefiles
394    self.logPrintDivider()
395    self.framework.packages.reverse()
396    petscincludes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')]
397    petscincludes_install = [os.path.join(self.installdir.dir, 'include')] if self.framework.argDB['prefix'] else petscincludes
398    includes = []
399    self.packagelibs = []
400    for i in self.framework.packages:
401      if not i.required:
402        if i.devicePackage:
403          self.addDefine('HAVE_DEVICE',1)
404        self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
405      if not isinstance(i.lib, list):
406        i.lib = [i.lib]
407      if i.linkedbypetsc: self.packagelibs.extend(i.lib)
408      self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib))
409      if hasattr(i,'include'):
410        if not isinstance(i.include,list):
411          i.include = [i.include]
412        includes.extend(i.include)
413        self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include))
414    if self.framework.argDB['with-single-library']:
415      self.petsclib = '-lpetsc'
416    else:
417      self.petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
418    self.complibs = self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split()
419    self.PETSC_WITH_EXTERNAL_LIB = self.libraries.toStringNoDupes(['-L${PETSC_DIR}/${PETSC_ARCH}/lib', self.petsclib]+self.packagelibs+self.complibs)
420    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(self.packagelibs+self.complibs)
421
422    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.PETSC_EXTERNAL_LIB_BASIC)
423    allincludes = petscincludes + includes
424    allincludes_install = petscincludes_install + includes
425    self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(allincludes)
426    self.PETSC_CC_INCLUDES_INSTALL = self.headers.toStringNoDupes(allincludes_install)
427    self.addMakeMacro('PETSC_CC_INCLUDES',self.PETSC_CC_INCLUDES)
428    self.addMakeMacro('PETSC_CC_INCLUDES_INSTALL', self.PETSC_CC_INCLUDES_INSTALL)
429    if hasattr(self.compilers, 'FC'):
430      def modinc(includes):
431        return includes if self.fortran.fortranIsF90 else []
432      self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(allincludes,modinc(allincludes)))
433      self.addMakeMacro('PETSC_FC_INCLUDES_INSTALL',self.headers.toStringNoDupes(allincludes_install,modinc(allincludes_install)))
434
435    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"')
436
437    if self.framework.argDB['with-single-library']:
438      # overrides the values set in conf/variables
439      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
440      self.addMakeMacro('SHLIBS','libpetsc')
441      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
442      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
443      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
444      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
445      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.PETSC_WITH_EXTERNAL_LIB)
446      self.addDefine('USE_SINGLE_LIBRARY', '1')
447      if self.sharedlibraries.useShared:
448        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
449        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
450        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
451        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
452        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
453        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
454        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
455        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
456        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
457        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
458        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
459      else:
460        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
461        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
462        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
463        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
464        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
465        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
466        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
467        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
468        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
469        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
470        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
471
472    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
473      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
474
475# add a makefile endtry for display
476    if self.framework.argDB['with-display']:
477      self.addMakeMacro('DISPLAY',self.framework.argDB['with-display'])
478
479    # add a makefile entry for configure options
480    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
481    return
482
483  def dumpConfigInfo(self):
484    import time
485    fd = open(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
486    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"').replace('\\ ','\\\\ ')+'";\n')
487    fd.close()
488    return
489
490  def dumpMachineInfo(self):
491    import platform
492    import datetime
493    import time
494    import script
495    def escape(s):
496      return s.replace('"',r'\"').replace(r'\ ',r'\\ ') # novermin
497    fd = open(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
498    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
499    fd.write('\"-----------------------------------------\\n\"\n')
500    buildhost = platform.node()
501    if os.environ.get('SOURCE_DATE_EPOCH'):
502      buildhost = "reproducible"
503    buildtime = datetime.datetime.utcfromtimestamp(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))
504    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (buildtime, buildhost))
505    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
506    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.installdir.petscDir)))
507    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.installdir.petscArch)))
508    fd.write('\"-----------------------------------------\\n\";\n')
509    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
510    self.setCompilers.pushLanguage(self.languages.clanguage)
511    fd.write('\"Using C compiler: %s %s \\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
512    self.setCompilers.popLanguage()
513    if hasattr(self.compilers, 'FC'):
514      self.setCompilers.pushLanguage('FC')
515      fd.write('\"Using Fortran compiler: %s %s  %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
516      self.setCompilers.popLanguage()
517    fd.write('\"-----------------------------------------\\n\";\n')
518    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
519    fd.write('\"Using include paths: %s\\n\"\n' % (escape(self.PETSC_CC_INCLUDES_INSTALL.replace('${PETSC_DIR}', self.installdir.petscDir))))
520    fd.write('\"-----------------------------------------\\n\";\n')
521    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
522    self.setCompilers.pushLanguage(self.languages.clanguage)
523    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
524    self.setCompilers.popLanguage()
525    if hasattr(self.compilers, 'FC'):
526      self.setCompilers.pushLanguage('FC')
527      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
528      self.setCompilers.popLanguage()
529    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)))
530    fd.write('\"-----------------------------------------\\n\";\n')
531    fd.close()
532    return
533
534  def configurePrefetch(self):
535    '''Sees if there are any prefetch functions supported'''
536    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
537      self.addDefine('Prefetch(a,b,c)', ' ')
538      return
539    self.pushLanguage(self.languages.clanguage)
540    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
541      # The Intel Intrinsics manual [1] specifies the prototype
542      #
543      #   void _mm_prefetch(char const *a, int sel);
544      #
545      # but other vendors seem to insist on using subtly different
546      # prototypes, including void* for the pointer, and an enum for
547      # sel.  These are both reasonable changes, but negatively impact
548      # portability.
549      #
550      # [1] https://software.intel.com/file/6373
551      self.addDefine('HAVE_XMMINTRIN_H', 1)
552      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
553      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
554      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
555      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
556      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
557    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
558      self.addDefine('HAVE_XMMINTRIN_H', 1)
559      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
560      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
561      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
562      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
563      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
564    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
565      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
566      #
567      #   The value of rw is a compile-time constant one or zero; one
568      #   means that the prefetch is preparing for a write to the memory
569      #   address and zero, the default, means that the prefetch is
570      #   preparing for a read. The value locality must be a compile-time
571      #   constant integer between zero and three. A value of zero means
572      #   that the data has no temporal locality, so it need not be left
573      #   in the cache after the access. A value of three means that the
574      #   data has a high degree of temporal locality and should be left
575      #   in all levels of cache possible. Values of one and two mean,
576      #   respectively, a low or moderate degree of temporal locality.
577      #
578      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
579      # hints.  Using macros for these values in necessary since some
580      # compilers require an enum.
581      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
582      self.addDefine('PREFETCH_HINT_NTA', '0')
583      self.addDefine('PREFETCH_HINT_T0',  '3')
584      self.addDefine('PREFETCH_HINT_T1',  '2')
585      self.addDefine('PREFETCH_HINT_T2',  '1')
586    else:
587      self.addDefine('Prefetch(a,b,c)', ' ')
588    self.popLanguage()
589
590  def delGenFiles(self):
591    '''Delete generated files'''
592    delfile = os.path.join(self.arch.arch,'lib','petsc','conf','files')
593    try:
594      os.unlink(delfile)
595    except: pass
596
597  def configureAtoll(self):
598    '''Checks if atoll exists'''
599    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'):
600       self.addDefine('HAVE_ATOLL', '1')
601
602  def configureUnused(self):
603    '''Sees if __attribute((unused)) is supported'''
604    if self.framework.argDB['with-ios']:
605      self.addDefine('UNUSED', ' ')
606      return
607    self.pushLanguage(self.languages.clanguage)
608    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'):
609      self.addDefine('UNUSED', '__attribute((unused))')
610    else:
611      self.addDefine('UNUSED', ' ')
612    self.popLanguage()
613
614  def configureIsatty(self):
615    '''Check if the Unix C function isatty() works correctly
616       Actually just assumes it does not work correctly on batch systems'''
617    if not self.framework.argDB['with-batch']:
618      self.addDefine('USE_ISATTY',1)
619
620  def configureDeprecated(self):
621    '''Check if __attribute((deprecated)) is supported'''
622    def checkDeprecated(macro_base, src, is_intel):
623      '''
624      run through the various attribute deprecated combinations and define MACRO_BAS(why) to the result
625      it if it compiles.
626
627      If none of the combos work, defines MACRO_BASE(why) as empty
628      '''
629      full_macro_name = macro_base + '(why)'
630      for prefix in ('__attribute__', '__attribute','__declspec'):
631        if prefix == '__declspec':
632          # declspec does not have an extra set of brackets around the arguments
633          attr_bodies = ('deprecated(why)', 'deprecated')
634        else:
635          attr_bodies = ('(deprecated(why))', '(deprecated)')
636
637        for attr_body in attr_bodies:
638          attr_def = '{}({})'.format(prefix, attr_body)
639          test_src = '\n'.join((
640            '#define {} {}'.format(full_macro_name, attr_def),
641            src.format(macro_base + '("asdasdadsasd")')
642          ))
643          if self.checkCompile(test_src, ''):
644            self.logPrint('configureDeprecated: \'{}\' appears to work'.format(attr_def))
645            if is_intel and '(why)' in attr_body:
646              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))
647              self.logPrint('*** WE WILL THEREFORE REJECT \'{}\' AND CONTINUE TESTING ***'.format(attr_def))
648              continue
649            self.addDefine(full_macro_name, attr_def)
650            return
651
652      self.addDefine(full_macro_name, ' ')
653      return
654
655    lang = self.languages.clanguage
656    with self.Language(lang):
657      is_intel = self.setCompilers.isIntel(self.getCompiler(lang=lang), self.log)
658      checkDeprecated('DEPRECATED_FUNCTION', '{} int myfunc(void) {{ return 1; }}', is_intel)
659      checkDeprecated('DEPRECATED_TYPEDEF', 'typedef int my_int {};', is_intel)
660      checkDeprecated('DEPRECATED_ENUM', 'enum E {{ oldval {}, newval }};', is_intel)
661      # I was unable to make a CPP macro that takes the old and new values as separate
662      # arguments and builds the message needed by _Pragma hence the deprecation message is
663      # handled as it is
664      if self.checkCompile('#define TEST _Pragma("GCC warning \"Testing _Pragma\"") value'):
665        self.addDefine('DEPRECATED_MACRO(why)', '_Pragma(why)')
666      else:
667        self.addDefine('DEPRECATED_MACRO(why)', ' ')
668
669  def configureAlign(self):
670    '''Check if __attribute(aligned) is supported'''
671    code = '''\
672struct mystruct {int myint;} __attribute((aligned(16)));
673char assert_aligned[(sizeof(struct mystruct)==16)*2-1];
674'''
675    self.pushLanguage(self.languages.clanguage)
676    if self.checkCompile(code):
677      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned(size)))')
678      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
679    else:
680      self.framework.logPrint('Incorrect attribute(aligned)')
681      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
682    self.popLanguage()
683    return
684
685  def configureExpect(self):
686    '''Sees if the __builtin_expect directive is supported'''
687    self.pushLanguage(self.languages.clanguage)
688    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
689      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
690    self.popLanguage()
691
692  def configureFunctionName(self):
693    '''Sees if the compiler supports __func__ or a variant.'''
694    def getFunctionName(lang):
695      name = '"unknown"'
696      self.pushLanguage(lang)
697      for fname in ['__func__','__FUNCTION__','__extension__ __func__']:
698        code = "if ("+fname+"[0] != 'm') return 1;"
699        if self.checkCompile('',code) and self.checkLink('',code):
700          name = fname
701          break
702      self.popLanguage()
703      return name
704    langs = []
705
706    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
707    if hasattr(self.compilers, 'CXX'):
708      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
709
710  def configureIntptrt(self):
711    '''Determine what to use for uintptr_t'''
712    def staticAssertSizeMatchesVoidStar(inc,typename):
713      # The declaration is an error if either array size is negative.
714      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
715      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
716                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
717    self.pushLanguage(self.languages.clanguage)
718    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x; (void)i'):
719      self.addDefine('UINTPTR_T', 'uintptr_t')
720    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
721      self.addDefine('UINTPTR_T', 'unsigned long long')
722    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
723      self.addDefine('UINTPTR_T', 'size_t')
724    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
725      self.addDefine('UINTPTR_T', 'unsigned long')
726    elif staticAssertSizeMatchesVoidStar('','unsigned'):
727      self.addDefine('UINTPTR_T', 'unsigned')
728    else:
729      raise RuntimeError('Could not find any unsigned integer type matching void*')
730    self.popLanguage()
731
732  def configureRTLDDefault(self):
733    '''Check for dynamic library feature'''
734    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
735      self.addDefine('HAVE_RTLD_DEFAULT','1')
736    return
737
738  def configureSolaris(self):
739    '''Solaris specific stuff'''
740    if os.path.isdir(os.path.join('/usr','ucblib')):
741      try:
742        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
743      except AttributeError:
744        flag = None
745      if flag is None:
746        self.compilers.LIBS += ' -L/usr/ucblib'
747      else:
748        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
749    return
750
751  def configureDarwin(self):
752    '''Log brew configuration for Apple systems'''
753    try:
754      self.executeShellCommand(['brew', 'config'], log = self.log)
755      self.executeShellCommand(['brew', 'info', 'gcc'], log = self.log)
756    except:
757      pass
758    return
759
760  def configureLinux(self):
761    '''Linux specific stuff'''
762    # TODO: Test for this by mallocing an odd number of floats and checking the address
763    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
764    return
765
766  def configureWin32(self):
767    '''Win32 non-cygwin specific stuff'''
768    kernel32=0
769    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'):
770      self.addDefine('HAVE_WINDOWS_H',1)
771      self.addDefine('HAVE_GETCOMPUTERNAME',1)
772      kernel32=1
773    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <windows.h>', call='GetComputerName(NULL,NULL);'):
774      self.addDefine('HAVE_WINDOWS_H',1)
775      self.addDefine('HAVE_GETCOMPUTERNAME',1)
776      kernel32=1
777    if kernel32:
778      if self.framework.argDB['with-windows-graphics']:
779        self.addDefine('USE_WINDOWS_GRAPHICS',1)
780      if self.checkLink('#include <windows.h>','LoadLibrary(0)'):
781        self.addDefine('HAVE_LOADLIBRARY',1)
782      if self.checkLink('#include <windows.h>','GetProcAddress(0,0)'):
783        self.addDefine('HAVE_GETPROCADDRESS',1)
784      if self.checkLink('#include <windows.h>','FreeLibrary(0)'):
785        self.addDefine('HAVE_FREELIBRARY',1)
786      if self.checkLink('#include <windows.h>','GetLastError()'):
787        self.addDefine('HAVE_GETLASTERROR',1)
788      if self.checkLink('#include <windows.h>','SetLastError(0)'):
789        self.addDefine('HAVE_SETLASTERROR',1)
790      if self.checkLink('#include <windows.h>\n','QueryPerformanceCounter(0);\n'):
791        self.addDefine('USE_MICROSOFT_TIME',1)
792    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'):
793      self.addDefine('HAVE_GET_USER_NAME',1)
794    elif self.libraries.add('advapi32','GetUserName',prototype='#include <windows.h>', call='GetUserName(NULL,NULL);'):
795      self.addDefine('HAVE_GET_USER_NAME',1)
796
797    if not self.libraries.add('User32.lib','GetDC',prototype='#include <windows.h>',call='GetDC(0);'):
798      self.libraries.add('user32','GetDC',prototype='#include <windows.h>',call='GetDC(0);')
799    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);'):
800      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <windows.h>',call='CreateCompatibleDC(0);')
801
802    self.types.check('int32_t', 'int')
803    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n(void)u'):
804      self.addTypedef('int', 'uid_t')
805      self.addTypedef('int', 'gid_t')
806    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n(void)a'):
807      self.framework.addDefine('R_OK', '04')
808      self.framework.addDefine('W_OK', '02')
809      self.framework.addDefine('X_OK', '01')
810    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
811      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
812      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
813    if self.checkCompile('#include <windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
814      self.addDefine('HAVE_LARGE_INTEGER_U',1)
815
816    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
817    if self.checkCompile('#include <windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
818      self.addDefine('HAVE_O_BINARY',1)
819
820    if self.compilers.CC.find('win32fe') >= 0:
821      self.addDefine('HAVE_WINDOWS_COMPILERS',1)
822      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
823      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
824      self.addDefine('CANNOT_START_DEBUGGER',1)
825      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.installdir.petscDir, log = self.log)
826      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
827      (petscdir,error,status) = self.executeShellCommand('cygpath -m '+self.installdir.petscDir, log = self.log)
828      self.addMakeMacro('wPETSC_DIR',petscdir)
829      if self.dataFilesPath.datafilespath:
830        (datafilespath,error,status) = self.executeShellCommand('cygpath -m '+self.dataFilesPath.datafilespath, log = self.log)
831        self.addMakeMacro('DATAFILESPATH',datafilespath)
832
833    else:
834      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
835      self.addDefine('DIR_SEPARATOR','\'/\'')
836      self.addDefine('DIR','"'+self.installdir.petscDir+'"')
837      self.addMakeMacro('wPETSC_DIR',self.installdir.petscDir)
838      if self.dataFilesPath.datafilespath:
839        self.addMakeMacro('DATAFILESPATH',self.dataFilesPath.datafilespath)
840    self.addDefine('ARCH','"'+self.installdir.petscArch+'"')
841    return
842
843#-----------------------------------------------------------------------------------------------------
844  def configureCygwinBrokenPipe(self):
845    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
846    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
847    if config.setCompilers.Configure.isCygwin(self.log):
848      import platform
849      import re
850      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
851      m=r.match(platform.release())
852      major=int(m.group(1))
853      minor=int(m.group(2))
854      subminor=int(m.group(3))
855      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
856        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
857    return
858
859#-----------------------------------------------------------------------------------------------------
860  def configureDefaultArch(self):
861    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
862    if self.framework.argDB['with-default-arch']:
863      fd = open(conffile, 'w')
864      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
865      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
866      fd.write('include '+os.path.join('$(PETSC_DIR)','$(PETSC_ARCH)','lib','petsc','conf','petscvariables')+'\n')
867      fd.close()
868      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
869    elif os.path.isfile(conffile):
870      try:
871        os.unlink(conffile)
872      except:
873        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
874    return
875
876#-----------------------------------------------------------------------------------------------------
877  def configureScript(self):
878    '''Output a script in the conf directory which will reproduce the configuration'''
879    import nargs
880    import sys
881    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
882    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
883    if 'with-clean' in args:
884      del args['with-clean']
885    if 'force' in args:
886      del args['force']
887    if 'configModules' in args:
888      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
889        del args['configModules']
890    if 'optionsModule' in args:
891      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
892        del args['optionsModule']
893    if not 'PETSC_ARCH' in args:
894      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
895    f = open(scriptName, 'w')
896    f.write('#!'+sys.executable+'\n')
897    f.write('if __name__ == \'__main__\':\n')
898    f.write('  import sys\n')
899    f.write('  import os\n')
900    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
901    f.write('  import configure\n')
902    # pretty print repr(args.values())
903    f.write('  configure_options = [\n')
904    for itm in sorted(args.values()):
905      f.write('    \''+str(itm)+'\',\n')
906    f.write('  ]\n')
907    f.write('  configure.petsc_configure(configure_options)\n')
908    f.close()
909    try:
910      os.chmod(scriptName, 0o775)
911    except OSError as e:
912      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
913    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
914    return
915
916  def configureInstall(self):
917    '''Setup the directories for installation'''
918    if self.framework.argDB['prefix']:
919      self.addMakeRule('print_mesg_after_build','',
920       ['-@echo "========================================="',
921        '-@echo "Now to install the libraries do:"',
922        '-@echo "%s${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"' % self.installdir.installSudo,
923        '-@echo "========================================="'])
924    else:
925      self.addMakeRule('print_mesg_after_build','',
926       ['-@echo "========================================="',
927        '-@echo "Now to check if the libraries are working do:"',
928        '-@echo "${MAKE_USER} PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} check"',
929        '-@echo "========================================="'])
930      return
931
932  def configureGCOV(self):
933    '''Checking for configuring with gcov, from --with-gcov'''
934    if self.framework.argDB['with-gcov']:
935      self.addDefine('USE_GCOV','1')
936    return
937
938  def postProcessPackages(self):
939    postPackages=[]
940    for i in self.framework.packages:
941      if hasattr(i,'postProcess'): postPackages.append(i)
942    if postPackages:
943      # ctetgen needs petsc conf files. so attempt to create them early
944      self.framework.dumpConfFiles()
945      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
946      for i in postPackages:
947        if i.name.upper() in ['PFLOTRAN']:
948          i.postProcess()
949          postPackages.remove(i)
950      for i in postPackages: i.postProcess()
951      for i in postPackages:
952        if i.installedpetsc:
953          self.installed = 1
954          break
955    return
956
957  def configure(self):
958    if 'package-prefix-hash' in self.argDB:
959      # turn off prefix if it was only used to for installing external packages.
960      self.framework.argDB['prefix'] = ''
961      self.dir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch))
962      self.installdir.dir = self.dir
963      self.installdir.petscDir = self.petscdir.dir
964      self.petscDir = self.petscdir.dir
965      self.petscArch = self.arch.arch
966      self.addMakeMacro('PREFIXDIR',self.dir)
967      self.confDir = os.path.abspath(os.path.join(self.petscdir.dir, self.arch.arch))
968
969    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
970      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
971    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
972      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
973    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
974      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')
975    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)):
976      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
977    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
978    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
979    self.framework.poisonheader    = os.path.join(self.arch.arch,'include','petscconf_poison.h')
980    self.framework.pkgheader       = os.path.join(self.arch.arch,'include','petscpkg_version.h')
981    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
982    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
983    if self.libraries.math is None:
984      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
985    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
986      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
987    self.executeTest(self.configureRTLDDefault)
988    self.executeTest(self.configurePrefetch)
989    self.executeTest(self.configureUnused)
990    self.executeTest(self.configureDeprecated)
991    self.executeTest(self.configureIsatty)
992    self.executeTest(self.configureExpect)
993    self.executeTest(self.configureAlign)
994    self.executeTest(self.configureFunctionName)
995    self.executeTest(self.configureIntptrt)
996    self.executeTest(self.configureSolaris)
997    self.executeTest(self.configureLinux)
998    self.executeTest(self.configureDarwin)
999    self.executeTest(self.configureWin32)
1000    self.executeTest(self.configureCygwinBrokenPipe)
1001    self.executeTest(self.configureDefaultArch)
1002    self.executeTest(self.configureScript)
1003    self.executeTest(self.configureInstall)
1004    self.executeTest(self.configureGCOV)
1005    self.executeTest(self.configureAtoll)
1006
1007    self.Dump()
1008    self.dumpConfigInfo()
1009    self.dumpMachineInfo()
1010    self.delGenFiles()
1011    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
1012    self.framework.storeSubstitutions(self.framework.argDB)
1013    self.framework.argDB['configureCache'] = pickle.dumps(self.framework)
1014    self.framework.argDB.save(force = True)
1015    self.DumpPkgconfig('PETSc.pc')
1016    self.DumpPkgconfig('petsc.pc')
1017    self.DumpModule()
1018    self.postProcessPackages()
1019    self.framework.log.write('================================================================================\n')
1020    self.logClear()
1021    return
1022