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