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