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