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