xref: /petsc/config/PETSc/Configure.py (revision a29ed550261602abefbc7e53cb3da0d66e185d86)
1import config.base
2
3import os
4import sys
5import re
6import cPickle
7
8# The sorted() builtin is not available with python-2.3
9try: sorted
10except NameError:
11  def sorted(lst):
12    lst.sort()
13    return lst
14
15class Configure(config.base.Configure):
16  def __init__(self, framework):
17    config.base.Configure.__init__(self, framework)
18    self.headerPrefix = 'PETSC'
19    self.substPrefix  = 'PETSC'
20    self.installed = 0 # 1 indicates that Configure itself has already compiled and installed PETSc
21    return
22
23  def __str2__(self):
24    desc = []
25    if not self.installed:
26      desc.append('xxx=========================================================================xxx')
27      if self.make.getMakeMacro('MAKE_IS_GNUMAKE'):
28        build_type = 'gnumake build'
29      elif self.getMakeMacro('PETSC_BUILD_USING_CMAKE'):
30        build_type = 'cmake build'
31      else:
32        build_type = 'legacy build'
33      desc.append(' Configure stage complete. Now build PETSc libraries with (%s):' % build_type)
34      desc.append('   make PETSC_DIR='+self.petscdir.dir+' PETSC_ARCH='+self.arch.arch+' all')
35      desc.append('xxx=========================================================================xxx')
36    else:
37      desc.append('xxx=========================================================================xxx')
38      desc.append(' Installation complete. You do not need to run make to compile or install the software')
39      desc.append('xxx=========================================================================xxx')
40    return '\n'.join(desc)+'\n'
41
42  def setupHelp(self, help):
43    import nargs
44    help.addArgument('PETSc',  '-prefix=<dir>',                   nargs.Arg(None, '', 'Specifiy location to install PETSc (eg. /usr/local)'))
45    help.addArgument('PETSc',  '-with-prefetch=<bool>',           nargs.ArgBool(None, 1,'Enable checking for prefetch instructions'))
46    help.addArgument('Windows','-with-windows-graphics=<bool>',   nargs.ArgBool(None, 1,'Enable check for Windows Graphics'))
47    help.addArgument('PETSc', '-with-default-arch=<bool>',        nargs.ArgBool(None, 1, 'Allow using the last configured arch without setting PETSC_ARCH'))
48    help.addArgument('PETSc','-with-single-library=<bool>',       nargs.ArgBool(None, 1,'Put all PETSc code into the single -lpetsc library'))
49    help.addArgument('PETSc', '-with-ios=<bool>',              nargs.ArgBool(None, 0, 'Build an iPhone/iPad version of PETSc library'))
50    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'))
51    help.addArgument('PETSc', '-known-has-attribute-aligned=<bool>',nargs.ArgBool(None, None, 'Indicates __attribute((aligned(16)) directive works (the usual test will be skipped)'))
52    help.addArgument('PETSc','-with-viewfromoptions=<bool>',      nargs.ArgBool(None, 1,'Support XXXSetFromOptions() calls, for calls with many small solvers turn this off'))
53
54    return
55
56  def registerPythonFile(self,filename,directory):
57    ''' Add a python file to the framework and registers its headerprefix, ... externalpackagedir
58        directory is the directory where the file relative to the BuildSystem or config path in python notation with . '''
59    (utilityName, ext) = os.path.splitext(filename)
60    if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__':
61      if directory: directory = directory+'.'
62      utilityObj                             = self.framework.require(directory+utilityName, self)
63      utilityObj.headerPrefix                = self.headerPrefix
64      utilityObj.archProvider                = self.arch
65      utilityObj.languageProvider            = self.languages
66      utilityObj.installDirProvider          = self.installdir
67      utilityObj.externalPackagesDirProvider = self.externalpackagesdir
68      utilityObj.precisionProvider           = self.scalartypes
69      utilityObj.indexProvider               = self.indexTypes
70      setattr(self, utilityName.lower(), utilityObj)
71
72  def setupDependencies(self, framework):
73    config.base.Configure.setupDependencies(self, framework)
74    self.programs      = framework.require('config.programs',           self)
75    self.setCompilers  = framework.require('config.setCompilers',       self)
76    self.compilers     = framework.require('config.compilers',          self)
77    self.arch          = framework.require('PETSc.options.arch',        self.setCompilers)
78    self.petscdir      = framework.require('PETSc.options.petscdir',    self.arch)
79    self.installdir    = framework.require('PETSc.options.installDir',  self)
80    self.scalartypes   = framework.require('PETSc.options.scalarTypes', self)
81    self.indexTypes    = framework.require('PETSc.options.indexTypes',  self)
82    self.languages     = framework.require('PETSc.options.languages',   self.setCompilers)
83    self.debugging     = framework.require('PETSc.options.debugging',   self.compilers)
84    self.indexTypes    = framework.require('PETSc.options.indexTypes',  self.compilers)
85    self.compilers     = framework.require('config.compilers',          self)
86    self.types         = framework.require('config.types',              self)
87    self.headers       = framework.require('config.headers',            self)
88    self.functions     = framework.require('config.functions',          self)
89    self.libraries     = framework.require('config.libraries',          self)
90    self.atomics       = framework.require('config.atomics',            self)
91    self.make          = framework.require('config.packages.make',      self)
92    self.blasLapack    = framework.require('config.packages.BlasLapack',self)
93    self.cmake         = framework.require('config.packages.cmake',self)
94    self.externalpackagesdir = framework.require('PETSc.options.externalpackagesdir',self)
95    self.mpi           = framework.require('config.packages.MPI',self)
96
97    for utility in os.listdir(os.path.join('config','PETSc','options')):
98      self.registerPythonFile(utility,'PETSc.options')
99
100    for utility in os.listdir(os.path.join('config','BuildSystem','config','utilities')):
101      self.registerPythonFile(utility,'config.utilities')
102
103    for package in os.listdir(os.path.join('config', 'BuildSystem', 'config', 'packages')):
104      self.registerPythonFile(package,'config.packages')
105
106    # Force blaslapack and opencl to depend on scalarType so precision is set before BlasLapack is built
107    framework.require('PETSc.options.scalarTypes', self.f2cblaslapack)
108    framework.require('PETSc.options.scalarTypes', self.fblaslapack)
109    framework.require('PETSc.options.scalarTypes', self.blaslapack)
110    framework.require('PETSc.options.scalarTypes', self.opencl)
111    framework.require('PETSc.Regression', self)
112
113    self.programs.headerPrefix   = self.headerPrefix
114    self.compilers.headerPrefix  = self.headerPrefix
115    self.types.headerPrefix      = self.headerPrefix
116    self.headers.headerPrefix    = self.headerPrefix
117    self.functions.headerPrefix  = self.headerPrefix
118    self.libraries.headerPrefix  = self.headerPrefix
119
120    # Look for any user provided --download-xxx=directory packages
121    for arg in sys.argv:
122      if arg.startswith('--download-') and arg.find('=') > -1:
123        pname = arg[11:arg.find('=')]
124        if not hasattr(self,pname):
125          dname = os.path.dirname(arg[arg.find('=')+1:])
126          if os.path.isdir(dname) and not os.path.isfile(os.path.join(dname,pname+'.py')):
127            self.framework.logPrint('User is registering a new package: '+arg)
128            sys.path.append(dname)
129            self.registerPythonFile(pname+'.py','')
130
131    # test for a variety of basic headers and functions
132    headersC = map(lambda name: name+'.h', ['setjmp','dos', 'endian', 'fcntl', 'float', 'io', 'limits', 'malloc', 'pwd', 'search', 'strings',
133                                            'unistd', 'sys/sysinfo', 'machine/endian', 'sys/param', 'sys/procfs', 'sys/resource',
134                                            'sys/systeminfo', 'sys/times', 'sys/utsname','string', 'stdlib',
135                                            'sys/socket','sys/wait','netinet/in','netdb','Direct','time','Ws2tcpip','sys/types',
136                                            'WindowsX', 'cxxabi','float','ieeefp','stdint','sched','pthread','mathimf','inttypes'])
137    functions = ['access', '_access', 'clock', 'drand48', 'getcwd', '_getcwd', 'getdomainname', 'gethostname',
138                 'gettimeofday', 'getwd', 'memalign', 'memmove', 'mkstemp', 'popen', 'PXFGETARG', 'rand', 'getpagesize',
139                 'readlink', 'realpath',  'sigaction', 'signal', 'sigset', 'usleep', 'sleep', '_sleep', 'socket',
140                 'times', 'gethostbyname', 'uname','snprintf','_snprintf','lseek','_lseek','time','fork','stricmp',
141                 'strcasecmp', 'bzero', 'dlopen', 'dlsym', 'dlclose', 'dlerror','get_nprocs','sysctlbyname',
142                 '_set_output_format','_mkdir']
143    libraries1 = [(['socket', 'nsl'], 'socket'), (['fpe'], 'handle_sigfpes')]
144    self.headers.headers.extend(headersC)
145    self.functions.functions.extend(functions)
146    self.libraries.libraries.extend(libraries1)
147
148    return
149
150  def DumpPkgconfig(self):
151    ''' Create a pkg-config file '''
152    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig')):
153      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig'))
154    fd = open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','pkgconfig','PETSc.pc'),'w')
155    if self.framework.argDB['prefix']:
156      fd.write('prefix='+self.installdir.dir+'\n')
157      fd.write('exec_prefix=${prefix}\n')
158      fd.write('includedir=${prefix}/include\n')
159    else:
160      fd.write('prefix='+self.petscdir.dir+'\n')
161      fd.write('exec_prefix=${prefix}\n')
162      fd.write('includedir=${prefix}/include\n')
163    fd.write('libdir='+os.path.join(self.installdir.dir,'lib')+'\n')
164
165    self.setCompilers.pushLanguage('C')
166    fd.write('ccompiler='+self.setCompilers.getCompiler()+'\n')
167    self.setCompilers.popLanguage()
168    if hasattr(self.compilers, 'C++'):
169      self.setCompilers.pushLanguage('C++')
170      fd.write('cxxcompiler='+self.setCompilers.getCompiler()+'\n')
171      self.setCompilers.popLanguage()
172    if hasattr(self.compilers, 'FC'):
173      self.setCompilers.pushLanguage('FC')
174      fd.write('fcompiler='+self.setCompilers.getCompiler()+'\n')
175      self.setCompilers.popLanguage()
176    fd.write('blaslapacklibs='+self.libraries.toStringNoDupes(self.blaslapack.lib)+'\n')
177
178    fd.write('\n')
179    fd.write('Name: PETSc\n')
180    fd.write('Description: Library to solve ODEs and algebraic equations\n')
181    fd.write('Version: %s\n' % self.petscdir.version)
182
183    fd.write('Cflags: '+self.allincludes+'\n')
184
185    plibs = self.libraries.toStringNoDupes(['-L'+os.path.join(self.petscdir.dir,self.arch.arch,'lib'), self.petsclib])
186    if self.framework.argDB['prefix']:
187      fd.write('Libs: '+plibs.replace(os.path.join(self.petscdir.dir,self.arch.arch),self.installdir.dir)+'\n')
188    else:
189      fd.write('Libs: '+plibs+'\n')
190    fd.write('Libs.private: '+self.libraries.toStringNoDupes(self.packagelibs+self.libraries.math+self.compilers.flibs+self.compilers.cxxlibs)+' '+self.compilers.LIBS+'\n')
191
192    fd.close()
193    return
194
195  def DumpModule(self):
196    ''' Create a module file '''
197    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules')):
198      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules'))
199    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc')):
200      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc'))
201    if self.framework.argDB['prefix']:
202      installdir  = self.installdir.dir
203      installarch = ''
204      installpath = os.path.join(installdir,'bin')
205    else:
206      installdir  = self.petscdir.dir
207      installarch = self.arch.arch
208      installpath = os.path.join(installdir,installarch,'bin')+':'+os.path.join(installdir,'bin')
209    fd = open(os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','modules','petsc',self.petscdir.version),'w')
210    fd.write('''\
211#%%Module
212
213proc ModulesHelp { } {
214    puts stderr "This module sets the path and environment variables for petsc-%s"
215    puts stderr "     see http://www.mcs.anl.gov/petsc/ for more information      "
216    puts stderr ""
217}
218module-whatis "PETSc - Portable, Extensible Toolkit for Scientific Computation"
219
220set petsc_dir   %s
221set petsc_arch  %s
222
223setenv PETSC_ARCH $petsc_arch
224setenv PETSC_DIR $petsc_dir
225prepend-path PATH %s
226''' % (self.petscdir.version, installdir, installarch, installpath))
227    fd.close()
228    return
229
230  def Dump(self):
231    ''' Actually put the values into the configuration files '''
232    # eventually everything between -- should be gone
233    if self.mpi.usingMPIUni:
234      #
235      # Remove any MPI/MPICH include files that may have been put here by previous runs of ./configure
236      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)
237
238#-----------------------------------------------------------------------------------------------------
239
240    # Sometimes we need C compiler, even if built with C++
241    self.setCompilers.pushLanguage('C')
242    self.addMakeMacro('CC_FLAGS',self.setCompilers.getCompilerFlags())
243    self.setCompilers.popLanguage()
244
245    # And sometimes we need a C++ compiler even when PETSc is built with C
246    if hasattr(self.compilers, 'CXX'):
247      self.setCompilers.pushLanguage('Cxx')
248      self.addMakeMacro('CXX_FLAGS',self.setCompilers.getCompilerFlags())
249      self.setCompilers.popLanguage()
250
251    # C preprocessor values
252    self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS)
253
254    # compiler values
255    self.setCompilers.pushLanguage(self.languages.clanguage)
256    self.addMakeMacro('PCC',self.setCompilers.getCompiler())
257    self.addMakeMacro('PCC_FLAGS',self.setCompilers.getCompilerFlags())
258    self.setCompilers.popLanguage()
259    # .o or .obj
260    self.addMakeMacro('CC_SUFFIX','o')
261
262    # executable linker values
263    self.setCompilers.pushLanguage(self.languages.clanguage)
264    pcc_linker = self.setCompilers.getLinker()
265    self.addMakeMacro('PCC_LINKER',pcc_linker)
266    self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
267    self.setCompilers.popLanguage()
268    # '' for Unix, .exe for Windows
269    self.addMakeMacro('CC_LINKER_SUFFIX','')
270
271    if hasattr(self.compilers, 'FC'):
272      self.setCompilers.pushLanguage('FC')
273      # need FPPFLAGS in config/setCompilers
274      self.addDefine('HAVE_FORTRAN','1')
275      self.addMakeMacro('FPP_FLAGS',self.setCompilers.CPPFLAGS)
276
277      # compiler values
278      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
279      self.setCompilers.popLanguage()
280      # .o or .obj
281      self.addMakeMacro('FC_SUFFIX','o')
282
283      # executable linker values
284      self.setCompilers.pushLanguage('FC')
285      # Cannot have NAG f90 as the linker - so use pcc_linker as fc_linker
286      fc_linker = self.setCompilers.getLinker()
287      if config.setCompilers.Configure.isNAG(fc_linker, self.log):
288        self.addMakeMacro('FC_LINKER',pcc_linker)
289      else:
290        self.addMakeMacro('FC_LINKER',fc_linker)
291      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
292      # apple requires this shared library linker flag on SOME versions of the os
293      if self.setCompilers.getLinkerFlags().find('-Wl,-commons,use_dylibs') > -1:
294        self.addMakeMacro('DARWIN_COMMONS_USE_DYLIBS',' -Wl,-commons,use_dylibs ')
295      self.setCompilers.popLanguage()
296
297      # F90 Modules
298      if self.setCompilers.fortranModuleIncludeFlag:
299        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
300      else: # for non-f90 compilers like g77
301        self.addMakeMacro('FC_MODULE_FLAG', '-I')
302      if self.setCompilers.fortranModuleIncludeFlag:
303        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
304    else:
305      self.addMakeMacro('FC','')
306
307    if hasattr(self.compilers, 'CUDAC'):
308      self.setCompilers.pushLanguage('CUDA')
309      self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags())
310      self.setCompilers.popLanguage()
311
312    # shared library linker values
313    self.setCompilers.pushLanguage(self.languages.clanguage)
314    # need to fix BuildSystem to collect these separately
315    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
316    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
317    self.setCompilers.popLanguage()
318    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
319    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
320    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
321      self.addMakeMacro('SL_LINKER_SUFFIX', '')
322      self.addDefine('SLSUFFIX','""')
323    else:
324      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
325      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
326
327    self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}')
328
329#-----------------------------------------------------------------------------------------------------
330
331    # CONLY or CPP. We should change the PETSc makefiles to do this better
332    if self.languages.clanguage == 'C': lang = 'CONLY'
333    else: lang = 'CXXONLY'
334    self.addMakeMacro('PETSC_LANGUAGE',lang)
335
336    # real or complex
337    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
338    # double or float
339    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
340
341    if self.framework.argDB['with-batch']:
342      self.addMakeMacro('PETSC_WITH_BATCH','1')
343
344    # Test for compiler-specific macros that need to be defined.
345    if self.setCompilers.isCrayVector('CC', self.log):
346      self.addDefine('HAVE_CRAY_VECTOR','1')
347
348#-----------------------------------------------------------------------------------------------------
349    if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket') and self.headers.haveHeader('netinet/in.h'):
350      self.addDefine('USE_SOCKET_VIEWER','1')
351      if self.checkCompile('#include <sys/socket.h>','setsockopt(0,SOL_SOCKET,SO_REUSEADDR,0,0)'):
352        self.addDefine('HAVE_SO_REUSEADDR','1')
353
354#-----------------------------------------------------------------------------------------------------
355    # print include and lib for makefiles
356    self.framework.packages.reverse()
357    includes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')]
358    libs = []
359    for i in self.framework.packages:
360      if i.useddirectly:
361        self.addDefine('HAVE_'+i.PACKAGE.replace('-','_'), 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
362      if not isinstance(i.lib, list):
363        i.lib = [i.lib]
364      if i.linkedbypetsc: libs.extend(i.lib)
365      self.addMakeMacro(i.PACKAGE.replace('-','_')+'_LIB', self.libraries.toStringNoDupes(i.lib))
366      if hasattr(i,'include'):
367        if not isinstance(i.include,list):
368          i.include = [i.include]
369        includes.extend(i.include)
370        self.addMakeMacro(i.PACKAGE.replace('-','_')+'_INCLUDE',self.headers.toStringNoDupes(i.include))
371    self.packagelibs = libs
372    if self.framework.argDB['with-single-library']:
373      self.petsclib = '-lpetsc'
374    else:
375      self.petsclib = '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys'
376    self.alllibs = self.libraries.toStringNoDupes(['-L'+os.path.join(self.petscdir.dir,self.arch.arch,'lib'), self.petsclib]+libs+self.libraries.math+self.compilers.flibs+self.compilers.cxxlibs)+' '+self.compilers.LIBS
377    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(libs+self.libraries.math+self.compilers.flibs+self.compilers.cxxlibs)+' '+self.compilers.LIBS
378    if self.framework.argDB['prefix'] and self.setCompilers.CSharedLinkerFlag not in ['-L']:
379      lib_basic = self.PETSC_EXTERNAL_LIB_BASIC.replace(self.setCompilers.CSharedLinkerFlag+os.path.join(self.petscdir.dir,self.arch.arch,'lib'),self.setCompilers.CSharedLinkerFlag+os.path.join(self.installdir.dir,'lib'))
380    else:
381      lib_basic = self.PETSC_EXTERNAL_LIB_BASIC
382    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',lib_basic)
383    self.allincludes = self.headers.toStringNoDupes(includes)
384    self.addMakeMacro('PETSC_CC_INCLUDES',self.allincludes)
385    self.PETSC_CC_INCLUDES = self.allincludes
386    if hasattr(self.compilers, 'FC'):
387      if self.compilers.fortranIsF90:
388        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes,includes))
389      else:
390        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes))
391
392    self.addMakeMacro('DESTDIR',self.installdir.dir)
393    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir.dir,'lib')+'"')
394
395    if self.framework.argDB['with-single-library']:
396      # overrides the values set in conf/variables
397      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
398      self.addMakeMacro('SHLIBS','libpetsc')
399      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
400      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
401      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
402      self.addMakeMacro('PETSC_TAO_LIB_BASIC','-lpetsc')
403      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',self.alllibs)
404      self.addDefine('USE_SINGLE_LIBRARY', '1')
405      if self.sharedlibraries.useShared:
406        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
407        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
408        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
409        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
410        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
411        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
412        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
413        self.addMakeMacro('PETSC_TAO_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
414        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
415        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
416        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
417      else:
418        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
419        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
420        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
421        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
422        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
423        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
424        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
425        self.addMakeMacro('PETSC_TAO_LIB','${PETSC_WITH_EXTERNAL_LIB}')
426        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
427        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
428        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
429
430    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
431      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
432
433    # add a makefile entry for configure options
434    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
435    return
436
437  def dumpConfigInfo(self):
438    import time
439    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
440    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
441    fd.close()
442    return
443
444  def dumpMachineInfo(self):
445    import platform
446    import time
447    import script
448    def escape(s):
449      return s.replace('"',r'\"').replace(r'\ ',r'\\ ')
450    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
451    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
452    fd.write('\"-----------------------------------------\\n\"\n')
453    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
454    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
455    fd.write('\"Using PETSc directory: %s\\n\"\n' % (escape(self.petscdir.dir)))
456    fd.write('\"Using PETSc arch: %s\\n\"\n' % (escape(self.arch.arch)))
457    fd.write('\"-----------------------------------------\\n\";\n')
458    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
459    self.setCompilers.pushLanguage(self.languages.clanguage)
460    fd.write('\"Using C compiler: %s %s ${COPTFLAGS} ${CFLAGS}\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags())))
461    self.setCompilers.popLanguage()
462    if hasattr(self.compilers, 'FC'):
463      self.setCompilers.pushLanguage('FC')
464      fd.write('\"Using Fortran compiler: %s %s ${FOPTFLAGS} ${FFLAGS} %s\\n\"\n' % (escape(self.setCompilers.getCompiler()), escape(self.setCompilers.getCompilerFlags()), escape(self.setCompilers.CPPFLAGS)))
465      self.setCompilers.popLanguage()
466    fd.write('\"-----------------------------------------\\n\";\n')
467    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
468    fd.write('\"Using include paths: %s %s %s\\n\"\n' % ('-I'+escape(os.path.join(self.petscdir.dir, self.arch.arch, 'include')), '-I'+escape(os.path.join(self.petscdir.dir, 'include')), escape(self.PETSC_CC_INCLUDES)))
469    fd.write('\"-----------------------------------------\\n\";\n')
470    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
471    self.setCompilers.pushLanguage(self.languages.clanguage)
472    fd.write('\"Using C linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
473    self.setCompilers.popLanguage()
474    if hasattr(self.compilers, 'FC'):
475      self.setCompilers.pushLanguage('FC')
476      fd.write('\"Using Fortran linker: %s\\n\"\n' % (escape(self.setCompilers.getLinker())))
477      self.setCompilers.popLanguage()
478    fd.write('\"Using libraries: %s%s -L%s %s %s\\n\"\n' % (escape(self.setCompilers.CSharedLinkerFlag), escape(os.path.join(self.petscdir.dir, self.arch.arch, 'lib')), escape(os.path.join(self.petscdir.dir, self.arch.arch, 'lib')), escape(self.petsclib), escape(self.PETSC_EXTERNAL_LIB_BASIC)))
479    fd.write('\"-----------------------------------------\\n\";\n')
480    fd.close()
481    return
482
483  def dumpCMakeConfig(self):
484    '''
485    Writes configuration-specific values to ${PETSC_ARCH}/lib/petsc/conf/PETScBuildInternal.cmake.
486    This file is private to PETSc and should not be included by third parties
487    (a suitable file can be produced later by CMake, but this is not it).
488    '''
489    def cmakeset(fd,key,val=True):
490      if val == True: val = 'YES'
491      if val == False: val = 'NO'
492      fd.write('set (' + key + ' ' + val + ')\n')
493    def ensurelist(a):
494      if isinstance(a,list):
495        return a
496      else:
497        return [a]
498    def libpath(lib):
499      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
500      if not isinstance(lib,str): return ''
501      if lib.startswith('-L'): return lib[2:]
502      if lib.startswith('-R'): return lib[2:]
503      if lib.startswith('-Wl,-rpath,'):
504        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
505        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
506        # corresponding library.
507        return lib[len('-Wl,-rpath,'):]
508      if lib.startswith('-'): return ''
509      return os.path.dirname(lib)
510    def cleanlib(lib):
511      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
512      if not isinstance(lib,str): return ''
513      if lib.startswith('-l'):  return lib[2:]
514      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
515      lib = os.path.splitext(os.path.basename(lib))[0]
516      if lib.startswith('lib'): return lib[3:]
517      return lib
518    def nub(lst):
519      'Return a list containing the first occurrence of each unique element'
520      unique = []
521      for elem in lst:
522        if elem not in unique and elem != '':
523          unique.append(elem)
524      return unique
525    try: reversed # reversed was added in Python-2.4
526    except NameError:
527      def reversed(lst): return lst[::-1]
528    def nublast(lst):
529      'Return a list containing the last occurrence of each unique entry in a list'
530      return reversed(nub(reversed(lst)))
531    def cmakeexpand(varname):
532      return r'"${' + varname + r'}"'
533    def uniqextend(lst,new):
534      for x in ensurelist(new):
535        if x not in lst:
536          lst.append(x)
537    def notstandardinclude(path):
538      return path not in '/usr/include'.split() # /usr/local/include is not automatically included on FreeBSD
539    def writeMacroDefinitions(fd):
540      if self.mpi.usingMPIUni:
541        cmakeset(fd,'PETSC_HAVE_MPIUNI')
542      for pkg in self.framework.packages:
543        if pkg.useddirectly:
544          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE.replace('-','_'))
545        for pair in pkg.defines.items():
546          if pair[0].startswith('HAVE_') and pair[1]:
547            cmakeset(fd, self.framework.getFullDefineName(pkg, pair[0]), pair[1])
548      for name,val in self.functions.defines.items():
549        cmakeset(fd,'PETSC_'+name,val)
550      for dct in [self.defines, self.libraryoptions.defines]:
551        for k,v in dct.items():
552          if k.startswith('USE_'):
553            cmakeset(fd,'PETSC_' + k, v)
554      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
555      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
556      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
557      if hasattr(self.compilers, 'FC'):
558        cmakeset(fd,'PETSC_HAVE_FORTRAN')
559        if self.compilers.fortranIsF90:
560          cmakeset(fd,'PETSC_USING_F90')
561        if self.compilers.fortranIsF2003:
562          cmakeset(fd,'PETSC_USING_F2003')
563      if hasattr(self.compilers, 'CXX'):
564        cmakeset(fd,'PETSC_HAVE_CXX')
565      if self.sharedlibraries.useShared:
566        cmakeset(fd,'BUILD_SHARED_LIBS')
567    def writeBuildFlags(fd):
568      def extendby(lib):
569        libs = ensurelist(lib)
570        lib_paths.extend(map(libpath,libs))
571        lib_libs.extend(map(cleanlib,libs))
572      lib_paths = []
573      lib_libs  = []
574      includes  = []
575      libvars   = []
576      for pkg in self.framework.packages:
577        if pkg.linkedbypetsc:
578          extendby(pkg.lib)
579          uniqextend(includes,pkg.include)
580      extendby(self.libraries.math)
581      extendby(self.libraries.rt)
582      extendby(self.compilers.flibs)
583      extendby(self.compilers.cxxlibs)
584      extendby(self.compilers.LIBS.split())
585      for libname in nublast(lib_libs):
586        libvar = 'PETSC_' + libname.upper() + '_LIB'
587        addpath = ''
588        for lpath in nublast(lib_paths):
589          addpath += '"' + str(lpath) + '" '
590        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
591        libvars.append(libvar)
592      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
593      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
594      includes = filter(notstandardinclude,includes)
595      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',includes)) + ')\n')
596    fd = open(os.path.join(self.arch.arch,'lib','petsc','conf','PETScBuildInternal.cmake'), 'w')
597    writeMacroDefinitions(fd)
598    writeBuildFlags(fd)
599    fd.close()
600    return
601
602  def dumpCMakeLists(self):
603    import sys
604    if sys.version_info >= (2,4):
605      import cmakegen
606      try:
607        cmakegen.main(self.petscdir.dir, log=self.framework.log)
608      except (OSError), e:
609        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
610    else:
611      self.framework.logPrint('Skipping cmakegen due to old python version: ' +str(sys.version_info) )
612
613  def cmakeBoot(self):
614    import sys
615    self.cmakeboot_success = False
616    if sys.version_info >= (2,4) and hasattr(self.cmake,'cmake'):
617      oldRead = self.argDB.readonly
618      self.argDB.readonly = True
619      try:
620        import cmakeboot
621        self.cmakeboot_success = cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
622      except (OSError), e:
623        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
624      except (ImportError, KeyError), e:
625        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
626      self.argDB.readonly = oldRead
627      if self.cmakeboot_success:
628        if hasattr(self.compilers, 'FC') and self.compilers.fortranIsF90 and not self.setCompilers.fortranModuleOutputFlag:
629          self.framework.logPrint('CMake configured successfully, but could not be used by default because of missing fortranModuleOutputFlag\n')
630        else:
631          self.framework.logPrint('CMake configured successfully, using as default build\n')
632          self.addMakeMacro('PETSC_BUILD_USING_CMAKE',1)
633      else:
634        self.framework.logPrint('CMake configuration was unsuccessful\n')
635    else:
636      self.framework.logPrint('Skipping cmakeboot due to old python version: ' +str(sys.version_info) )
637    return
638
639  def configurePrefetch(self):
640    '''Sees if there are any prefetch functions supported'''
641    if config.setCompilers.Configure.isSolaris(self.log) or self.framework.argDB['with-ios'] or not self.framework.argDB['with-prefetch']:
642      self.addDefine('Prefetch(a,b,c)', ' ')
643      return
644    self.pushLanguage(self.languages.clanguage)
645    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
646      # The Intel Intrinsics manual [1] specifies the prototype
647      #
648      #   void _mm_prefetch(char const *a, int sel);
649      #
650      # but other vendors seem to insist on using subtly different
651      # prototypes, including void* for the pointer, and an enum for
652      # sel.  These are both reasonable changes, but negatively impact
653      # portability.
654      #
655      # [1] http://software.intel.com/file/6373
656      self.addDefine('HAVE_XMMINTRIN_H', 1)
657      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
658      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
659      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
660      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
661      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
662    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
663      self.addDefine('HAVE_XMMINTRIN_H', 1)
664      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
665      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
666      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
667      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
668      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
669    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
670      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
671      #
672      #   The value of rw is a compile-time constant one or zero; one
673      #   means that the prefetch is preparing for a write to the memory
674      #   address and zero, the default, means that the prefetch is
675      #   preparing for a read. The value locality must be a compile-time
676      #   constant integer between zero and three. A value of zero means
677      #   that the data has no temporal locality, so it need not be left
678      #   in the cache after the access. A value of three means that the
679      #   data has a high degree of temporal locality and should be left
680      #   in all levels of cache possible. Values of one and two mean,
681      #   respectively, a low or moderate degree of temporal locality.
682      #
683      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
684      # hints.  Using macros for these values in necessary since some
685      # compilers require an enum.
686      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
687      self.addDefine('PREFETCH_HINT_NTA', '0')
688      self.addDefine('PREFETCH_HINT_T0',  '3')
689      self.addDefine('PREFETCH_HINT_T1',  '2')
690      self.addDefine('PREFETCH_HINT_T2',  '1')
691    else:
692      self.addDefine('Prefetch(a,b,c)', ' ')
693    self.popLanguage()
694
695  def configureAtoll(self):
696    '''Checks if atoll exists'''
697    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")'):
698       self.addDefine('HAVE_ATOLL', '1')
699
700  def configureUnused(self):
701    '''Sees if __attribute((unused)) is supported'''
702    if self.framework.argDB['with-ios']:
703      self.addDefine('UNUSED', ' ')
704      return
705    self.pushLanguage(self.languages.clanguage)
706    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'):
707      self.addDefine('UNUSED', '__attribute((unused))')
708    else:
709      self.addDefine('UNUSED', ' ')
710    self.popLanguage()
711
712  def configureIsatty(self):
713    '''Check if the Unix C function isatty() works correctly
714       Actually just assumes it does not work correctly on batch systems'''
715    if not self.framework.argDB['with-batch']:
716      self.addDefine('USE_ISATTY',1)
717
718  def configureDeprecated(self):
719    '''Check if __attribute((deprecated)) is supported'''
720    self.pushLanguage(self.languages.clanguage)
721    ## Recent versions of gcc and clang support __attribute((deprecated("string argument"))), which is very useful, but
722    ## Intel has conspired to make a supremely environment-sensitive compiler.  The Intel compiler looks at the gcc
723    ## executable in the environment to determine the language compatibility that it should attempt to emulate.  Some
724    ## important Cray installations have built PETSc using the Intel compiler, but with a newer gcc module loaded (e.g.,
725    ## 4.7).  Thus at PETSc configure time, the Intel compiler decides to support the string argument, but the gcc
726    ## found in the default user environment is older and does not support the argument.  If GCC and Intel were cool
727    ## like Clang and supported __has_attribute, we could avoid configure tests entirely, but they don't.  And that is
728    ## why we can't have nice things.
729    #
730    # if self.checkCompile("""__attribute((deprecated("Why you shouldn't use myfunc"))) static int myfunc(void) { return 1;}""", ''):
731    #   self.addDefine('DEPRECATED(why)', '__attribute((deprecated(why)))')
732    if self.checkCompile("""__attribute((deprecated)) static int myfunc(void) { return 1;}""", ''):
733      self.addDefine('DEPRECATED(why)', '__attribute((deprecated))')
734    else:
735      self.addDefine('DEPRECATED(why)', ' ')
736    self.popLanguage()
737
738  def configureAlign(self):
739    '''Check if __attribute(align) is supported'''
740    filename = 'conftestalign'
741    includes = '''
742#include <sys/types.h>
743#if STDC_HEADERS
744#include <stdlib.h>
745#include <stdio.h>
746#include <stddef.h>
747#endif\n'''
748    body     = '''
749struct mystruct {int myint;} __attribute((aligned(16)));
750FILE *f = fopen("'''+filename+'''", "w");
751if (!f) exit(1);
752fprintf(f, "%lu\\n", (unsigned long)sizeof(struct mystruct));
753'''
754    if 'known-has-attribute-aligned' in self.argDB:
755      if self.argDB['known-has-attribute-aligned']:
756        size = 16
757      else:
758        size = -3
759    elif not self.argDB['with-batch']:
760      self.pushLanguage(self.languages.clanguage)
761      try:
762        if self.checkRun(includes, body) and os.path.exists(filename):
763          f    = file(filename)
764          size = int(f.read())
765          f.close()
766          os.remove(filename)
767        else:
768          size = -4
769      except:
770        size = -1
771        self.framework.logPrint('Error checking attribute(aligned)')
772      self.popLanguage()
773    else:
774      self.framework.addBatchInclude(['#include <stdlib.h>', '#include <stdio.h>', '#include <sys/types.h>','struct mystruct {int myint;} __attribute((aligned(16)));'])
775      self.framework.addBatchBody('fprintf(output, "  \'--known-has-attribute-aligned=%d\',\\n", sizeof(struct mystruct)==16);')
776      size = -2
777    if size == 16:
778      self.addDefine('ATTRIBUTEALIGNED(size)', '__attribute((aligned (size)))')
779      self.addDefine('HAVE_ATTRIBUTEALIGNED', 1)
780    else:
781      self.framework.logPrint('incorrect alignment. Found alignment:'+ str(size))
782      self.addDefine('ATTRIBUTEALIGNED(size)', ' ')
783    return
784
785  def configureExpect(self):
786    '''Sees if the __builtin_expect directive is supported'''
787    self.pushLanguage(self.languages.clanguage)
788    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
789      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
790    self.popLanguage()
791
792  def configureFunctionName(self):
793    '''Sees if the compiler supports __func__ or a variant.  Falls back
794    on __FUNCT__ which PETSc source defines, but most users do not, thus
795    stack traces through user code are better when the compiler's
796    variant is used.'''
797    def getFunctionName(lang):
798      name = '__FUNCT__'
799      self.pushLanguage(lang)
800      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
801        name = '__func__'
802      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
803        name = '__FUNCTION__'
804      self.popLanguage()
805      return name
806    langs = []
807
808    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
809    if hasattr(self.compilers, 'CXX'):
810      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
811    else:
812      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
813
814  def configureIntptrt(self):
815    '''Determine what to use for uintptr_t'''
816    def staticAssertSizeMatchesVoidStar(inc,typename):
817      # The declaration is an error if either array size is negative.
818      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
819      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
820                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
821    self.pushLanguage(self.languages.clanguage)
822    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
823      self.addDefine('UINTPTR_T', 'uintptr_t')
824    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
825      self.addDefine('UINTPTR_T', 'unsigned long long')
826    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
827      self.addDefine('UINTPTR_T', 'size_t')
828    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
829      self.addDefine('UINTPTR_T', 'unsigned long')
830    elif staticAssertSizeMatchesVoidStar('','unsigned'):
831      self.addDefine('UINTPTR_T', 'unsigned')
832    else:
833      raise RuntimeError('Could not find any unsigned integer type matching void*')
834    self.popLanguage()
835
836  def configureRTLDDefault(self):
837    if self.checkCompile('#include <dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
838      self.addDefine('RTLD_DEFAULT','1')
839    return
840
841  def configureSolaris(self):
842    '''Solaris specific stuff'''
843    if os.path.isdir(os.path.join('/usr','ucblib')):
844      try:
845        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
846      except AttributeError:
847        flag = None
848      if flag is None:
849        self.compilers.LIBS += ' -L/usr/ucblib'
850      else:
851        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
852    return
853
854  def configureLinux(self):
855    '''Linux specific stuff'''
856    # TODO: Test for this by mallocing an odd number of floats and checking the address
857    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
858    return
859
860  def configureWin32(self):
861    '''Win32 non-cygwin specific stuff'''
862    kernel32=0
863    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
864      self.addDefine('HAVE_WINDOWS_H',1)
865      self.addDefine('HAVE_GETCOMPUTERNAME',1)
866      kernel32=1
867    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
868      self.addDefine('HAVE_WINDOWS_H',1)
869      self.addDefine('HAVE_GETCOMPUTERNAME',1)
870      kernel32=1
871    if kernel32:
872      if self.framework.argDB['with-windows-graphics']:
873        self.addDefine('USE_WINDOWS_GRAPHICS',1)
874      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
875        self.addDefine('HAVE_LOADLIBRARY',1)
876      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
877        self.addDefine('HAVE_GETPROCADDRESS',1)
878      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
879        self.addDefine('HAVE_FREELIBRARY',1)
880      if self.checkLink('#include <Windows.h>','GetLastError()'):
881        self.addDefine('HAVE_GETLASTERROR',1)
882      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
883        self.addDefine('HAVE_SETLASTERROR',1)
884      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
885        self.addDefine('USE_MICROSOFT_TIME',1)
886    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
887      self.addDefine('HAVE_GET_USER_NAME',1)
888    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
889      self.addDefine('HAVE_GET_USER_NAME',1)
890
891    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
892      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
893    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
894      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
895
896    self.types.check('int32_t', 'int')
897    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
898      self.addTypedef('int', 'uid_t')
899      self.addTypedef('int', 'gid_t')
900    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
901      self.framework.addDefine('R_OK', '04')
902      self.framework.addDefine('W_OK', '02')
903      self.framework.addDefine('X_OK', '01')
904    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
905      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
906      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
907    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
908      self.addDefine('HAVE_LARGE_INTEGER_U',1)
909
910    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
911    if self.checkCompile('#include <Windows.h>\n#include <fcntl.h>\n', 'int flags = O_BINARY;'):
912      self.addDefine('HAVE_O_BINARY',1)
913
914    if self.compilers.CC.find('win32fe') >= 0:
915      self.addDefine('PATH_SEPARATOR','\';\'')
916      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
917      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
918      self.addDefine('CANNOT_START_DEBUGGER',1)
919      (petscdir,error,status) = self.executeShellCommand('cygpath -w '+self.petscdir.dir, log = self.log)
920      self.addDefine('DIR','"'+petscdir.replace('\\','\\\\')+'"')
921    else:
922      self.addDefine('PATH_SEPARATOR','\':\'')
923      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
924      self.addDefine('DIR_SEPARATOR','\'/\'')
925      self.addDefine('DIR', '"'+self.petscdir.dir+'"')
926
927    return
928
929#-----------------------------------------------------------------------------------------------------
930  def configureCygwinBrokenPipe(self):
931    '''Cygwin version <= 1.7.18 had issues with pipes and long commands invoked from gnu-make
932    http://cygwin.com/ml/cygwin/2013-05/msg00340.html '''
933    if config.setCompilers.Configure.isCygwin(self.log):
934      import platform
935      import re
936      r=re.compile("([0-9]+).([0-9]+).([0-9]+)")
937      m=r.match(platform.release())
938      major=int(m.group(1))
939      minor=int(m.group(2))
940      subminor=int(m.group(3))
941      if ((major < 1) or (major == 1 and minor < 7) or (major == 1 and minor == 7 and subminor <= 18)):
942        self.addMakeMacro('PETSC_CYGWIN_BROKEN_PIPE','1')
943    return
944
945#-----------------------------------------------------------------------------------------------------
946  def configureDefaultArch(self):
947    conffile = os.path.join('lib','petsc','conf', 'petscvariables')
948    if self.framework.argDB['with-default-arch']:
949      fd = file(conffile, 'w')
950      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
951      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
952      fd.write('include '+os.path.join(self.petscdir.dir,self.arch.arch,'lib','petsc','conf','petscvariables')+'\n')
953      fd.close()
954      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
955    elif os.path.isfile(conffile):
956      try:
957        os.unlink(conffile)
958      except:
959        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
960    return
961
962#-----------------------------------------------------------------------------------------------------
963  def configureScript(self):
964    '''Output a script in the conf directory which will reproduce the configuration'''
965    import nargs
966    import sys
967    scriptName = os.path.join(self.arch.arch,'lib','petsc','conf', 'reconfigure-'+self.arch.arch+'.py')
968    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
969    if 'with-clean' in args:
970      del args['with-clean']
971    if 'configModules' in args:
972      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
973        del args['configModules']
974    if 'optionsModule' in args:
975      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'config.compilerOptions':
976        del args['optionsModule']
977    if not 'PETSC_ARCH' in args:
978      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
979    f = file(scriptName, 'w')
980    f.write('#!'+sys.executable+'\n')
981    f.write('if __name__ == \'__main__\':\n')
982    f.write('  import sys\n')
983    f.write('  import os\n')
984    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
985    f.write('  import configure\n')
986    # pretty print repr(args.values())
987    f.write('  configure_options = [\n')
988    for itm in sorted(args.values()):
989      f.write('    \''+str(itm)+'\',\n')
990    f.write('  ]\n')
991    f.write('  configure.petsc_configure(configure_options)\n')
992    f.close()
993    try:
994      os.chmod(scriptName, 0775)
995    except OSError, e:
996      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
997    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
998    return
999
1000  def configureInstall(self):
1001    '''Setup the directories for installation'''
1002    if self.framework.argDB['prefix']:
1003      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
1004                                              '-@echo "'+self.installdir.installSudo+'make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
1005                                              '-@echo "========================================="'])
1006    else:
1007      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
1008                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
1009                                              '-@echo "========================================="'])
1010      return
1011
1012  def configureGCOV(self):
1013    if self.framework.argDB['with-gcov']:
1014      self.addDefine('USE_GCOV','1')
1015    return
1016
1017  def configureFortranFlush(self):
1018    if hasattr(self.compilers, 'FC'):
1019      for baseName in ['flush','flush_']:
1020        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
1021          self.addDefine('HAVE_'+baseName.upper(), 1)
1022          return
1023
1024  def configureViewFromOptions(self):
1025    if not self.framework.argDB['with-viewfromoptions']:
1026      self.addDefine('SKIP_VIEWFROMOPTIONS',1)
1027
1028  def postProcessPackages(self):
1029    postPackages=[]
1030    for i in self.framework.packages:
1031      if hasattr(i,'postProcess'): postPackages.append(i)
1032    if postPackages:
1033      # ctetgen needs petsc conf files. so attempt to create them early
1034      self.framework.dumpConfFiles()
1035      # tacky fix for dependency of Aluimia on Pflotran; requested via petsc-dev Matt provide a correct fix
1036      for i in postPackages:
1037        if i.name.upper() in ['PFLOTRAN']:
1038          i.postProcess()
1039          postPackages.remove(i)
1040      for i in postPackages: i.postProcess()
1041      for i in postPackages:
1042        if i.installedpetsc:
1043          self.installed = 1
1044          break
1045    return
1046
1047  def configure(self):
1048    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
1049      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
1050    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
1051      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
1052    if self.framework.argDB['prefix'] and self.framework.argDB['prefix'].find(' ') > -1:
1053      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')
1054    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)):
1055      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
1056    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
1057    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
1058    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'lib','petsc','conf','petscvariables')
1059    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'lib','petsc','conf','petscrules')
1060    if self.libraries.math is None:
1061      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
1062    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
1063      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
1064    self.executeTest(self.configureRTLDDefault)
1065    self.executeTest(self.configurePrefetch)
1066    self.executeTest(self.configureUnused)
1067    self.executeTest(self.configureDeprecated)
1068    self.executeTest(self.configureIsatty)
1069    self.executeTest(self.configureExpect);
1070    self.executeTest(self.configureAlign);
1071    self.executeTest(self.configureFunctionName);
1072    self.executeTest(self.configureIntptrt);
1073    self.executeTest(self.configureSolaris)
1074    self.executeTest(self.configureLinux)
1075    self.executeTest(self.configureWin32)
1076    self.executeTest(self.configureCygwinBrokenPipe)
1077    self.executeTest(self.configureDefaultArch)
1078    self.executeTest(self.configureScript)
1079    self.executeTest(self.configureInstall)
1080    self.executeTest(self.configureGCOV)
1081    self.executeTest(self.configureFortranFlush)
1082    self.executeTest(self.configureAtoll)
1083    self.executeTest(self.configureViewFromOptions)
1084    # dummy rules, always needed except for remote builds
1085    self.addMakeRule('remote','')
1086    self.addMakeRule('remoteclean','')
1087
1088    self.Dump()
1089    self.dumpConfigInfo()
1090    self.dumpMachineInfo()
1091    self.dumpCMakeConfig()
1092    self.dumpCMakeLists()
1093    # need to save the current state of BuildSystem so that postProcess() packages can read it in and perhaps run make install
1094    self.framework.storeSubstitutions(self.framework.argDB)
1095    self.framework.argDB['configureCache'] = cPickle.dumps(self.framework)
1096    self.framework.argDB.save(force = True)
1097    self.cmakeBoot()
1098    self.DumpPkgconfig()
1099    self.DumpModule()
1100    self.postProcessPackages()
1101    self.framework.log.write('================================================================================\n')
1102    self.logClear()
1103    return
1104