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