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