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