xref: /petsc/config/PETSc/Configure.py (revision 58c9b8173e8b2543964ffc78265fd2abdbcb9cd3)
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    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 not isinstance(lib,str): return ''
343      if lib.startswith('-L'): return lib[2:]
344      if lib.startswith('-R'): return lib[2:]
345      if lib.startswith('-Wl,-rpath,'):
346        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
347        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
348        # corresponding library.
349        return lib[len('-Wl,-rpath,'):]
350      if lib.startswith('-'): return ''
351      return os.path.dirname(lib)
352    def cleanlib(lib):
353      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
354      if not isinstance(lib,str): return ''
355      if lib.startswith('-l'):  return lib[2:]
356      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
357      lib = os.path.splitext(os.path.basename(lib))[0]
358      if lib.startswith('lib'): return lib[3:]
359      return lib
360    def nub(lst):
361      'Return a list containing the first occurrence of each unique element'
362      unique = []
363      for elem in lst:
364        if elem not in unique and elem != '':
365          unique.append(elem)
366      return unique
367    def nublast(lst):
368      'Return a list containing the last occurrence of each unique entry in a list'
369      return reversed(nub(reversed(lst)))
370    def cmakeexpand(varname):
371      return r'"${' + varname + r'}"'
372    def uniqextend(lst,new):
373      for x in ensurelist(new):
374        if x not in lst:
375          lst.append(x)
376    def notstandardinclude(path):
377      return path not in '/usr/include /usr/local/include'.split()
378    def writeMacroDefinitions(fd):
379      if self.mpi.usingMPIUni:
380        cmakeset(fd,'PETSC_HAVE_MPIUNI')
381      for pkg in self.framework.packages:
382        if pkg.useddirectly:
383          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE)
384      for name,val in self.functions.defines.items():
385        cmakeset(fd,'PETSC_'+name,val)
386      for dct in [self.defines, self.libraryoptions.defines]:
387        for k,v in dct.items():
388          if k.startswith('USE_'):
389            cmakeset(fd,'PETSC_' + k, v)
390      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
391      cmakeset(fd,'PETSC_USE_REAL_' + self.scalartypes.precision.upper())
392      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
393      if hasattr(self.compilers, 'FC'):
394        cmakeset(fd,'PETSC_HAVE_FORTRAN')
395        if self.compilers.fortranIsF90:
396          cmakeset(fd,'PETSC_USING_F90')
397      if self.sharedlibraries.useShared:
398        cmakeset(fd,'BUILD_SHARED_LIBS')
399    def writeBuildFlags(fd):
400      def extendby(lib):
401        libs = ensurelist(lib)
402        lib_paths.extend(map(libpath,libs))
403        lib_libs.extend(map(cleanlib,libs))
404        uniqextend(includes,pkg.include)
405      lib_paths = []
406      lib_libs  = []
407      includes  = []
408      libvars   = []
409      for pkg in self.framework.packages:
410        extendby(pkg.lib)
411      extendby(self.libraries.math)
412      extendby(self.libraries.rt)
413      extendby(self.compilers.flibs)
414      extendby(self.compilers.cxxlibs)
415      extendby(self.compilers.LIBS.split())
416      for libname in nublast(lib_libs):
417        libvar = 'PETSC_' + libname.upper() + '_LIB'
418        addpath = ''
419        for lpath in nublast(lib_paths):
420          addpath += '"' + str(lpath) + '" '
421        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + addpath + ')\n')
422        libvars.append(libvar)
423      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
424      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
425      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',filter(notstandardinclude,includes))) + ')\n')
426    fd = open(os.path.join(self.arch.arch,'conf','PETScConfig.cmake'), 'w')
427    writeMacroDefinitions(fd)
428    writeBuildFlags(fd)
429    fd.close()
430    return
431
432  def dumpCMakeLists(self):
433    import sys
434    if sys.version_info >= (2,5):
435      import cmakegen
436      try:
437        cmakegen.main(self.petscdir.dir)
438      except (OSError), e:
439        self.framework.logPrint('Generating CMakeLists.txt failed:\n' + str(e))
440
441  def cmakeBoot(self):
442    import sys
443    if sys.version_info >= (2,5) and hasattr(self.cmake,'cmake'):
444      try:
445        import cmakeboot
446        cmakeboot.main(petscdir=self.petscdir.dir,petscarch=self.arch.arch,argDB=self.argDB,framework=self.framework,log=self.framework.log)
447      except (OSError), e:
448        self.framework.logPrint('Booting CMake in PETSC_ARCH failed:\n' + str(e))
449      except (ImportError, KeyError), e:
450        self.framework.logPrint('Importing cmakeboot failed:\n' + str(e))
451    return
452
453  def configurePrefetch(self):
454    '''Sees if there are any prefetch functions supported'''
455    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
456      self.addDefine('Prefetch(a,b,c)', ' ')
457      return
458    self.pushLanguage(self.languages.clanguage)
459    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,_MM_HINT_NTA);\n'):
460      # The Intel Intrinsics manual [1] specifies the prototype
461      #
462      #   void _mm_prefetch(char const *a, int sel);
463      #
464      # but other vendors seem to insist on using subtly different
465      # prototypes, including void* for the pointer, and an enum for
466      # sel.  These are both reasonable changes, but negatively impact
467      # portability.
468      #
469      # [1] http://software.intel.com/file/6373
470      self.addDefine('HAVE_XMMINTRIN_H', 1)
471      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(c))')
472      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
473      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
474      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
475      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
476    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,_MM_HINT_NTA);\n'):
477      self.addDefine('HAVE_XMMINTRIN_H', 1)
478      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(c))')
479      self.addDefine('PREFETCH_HINT_NTA', '_MM_HINT_NTA')
480      self.addDefine('PREFETCH_HINT_T0',  '_MM_HINT_T0')
481      self.addDefine('PREFETCH_HINT_T1',  '_MM_HINT_T1')
482      self.addDefine('PREFETCH_HINT_T2',  '_MM_HINT_T2')
483    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
484      # From GCC docs: void __builtin_prefetch(const void *addr,int rw,int locality)
485      #
486      #   The value of rw is a compile-time constant one or zero; one
487      #   means that the prefetch is preparing for a write to the memory
488      #   address and zero, the default, means that the prefetch is
489      #   preparing for a read. The value locality must be a compile-time
490      #   constant integer between zero and three. A value of zero means
491      #   that the data has no temporal locality, so it need not be left
492      #   in the cache after the access. A value of three means that the
493      #   data has a high degree of temporal locality and should be left
494      #   in all levels of cache possible. Values of one and two mean,
495      #   respectively, a low or moderate degree of temporal locality.
496      #
497      # Here we adopt Intel's x86/x86-64 naming scheme for the locality
498      # hints.  Using macros for these values in necessary since some
499      # compilers require an enum.
500      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
501      self.addDefine('PREFETCH_HINT_NTA', '0')
502      self.addDefine('PREFETCH_HINT_T0',  '3')
503      self.addDefine('PREFETCH_HINT_T1',  '2')
504      self.addDefine('PREFETCH_HINT_T2',  '1')
505    else:
506      self.addDefine('Prefetch(a,b,c)', ' ')
507    self.popLanguage()
508
509  def configureUnused(self):
510    '''Sees if __attribute((unused)) is supported'''
511    if self.framework.argDB['with-iphone'] or self.framework.argDB['with-cuda']:
512      self.addDefine('UNUSED', ' ')
513      return
514    self.pushLanguage(self.languages.clanguage)
515    if self.checkLink('__attribute((unused)) static int myfunc(void){ return 1;}', 'int i = myfunc();\n'):
516      self.addDefine('UNUSED', '__attribute((unused))')
517    else:
518      self.addDefine('UNUSED', ' ')
519    self.popLanguage()
520
521  def configureExpect(self):
522    '''Sees if the __builtin_expect directive is supported'''
523    self.pushLanguage(self.languages.clanguage)
524    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
525      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
526    self.popLanguage()
527
528  def configureFunctionName(self):
529    '''Sees if the compiler supports __func__ or a variant.  Falls back
530    on __FUNCT__ which PETSc source defines, but most users do not, thus
531    stack traces through user code are better when the compiler's
532    variant is used.'''
533    def getFunctionName(lang):
534      name = '__FUNCT__'
535      self.pushLanguage(lang)
536      if self.checkLink('', "if (__func__[0] != 'm') return 1;"):
537        name = '__func__'
538      elif self.checkLink('', "if (__FUNCTION__[0] != 'm') return 1;"):
539        name = '__FUNCTION__'
540      self.popLanguage()
541      return name
542    langs = []
543
544    self.addDefine('FUNCTION_NAME_C', getFunctionName('C'))
545    if hasattr(self.compilers, 'CXX'):
546      self.addDefine('FUNCTION_NAME_CXX', getFunctionName('Cxx'))
547    else:
548      self.addDefine('FUNCTION_NAME_CXX', '__FUNCT__')
549
550  def configureIntptrt(self):
551    '''Determine what to use for uintptr_t'''
552    def staticAssertSizeMatchesVoidStar(inc,typename):
553      # The declaration is an error if either array size is negative.
554      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
555      return self.checkCompile(inc, ('#define STATIC_ASSERT(cond) char negative_length_if_false[2*(!!(cond))-1]\n'
556                                     + 'STATIC_ASSERT(sizeof(void*) == sizeof(%s));'%typename))
557    self.pushLanguage(self.languages.clanguage)
558    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
559      self.addDefine('UINTPTR_T', 'uintptr_t')
560    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
561      self.addDefine('UINTPTR_T', 'unsigned long long')
562    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
563      self.addDefine('UINTPTR_T', 'size_t')
564    elif staticAssertSizeMatchesVoidStar('','unsigned long'):
565      self.addDefine('UINTPTR_T', 'unsigned long')
566    elif staticAssertSizeMatchesVoidStar('','unsigned'):
567      self.addDefine('UINTPTR_T', 'unsigned')
568    else:
569      raise RuntimeError('Could not find any unsigned integer type matching void*')
570    self.popLanguage()
571
572  def configureInline(self):
573    '''Get a generic inline keyword, depending on the language'''
574    if self.languages.clanguage == 'C':
575      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
576      self.addDefine('RESTRICT', self.compilers.cRestrict)
577    elif self.languages.clanguage == 'Cxx':
578      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
579      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
580    return
581
582  def configureSolaris(self):
583    '''Solaris specific stuff'''
584    if os.path.isdir(os.path.join('/usr','ucblib')):
585      try:
586        flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
587      except AttributeError:
588        flag = None
589      if flag is None:
590        self.compilers.LIBS += ' -L/usr/ucblib'
591      else:
592        self.compilers.LIBS += ' '+flag+'/usr/ucblib'
593    return
594
595  def configureLinux(self):
596    '''Linux specific stuff'''
597    # TODO: Test for this by mallocing an odd number of floats and checking the address
598    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
599    return
600
601  def configureWin32(self):
602    '''Win32 non-cygwin specific stuff'''
603    kernel32=0
604    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
605      self.addDefine('HAVE_WINDOWS_H',1)
606      self.addDefine('HAVE_GETCOMPUTERNAME',1)
607      kernel32=1
608    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
609      self.addDefine('HAVE_WINDOWS_H',1)
610      self.addDefine('HAVE_GETCOMPUTERNAME',1)
611      kernel32=1
612    if kernel32:
613      if self.framework.argDB['with-windows-graphics']:
614        self.addDefine('USE_WINDOWS_GRAPHICS',1)
615      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
616        self.addDefine('HAVE_LOADLIBRARY',1)
617      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
618        self.addDefine('HAVE_GETPROCADDRESS',1)
619      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
620        self.addDefine('HAVE_FREELIBRARY',1)
621      if self.checkLink('#include <Windows.h>','GetLastError()'):
622        self.addDefine('HAVE_GETLASTERROR',1)
623      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
624        self.addDefine('HAVE_SETLASTERROR',1)
625      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
626        self.addDefine('USE_NT_TIME',1)
627    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
628      self.addDefine('HAVE_GET_USER_NAME',1)
629    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
630      self.addDefine('HAVE_GET_USER_NAME',1)
631
632    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
633      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
634    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
635      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
636
637    self.types.check('int32_t', 'int')
638    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
639      self.addTypedef('int', 'uid_t')
640      self.addTypedef('int', 'gid_t')
641    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
642      self.framework.addDefine('R_OK', '04')
643      self.framework.addDefine('W_OK', '02')
644      self.framework.addDefine('X_OK', '01')
645    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
646      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
647      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
648    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
649      self.addDefine('HAVE_LARGE_INTEGER_U',1)
650
651    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
652    if self.checkCompile('#include <Windows.h>\n', 'int flags = O_BINARY;'):
653      self.addDefine('HAVE_O_BINARY',1)
654
655    if self.compilers.CC.find('win32fe') >= 0:
656      self.addDefine('PATH_SEPARATOR','\';\'')
657      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
658      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
659      self.addDefine('CANNOT_START_DEBUGGER',1)
660    else:
661      self.addDefine('PATH_SEPARATOR','\':\'')
662      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
663      self.addDefine('DIR_SEPARATOR','\'/\'')
664    return
665
666#-----------------------------------------------------------------------------------------------------
667  def configureDefaultArch(self):
668    conffile = os.path.join('conf', 'petscvariables')
669    if self.framework.argDB['with-default-arch']:
670      fd = file(conffile, 'w')
671      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
672      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
673      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
674      fd.close()
675      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
676    elif os.path.isfile(conffile):
677      try:
678        os.unlink(conffile)
679      except:
680        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
681    return
682
683#-----------------------------------------------------------------------------------------------------
684  def configureScript(self):
685    '''Output a script in the conf directory which will reproduce the configuration'''
686    import nargs
687    import sys
688    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
689    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
690    if 'configModules' in args:
691      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
692        del args['configModules']
693    if 'optionsModule' in args:
694      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
695        del args['optionsModule']
696    if not 'PETSC_ARCH' in args:
697      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
698    f = file(scriptName, 'w')
699    f.write('#!'+sys.executable+'\n')
700    f.write('if __name__ == \'__main__\':\n')
701    f.write('  import sys\n')
702    f.write('  import os\n')
703    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
704    f.write('  import configure\n')
705    # pretty print repr(args.values())
706    f.write('  configure_options = [\n')
707    for itm in sorted(args.values()):
708      f.write('    \''+str(itm)+'\',\n')
709    f.write('  ]\n')
710    f.write('  configure.petsc_configure(configure_options)\n')
711    f.close()
712    try:
713      os.chmod(scriptName, 0775)
714    except OSError, e:
715      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
716    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
717    return
718
719  def configureInstall(self):
720    '''Setup the directories for installation'''
721    if self.framework.argDB['prefix']:
722      self.installdir = self.framework.argDB['prefix']
723      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
724                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
725                                              '-@echo "========================================="'])
726    else:
727      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
728      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
729                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
730                                              '-@echo "========================================="'])
731      return
732
733  def configureGCOV(self):
734    if self.framework.argDB['with-gcov']:
735      self.addDefine('USE_GCOV','1')
736    return
737
738  def configureFortranFlush(self):
739    if hasattr(self.compilers, 'FC'):
740      for baseName in ['flush','flush_']:
741        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
742          self.addDefine('HAVE_'+baseName.upper(), 1)
743          return
744
745
746  def configure(self):
747    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
748      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
749    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
750      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
751    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)):
752      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
753    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
754    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
755    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
756    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
757    if self.libraries.math is None:
758      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
759    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
760      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
761    self.executeTest(self.configureInline)
762    self.executeTest(self.configurePrefetch)
763    self.executeTest(self.configureUnused)
764    self.executeTest(self.configureExpect);
765    self.executeTest(self.configureFunctionName);
766    self.executeTest(self.configureIntptrt);
767    self.executeTest(self.configureSolaris)
768    self.executeTest(self.configureLinux)
769    self.executeTest(self.configureWin32)
770    self.executeTest(self.configureDefaultArch)
771    self.executeTest(self.configureScript)
772    self.executeTest(self.configureInstall)
773    self.executeTest(self.configureGCOV)
774    self.executeTest(self.configureFortranFlush)
775    # dummy rules, always needed except for remote builds
776    self.addMakeRule('remote','')
777    self.addMakeRule('remoteclean','')
778
779    self.Dump()
780    self.dumpConfigInfo()
781    self.dumpMachineInfo()
782    self.dumpCMakeConfig()
783    self.dumpCMakeLists()
784    self.cmakeBoot()
785    self.framework.log.write('================================================================================\n')
786    self.logClear()
787    return
788