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