xref: /petsc/config/PETSc/Configure.py (revision 7d421530185bb723f244ebc5c37ccbc3c555f748)
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    desc.append('   Configure stage complete. Now build PETSc libraries with:')
24    desc.append('   make PETSC_DIR='+self.petscdir.dir+' PETSC_ARCH='+self.arch.arch+' all')
25    desc.append(' or:')
26    desc.append('   PETSC_DIR='+self.petscdir.dir+' PETSC_ARCH='+self.arch.arch+' ./config/builder.py')
27    desc.append('xxx=========================================================================xxx')
28    return '\n'.join(desc)+'\n'
29
30  def setupHelp(self, help):
31    import nargs
32    help.addArgument('PETSc',  '-prefix=<dir>',                  nargs.Arg(None, '', 'Specifiy location to install PETSc (eg. /usr/local)'))
33    help.addArgument('Windows','-with-windows-graphics=<bool>',   nargs.ArgBool(None, 1,'Enable check for Windows Graphics'))
34    help.addArgument('PETSc', '-with-default-arch=<bool>',        nargs.ArgBool(None, 1, 'Allow using the last configured arch without setting PETSC_ARCH'))
35    help.addArgument('PETSc','-with-single-library=<bool>',       nargs.ArgBool(None, 1,'Put all PETSc code into the single -lpetsc library'))
36    help.addArgument('PETSc', '-with-iphone=<bool>',              nargs.ArgBool(None, 0, 'Build an iPhone version of PETSc'))
37    return
38
39  def setupDependencies(self, framework):
40    config.base.Configure.setupDependencies(self, framework)
41    self.setCompilers  = framework.require('config.setCompilers',      self)
42    self.arch          = framework.require('PETSc.utilities.arch',     self.setCompilers)
43    self.petscdir      = framework.require('PETSc.utilities.petscdir', self.setCompilers)
44    self.languages     = framework.require('PETSc.utilities.languages',self.setCompilers)
45    self.debugging     = framework.require('PETSc.utilities.debugging',self.setCompilers)
46    self.CHUD          = framework.require('PETSc.utilities.CHUD',     self)
47    self.compilers     = framework.require('config.compilers',         self)
48    self.types         = framework.require('config.types',             self)
49    self.headers       = framework.require('config.headers',           self)
50    self.functions     = framework.require('config.functions',         self)
51    self.libraries     = framework.require('config.libraries',         self)
52    if os.path.isdir(os.path.join('config', 'PETSc')):
53      for d in ['utilities', 'packages']:
54        for utility in os.listdir(os.path.join('config', 'PETSc', d)):
55          (utilityName, ext) = os.path.splitext(utility)
56          if not utilityName.startswith('.') and not utilityName.startswith('#') and ext == '.py' and not utilityName == '__init__':
57            utilityObj                    = self.framework.require('PETSc.'+d+'.'+utilityName, self)
58            utilityObj.headerPrefix       = self.headerPrefix
59            utilityObj.archProvider       = self.arch
60            utilityObj.languageProvider   = self.languages
61            utilityObj.installDirProvider = self.petscdir
62            setattr(self, utilityName.lower(), utilityObj)
63
64    for package in config.packages.all:
65      if not package == 'PETSc':
66        packageObj                    = framework.require('config.packages.'+package, self)
67        packageObj.archProvider       = self.arch
68        packageObj.languageProvider   = self.languages
69        packageObj.installDirProvider = self.petscdir
70        setattr(self, package.lower(), packageObj)
71    # Force blaslapack to depend on scalarType so precision is set before BlasLapack is built
72    framework.require('PETSc.utilities.scalarTypes', self.blaslapack)
73    self.blaslapack.precisionProvider = self.scalartypes
74
75    self.compilers.headerPrefix  = self.headerPrefix
76    self.types.headerPrefix      = self.headerPrefix
77    self.headers.headerPrefix    = self.headerPrefix
78    self.functions.headerPrefix  = self.headerPrefix
79    self.libraries.headerPrefix  = self.headerPrefix
80    self.blaslapack.headerPrefix = self.headerPrefix
81    self.mpi.headerPrefix        = self.headerPrefix
82    headersC = map(lambda name: name+'.h', ['dos', 'endian', 'fcntl', 'float', 'io', 'limits', 'malloc', 'pwd', 'search', 'strings',
83                                            'unistd', 'machine/endian', 'sys/param', 'sys/procfs', 'sys/resource',
84                                            'sys/systeminfo', 'sys/times', 'sys/utsname','string', 'stdlib','memory',
85                                            'sys/socket','sys/wait','netinet/in','netdb','Direct','time','Ws2tcpip','sys/types',
86                                            'WindowsX', 'cxxabi','float','ieeefp','stdint','fenv'])
87    functions = ['access', '_access', 'clock', 'drand48', 'getcwd', '_getcwd', 'getdomainname', 'gethostname', 'getpwuid',
88                 'gettimeofday', 'getwd', 'memalign', 'memmove', 'mkstemp', 'popen', 'PXFGETARG', 'rand', 'getpagesize',
89                 'readlink', 'realpath',  'sigaction', 'signal', 'sigset', 'nanosleep', 'usleep', 'sleep', '_sleep', 'socket',
90                 'times', 'gethostbyname', 'uname','snprintf','_snprintf','_fullpath','lseek','_lseek','time','fork','stricmp',
91                 'strcasecmp', 'bzero', 'dlopen', 'dlsym', 'dlclose', 'dlerror',
92                 '_intel_fast_memcpy','_intel_fast_memset']
93    libraries1 = [(['socket', 'nsl'], 'socket'), (['fpe'], 'handle_sigfpes')]
94    self.headers.headers.extend(headersC)
95    self.functions.functions.extend(functions)
96    self.libraries.libraries.extend(libraries1)
97    if self.checkCompile('#include <<dlfcn.h>\n void *ptr =  RTLD_DEFAULT;'):
98      self.addDefine('RTLD_DEFAULT','1')
99
100    return
101
102  def Dump(self):
103    ''' Actually put the values into the configuration files '''
104    # eventually everything between -- should be gone
105#-----------------------------------------------------------------------------------------------------
106
107    # Sometimes we need C compiler, even if built with C++
108    self.setCompilers.pushLanguage('C')
109    self.addMakeMacro('CC_FLAGS',self.setCompilers.getCompilerFlags())
110    self.setCompilers.popLanguage()
111
112    # C preprocessor values
113    self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS+self.CHUD.CPPFLAGS)
114
115    # compiler values
116    self.setCompilers.pushLanguage(self.languages.clanguage)
117    self.addMakeMacro('PCC',self.setCompilers.getCompiler())
118    self.addMakeMacro('PCC_FLAGS',self.setCompilers.getCompilerFlags())
119    self.setCompilers.popLanguage()
120    # .o or .obj
121    self.addMakeMacro('CC_SUFFIX','o')
122
123    # executable linker values
124    self.setCompilers.pushLanguage(self.languages.clanguage)
125    pcc_linker = self.setCompilers.getLinker()
126    self.addMakeMacro('PCC_LINKER',pcc_linker)
127    self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
128    self.setCompilers.popLanguage()
129    # '' for Unix, .exe for Windows
130    self.addMakeMacro('CC_LINKER_SUFFIX','')
131
132    if hasattr(self.compilers, 'FC'):
133      self.setCompilers.pushLanguage('FC')
134      # need FPPFLAGS in config/setCompilers
135      self.addDefine('HAVE_FORTRAN','1')
136      self.addMakeMacro('FPP_FLAGS',self.setCompilers.CPPFLAGS)
137
138      # compiler values
139      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
140      self.setCompilers.popLanguage()
141      # .o or .obj
142      self.addMakeMacro('FC_SUFFIX','o')
143
144      # executable linker values
145      self.setCompilers.pushLanguage('FC')
146      # Cannot have NAG f90 as the linker - so use pcc_linker as fc_linker
147      fc_linker = self.setCompilers.getLinker()
148      if config.setCompilers.Configure.isNAG(fc_linker):
149        self.addMakeMacro('FC_LINKER',pcc_linker)
150      else:
151        self.addMakeMacro('FC_LINKER',fc_linker)
152      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
153      # apple requires this shared library linker flag on SOME versions of the os
154      if self.setCompilers.getLinkerFlags().find('-Wl,-commons,use_dylibs') > -1:
155        self.addMakeMacro('DARWIN_COMMONS_USE_DYLIBS',' -Wl,-commons,use_dylibs ')
156      self.setCompilers.popLanguage()
157
158      # F90 Modules
159      if self.setCompilers.fortranModuleIncludeFlag:
160        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
161      else: # for non-f90 compilers like g77
162        self.addMakeMacro('FC_MODULE_FLAG', '-I')
163      if self.setCompilers.fortranModuleIncludeFlag:
164        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
165    else:
166      self.addMakeMacro('FC','')
167
168    if hasattr(self.compilers, 'CUDAC'):
169      self.setCompilers.pushLanguage('CUDA')
170      self.addMakeMacro('CUDAC_FLAGS',self.setCompilers.getCompilerFlags())
171      self.setCompilers.popLanguage()
172
173    # shared library linker values
174    self.setCompilers.pushLanguage(self.languages.clanguage)
175    # need to fix BuildSystem to collect these separately
176    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
177    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
178    self.setCompilers.popLanguage()
179    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
180    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
181    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
182      self.addMakeMacro('SL_LINKER_SUFFIX', '')
183      self.addDefine('SLSUFFIX','""')
184    else:
185      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
186      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
187
188    self.addMakeMacro('SL_LINKER_LIBS','${PETSC_EXTERNAL_LIB_BASIC}')
189
190#-----------------------------------------------------------------------------------------------------
191
192    # CONLY or CPP. We should change the PETSc makefiles to do this better
193    if self.languages.clanguage == 'C': lang = 'CONLY'
194    else: lang = 'CXXONLY'
195    self.addMakeMacro('PETSC_LANGUAGE',lang)
196
197    # real or complex
198    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
199    # double or float
200    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
201
202    if self.framework.argDB['with-batch']:
203      self.addMakeMacro('PETSC_WITH_BATCH','1')
204
205    # Test for compiler-specific macros that need to be defined.
206    if self.setCompilers.isCrayVector('CC'):
207      self.addDefine('HAVE_CRAY_VECTOR','1')
208
209#-----------------------------------------------------------------------------------------------------
210    if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket'):
211      self.addDefine('USE_SOCKET_VIEWER','1')
212
213#-----------------------------------------------------------------------------------------------------
214    # print include and lib for makefiles
215    self.framework.packages.reverse()
216    includes = [os.path.join(self.petscdir.dir,'include'),os.path.join(self.petscdir.dir,self.arch.arch,'include')]
217    libs = []
218    for i in self.framework.packages:
219      if i.useddirectly:
220        self.addDefine('HAVE_'+i.PACKAGE, 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
221      if not isinstance(i.lib, list):
222        i.lib = [i.lib]
223      libs.extend(i.lib)
224      self.addMakeMacro(i.PACKAGE+'_LIB', self.libraries.toStringNoDupes(i.lib))
225      if hasattr(i,'include'):
226        if not isinstance(i.include,list):
227          i.include = [i.include]
228        includes.extend(i.include)
229        self.addMakeMacro(i.PACKAGE+'_INCLUDE',self.headers.toStringNoDupes(i.include))
230    if self.framework.argDB['with-single-library']:
231      self.addMakeMacro('PETSC_WITH_EXTERNAL_LIB',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.split(' '))+self.CHUD.LIBS)
232    self.addMakeMacro('PETSC_EXTERNAL_LIB_BASIC',self.libraries.toStringNoDupes(libs+self.libraries.math+self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' '))+self.CHUD.LIBS)
233    self.PETSC_EXTERNAL_LIB_BASIC = self.libraries.toStringNoDupes(libs+self.libraries.math+self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' '))+self.CHUD.LIBS
234    self.addMakeMacro('PETSC_CC_INCLUDES',self.headers.toStringNoDupes(includes))
235    self.PETSC_CC_INCLUDES = self.headers.toStringNoDupes(includes)
236    if hasattr(self.compilers, 'FC'):
237      if self.compilers.fortranIsF90:
238        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes,includes))
239      else:
240        self.addMakeMacro('PETSC_FC_INCLUDES',self.headers.toStringNoDupes(includes))
241
242    self.addMakeMacro('DESTDIR',self.installdir)
243    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir,'lib')+'"')
244
245    if self.framework.argDB['with-single-library']:
246      # overrides the values set in conf/variables
247      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
248      self.addMakeMacro('SHLIBS','libpetsc')
249      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
250      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
251      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
252      self.addDefine('USE_SINGLE_LIBRARY', '1')
253      if self.sharedlibraries.useShared:
254        self.addMakeMacro('PETSC_SYS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
255        self.addMakeMacro('PETSC_VEC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
256        self.addMakeMacro('PETSC_MAT_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
257        self.addMakeMacro('PETSC_DM_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
258        self.addMakeMacro('PETSC_KSP_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
259        self.addMakeMacro('PETSC_SNES_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
260        self.addMakeMacro('PETSC_TS_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
261        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
262        self.addMakeMacro('PETSC_LIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
263        self.addMakeMacro('PETSC_CONTRIB','${C_SH_LIB_PATH} ${PETSC_WITH_EXTERNAL_LIB}')
264      else:
265        self.addMakeMacro('PETSC_SYS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
266        self.addMakeMacro('PETSC_VEC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
267        self.addMakeMacro('PETSC_MAT_LIB','${PETSC_WITH_EXTERNAL_LIB}')
268        self.addMakeMacro('PETSC_DM_LIB','${PETSC_WITH_EXTERNAL_LIB}')
269        self.addMakeMacro('PETSC_KSP_LIB','${PETSC_WITH_EXTERNAL_LIB}')
270        self.addMakeMacro('PETSC_SNES_LIB','${PETSC_WITH_EXTERNAL_LIB}')
271        self.addMakeMacro('PETSC_TS_LIB','${PETSC_WITH_EXTERNAL_LIB}')
272        self.addMakeMacro('PETSC_CHARACTERISTIC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
273        self.addMakeMacro('PETSC_LIB','${PETSC_WITH_EXTERNAL_LIB}')
274        self.addMakeMacro('PETSC_CONTRIB','${PETSC_WITH_EXTERNAL_LIB}')
275
276    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
277      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
278
279    # add a makefile entry for configure options
280    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
281    return
282
283  def dumpConfigInfo(self):
284    import time
285    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
286    fd.write('static const char *petscconfigureruntime = "'+time.ctime(time.time())+'";\n')
287    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
288    fd.close()
289    return
290
291  def dumpMachineInfo(self):
292    import platform
293    import time
294    import script
295    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
296    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
297    fd.write('\"-----------------------------------------\\n\"\n')
298    fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
299    fd.write('\"Machine characteristics: %s\\n\"\n' % (platform.platform()))
300    fd.write('\"Using PETSc directory: %s\\n\"\n' % (self.petscdir.dir))
301    fd.write('\"Using PETSc arch: %s\\n\"\n' % (self.arch.arch))
302    fd.write('\"-----------------------------------------\\n\";\n')
303    fd.write('static const char *petsccompilerinfo = \"\\n\"\n')
304    self.setCompilers.pushLanguage(self.languages.clanguage)
305    fd.write('\"Using C compiler: %s %s ${COPTFLAGS} ${CFLAGS}\\n\"\n' % (self.setCompilers.getCompiler(), self.setCompilers.getCompilerFlags()))
306    self.setCompilers.popLanguage()
307    if hasattr(self.compilers, 'FC'):
308      self.setCompilers.pushLanguage('FC')
309      fd.write('\"Using Fortran compiler: %s %s ${FOPTFLAGS} ${FFLAGS} %s\\n\"\n' % (self.setCompilers.getCompiler(), self.setCompilers.getCompilerFlags(), self.setCompilers.CPPFLAGS))
310      self.setCompilers.popLanguage()
311    fd.write('\"-----------------------------------------\\n\";\n')
312    fd.write('static const char *petsccompilerflagsinfo = \"\\n\"\n')
313    fd.write('\"Using include paths: %s %s %s\\n\"\n' % ('-I'+os.path.join(self.petscdir.dir, self.arch.arch, 'include'), '-I'+os.path.join(self.petscdir.dir, 'include'), self.PETSC_CC_INCLUDES))
314    fd.write('\"-----------------------------------------\\n\";\n')
315    fd.write('static const char *petsclinkerinfo = \"\\n\"\n')
316    self.setCompilers.pushLanguage(self.languages.clanguage)
317    fd.write('\"Using C linker: %s\\n\"\n' % (self.setCompilers.getLinker()))
318    self.setCompilers.popLanguage()
319    if hasattr(self.compilers, 'FC'):
320      self.setCompilers.pushLanguage('FC')
321      fd.write('\"Using Fortran linker: %s\\n\"\n' % (self.setCompilers.getLinker()))
322      self.setCompilers.popLanguage()
323    fd.write('\"Using libraries: %s%s -L%s %s %s\\n\"\n' % (self.setCompilers.CSharedLinkerFlag, os.path.join(self.petscdir.dir, self.arch.arch, 'lib'), os.path.join(self.petscdir.dir, self.arch.arch, 'lib'), '-lpetscts -lpetscsnes -lpetscksp -lpetscdm -lpetscmat -lpetscvec -lpetscsys', self.PETSC_EXTERNAL_LIB_BASIC))
324    fd.write('\"-----------------------------------------\\n\";\n')
325    fd.close()
326    return
327
328  def dumpCMakeConfig(self):
329    '''
330    Writes configuration-specific values to ${PETSC_ARCH}/conf/PETScConfig.cmake.
331    This file is private to PETSc and should not be included by third parties
332    (a suitable file can be produced later by CMake, but this is not it).
333    '''
334    def cmakeset(fd,key,val=True):
335      if val == True: val = 'YES'
336      if val == False: val = 'NO'
337      fd.write('set (' + key + ' ' + val + ')\n')
338    def ensurelist(a):
339      if isinstance(a,list):
340        return a
341      else:
342        return [a]
343    def libpath(lib):
344      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
345      if not isinstance(lib,str): return ''
346      if lib.startswith('-L'): return lib[2:]
347      if lib.startswith('-R'): return lib[2:]
348      if lib.startswith('-Wl,-rpath,'):
349        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
350        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
351        # corresponding library.
352        return lib[len('-Wl,-rpath,'):]
353      if lib.startswith('-'): return ''
354      return os.path.dirname(lib)
355    def cleanlib(lib):
356      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
357      if not isinstance(lib,str): return ''
358      if lib.startswith('-l'):  return lib[2:]
359      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
360      lib = os.path.splitext(os.path.basename(lib))[0]
361      if lib.startswith('lib'): return lib[3:]
362      return lib
363    def nub(lst):
364      'Return a list containing the first occurrence of each unique element'
365      unique = []
366      for elem in lst:
367        if elem not in unique and elem != '':
368          unique.append(elem)
369      return unique
370    def nublast(lst):
371      'Return a list containing the last occurrence of each unique entry in a list'
372      return reversed(nub(reversed(lst)))
373    def cmakeexpand(varname):
374      return r'"${' + varname + r'}"'
375    def uniqextend(lst,new):
376      for x in ensurelist(new):
377        if x not in lst:
378          lst.append(x)
379    def notstandardinclude(path):
380      return path not in '/usr/include /usr/local/include'.split()
381    def writeMacroDefinitions(fd):
382      if self.mpi.usingMPIUni:
383        cmakeset(fd,'PETSC_HAVE_MPIUNI')
384      for pkg in self.framework.packages:
385        if pkg.useddirectly:
386          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE)
387      for name,val in self.functions.defines.items():
388        cmakeset(fd,'PETSC_'+name,val)
389      for dct in [self.defines, self.libraryoptions.defines]:
390        for k,v in dct.items():
391          if k.startswith('USE_'):
392            cmakeset(fd,'PETSC_' + k, v)
393      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
394      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
395      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
396      if hasattr(self.compilers, 'FC'):
397        cmakeset(fd,'PETSC_HAVE_FORTRAN')
398        if self.compilers.fortranIsF90:
399          cmakeset(fd,'PETSC_USING_F90')
400      if self.sharedlibraries.useShared:
401        cmakeset(fd,'BUILD_SHARED_LIBS')
402    def writeBuildFlags(fd):
403      def extendby(lib):
404        libs = ensurelist(lib)
405        lib_paths.extend(map(libpath,libs))
406        lib_libs.extend(map(cleanlib,libs))
407        uniqextend(includes,pkg.include)
408      lib_paths = []
409      lib_libs  = []
410      includes  = []
411      libvars   = []
412      for pkg in self.framework.packages:
413        extendby(pkg.lib)
414      extendby(self.libraries.math)
415      extendby(self.libraries.rt)
416      extendby(self.compilers.flibs)
417      extendby(self.compilers.cxxlibs)
418      extendby(self.compilers.LIBS.split())
419      for libname in nublast(lib_libs):
420        libvar = 'PETSC_' + libname.upper() + '_LIB'
421        addpath = ''
422        for lpath in nublast(lib_paths):
423          addpath += '"' + str(lpath) + '" '
424        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
425        libvars.append(libvar)
426      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
427      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
428      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',filter(notstandardinclude,includes))) + ')\n')
429    fd = open(os.path.join(self.arch.arch,'conf','PETScConfig.cmake'), 'w')
430    writeMacroDefinitions(fd)
431    writeBuildFlags(fd)
432    fd.close()
433    return
434
435  def dumpCMakeLists(self):
436    import sys
437    if sys.version_info >= (2,5):
438      import cmakegen
439      try:
440        cmakegen.main(self.petscdir.dir)
441      except (OSError), e:
442        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
443
444  def cmakeBoot(self):
445    import sys
446    if sys.version_info >= (2,5) and hasattr(self.cmake,'cmake'):
447      try:
448        import cmakeboot
449        cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
450      except (OSError), e:
451        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
452      except (ImportError, KeyError), e:
453        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
454    return
455
456  def configurePrefetch(self):
457    '''Sees if there are any prefetch functions supported'''
458    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
459      self.addDefine('Prefetch(a,b,c)', ' ')
460      return
461    self.pushLanguage(self.languages.clanguage)
462    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
463      # The Intel Intrinsics manual [1] specifies the prototype
464      #
465      #   void _mm_prefetch(char const *a, int sel);
466      #
467      # but other vendors seem to insist on using subtly different
468      # prototypes, including void* for the pointer, and an enum for
469      # sel.  These are both reasonable changes, but negatively impact
470      # portability.
471      #
472      # [1] http://software.intel.com/file/6373
473      self.addDefine('HAVE_XMMINTRIN_H', 1)
474      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
475      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
476      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
477      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
478      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
479    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
480      self.addDefine('HAVE_XMMINTRIN_H', 1)
481      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
482      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
483      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
484      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
485      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
486    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
487      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
488      #
489      #   The value of rw is a compile-time constant one or zero; one
490      #   means that the prefetch is preparing for a write to the memory
491      #   address and zero, the default, means that the prefetch is
492      #   preparing for a read. The value locality must be a compile-time
493      #   constant integer between zero and three. A value of zero means
494      #   that the data has no temporal locality, so it need not be left
495      #   in the cache after the access. A value of three means that the
496      #   data has a high degree of temporal locality and should be left
497      #   in all levels of cache possible. Values of one and two mean,
498      #   respectively, a low or moderate degree of temporal locality.
499      #
500      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
501      # hints.  Using macros for these values in necessary since some
502      # compilers require an enum.
503      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
504      self.addDefine('PREFETCH_HINT_NTA', '0')
505      self.addDefine('PREFETCH_HINT_T0',  '3')
506      self.addDefine('PREFETCH_HINT_T1',  '2')
507      self.addDefine('PREFETCH_HINT_T2',  '1')
508    else:
509      self.addDefine('Prefetch(a,b,c)', ' ')
510    self.popLanguage()
511
512  def configureUnused(self):
513    '''Sees if __attribute((unused)) is supported'''
514    if self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
515      self.addDefine('UNUSED', ' ')
516      return
517    self.pushLanguage(self.languages.clanguage)
518    if self.checkLink('__attribute((unused)) static int myfunc(void){ return 1;}', 'int i = myfunc();\n'):
519      self.addDefine('UNUSED', '__attribute((unused))')
520    else:
521      self.addDefine('UNUSED', ' ')
522    self.popLanguage()
523
524  def configureExpect(self):
525    '''Sees if the __builtin_expect directive is supported'''
526    self.pushLanguage(self.languages.clanguage)
527    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
528      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
529    self.popLanguage()
530
531  def configureFunctionName(self):
532    '''Sees if the compiler supports __func__ or a variant.  Falls back
533    on __FUNCT__ which PETSc source defines, but most users do not, thus
534    stack traces through user code are better when the compiler's
535    variant is used.'''
536    def getFunctionName(lang):
537      name = '__FUNCT__'
538      self.pushLanguage(lang)
539      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
540        name = '__func__'
541      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
542        name = '__FUNCTION__'
543      self.popLanguage()
544      return name
545    langs = []
546
547    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
548    if hasattr(self.compilers, 'CXX'):
549      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
550    else:
551      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
552
553  def configureIntptrt(self):
554    '''Determine what to use for uintptr_t'''
555    def staticAssertSizeMatchesVoidStar(inc,typename):
556      # The declaration is an error if either array size is negative.
557      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
558      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
559                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
560    self.pushLanguage(self.languages.clanguage)
561    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
562      self.addDefine('UINTPTR_T', 'uintptr_t')
563    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
564      self.addDefine('UINTPTR_T', 'unsigned long long')
565    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
566      self.addDefine('UINTPTR_T', 'size_t')
567    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
568      self.addDefine('UINTPTR_T', 'unsigned long')
569    elif staticAssertSizeMatchesVoidStar('','unsigned'):
570      self.addDefine('UINTPTR_T', 'unsigned')
571    else:
572      raise RuntimeError('Could not find any unsigned integer type matching void*')
573    self.popLanguage()
574
575  def configureInline(self):
576    '''Get a generic inline keyword, depending on the language'''
577    if self.languages.clanguage == 'C':
578      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
579      self.addDefine('RESTRICT', self.compilers.cRestrict)
580    elif self.languages.clanguage == 'Cxx':
581      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
582      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
583    return
584
585  def configureSolaris(self):
586    '''Solaris specific stuff'''
587    if os.path.isdir(os.path.join('/usr','ucblib')):
588      try:
589        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
590      except AttributeError:
591        flag = None
592      if flag is None:
593        self.compilers.LIBS += ' -L/usr/ucblib'
594      else:
595        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
596    return
597
598  def configureLinux(self):
599    '''Linux specific stuff'''
600    # TODO: Test for this by mallocing an odd number of floats and checking the address
601    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
602    return
603
604  def configureWin32(self):
605    '''Win32 non-cygwin specific stuff'''
606    kernel32=0
607    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
608      self.addDefine('HAVE_WINDOWS_H',1)
609      self.addDefine('HAVE_GETCOMPUTERNAME',1)
610      kernel32=1
611    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
612      self.addDefine('HAVE_WINDOWS_H',1)
613      self.addDefine('HAVE_GETCOMPUTERNAME',1)
614      kernel32=1
615    if kernel32:
616      if self.framework.argDB['with-windows-graphics']:
617        self.addDefine('USE_WINDOWS_GRAPHICS',1)
618      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
619        self.addDefine('HAVE_LOADLIBRARY',1)
620      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
621        self.addDefine('HAVE_GETPROCADDRESS',1)
622      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
623        self.addDefine('HAVE_FREELIBRARY',1)
624      if self.checkLink('#include <Windows.h>','GetLastError()'):
625        self.addDefine('HAVE_GETLASTERROR',1)
626      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
627        self.addDefine('HAVE_SETLASTERROR',1)
628      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
629        self.addDefine('USE_NT_TIME',1)
630    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
631      self.addDefine('HAVE_GET_USER_NAME',1)
632    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
633      self.addDefine('HAVE_GET_USER_NAME',1)
634
635    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
636      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
637    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
638      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
639
640    self.types.check('int32_t', 'int')
641    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
642      self.addTypedef('int', 'uid_t')
643      self.addTypedef('int', 'gid_t')
644    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
645      self.framework.addDefine('R_OK', '04')
646      self.framework.addDefine('W_OK', '02')
647      self.framework.addDefine('X_OK', '01')
648    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
649      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
650      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
651    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
652      self.addDefine('HAVE_LARGE_INTEGER_U',1)
653
654    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
655    if self.checkCompile('#include <Windows.h>\n', 'int flags = O_BINARY;'):
656      self.addDefine('HAVE_O_BINARY',1)
657
658    if self.compilers.CC.find('win32fe') >= 0:
659      self.addDefine('PATH_SEPARATOR','\';\'')
660      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
661      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
662      self.addDefine('CANNOT_START_DEBUGGER',1)
663    else:
664      self.addDefine('PATH_SEPARATOR','\':\'')
665      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
666      self.addDefine('DIR_SEPARATOR','\'/\'')
667    return
668
669#-----------------------------------------------------------------------------------------------------
670  def configureDefaultArch(self):
671    conffile = os.path.join('conf', 'petscvariables')
672    if self.framework.argDB['with-default-arch']:
673      fd = file(conffile, 'w')
674      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
675      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
676      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
677      fd.close()
678      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
679    elif os.path.isfile(conffile):
680      try:
681        os.unlink(conffile)
682      except:
683        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
684    return
685
686#-----------------------------------------------------------------------------------------------------
687  def configureScript(self):
688    '''Output a script in the conf directory which will reproduce the configuration'''
689    import nargs
690    import sys
691    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
692    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
693    if 'configModules' in args:
694      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
695        del args['configModules']
696    if 'optionsModule' in args:
697      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
698        del args['optionsModule']
699    if not 'PETSC_ARCH' in args:
700      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
701    f = file(scriptName, 'w')
702    f.write('#!'+sys.executable+'\n')
703    f.write('if __name__ == \'__main__\':\n')
704    f.write('  import sys\n')
705    f.write('  import os\n')
706    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
707    f.write('  import configure\n')
708    # pretty print repr(args.values())
709    f.write('  configure_options = [\n')
710    for itm in sorted(args.values()):
711      f.write('    \''+str(itm)+'\',\n')
712    f.write('  ]\n')
713    f.write('  configure.petsc_configure(configure_options)\n')
714    f.close()
715    try:
716      os.chmod(scriptName, 0775)
717    except OSError, e:
718      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
719    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
720    return
721
722  def configureInstall(self):
723    '''Setup the directories for installation'''
724    if self.framework.argDB['prefix']:
725      self.installdir = self.framework.argDB['prefix']
726      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
727                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
728                                              '-@echo "========================================="'])
729    else:
730      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
731      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
732                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
733                                              '-@echo "========================================="'])
734      return
735
736  def configureGCOV(self):
737    if self.framework.argDB['with-gcov']:
738      self.addDefine('USE_GCOV','1')
739    return
740
741  def configureFortranFlush(self):
742    if hasattr(self.compilers, 'FC'):
743      for baseName in ['flush','flush_']:
744        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
745          self.addDefine('HAVE_'+baseName.upper(), 1)
746          return
747
748
749  def configure(self):
750    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
751      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
752    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
753      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
754    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)):
755      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
756    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
757    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
758    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
759    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
760    if self.libraries.math is None:
761      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
762    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
763      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
764    self.executeTest(self.configureInline)
765    self.executeTest(self.configurePrefetch)
766    self.executeTest(self.configureUnused)
767    self.executeTest(self.configureExpect);
768    self.executeTest(self.configureFunctionName);
769    self.executeTest(self.configureIntptrt);
770    self.executeTest(self.configureSolaris)
771    self.executeTest(self.configureLinux)
772    self.executeTest(self.configureWin32)
773    self.executeTest(self.configureDefaultArch)
774    self.executeTest(self.configureScript)
775    self.executeTest(self.configureInstall)
776    self.executeTest(self.configureGCOV)
777    self.executeTest(self.configureFortranFlush)
778    # dummy rules, always needed except for remote builds
779    self.addMakeRule('remote','')
780    self.addMakeRule('remoteclean','')
781
782    self.Dump()
783    self.dumpConfigInfo()
784    self.dumpMachineInfo()
785    self.dumpCMakeConfig()
786    self.dumpCMakeLists()
787    self.cmakeBoot()
788    self.framework.log.write('================================================================================\n')
789    self.logClear()
790    return
791