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