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