xref: /petsc/config/PETSc/Configure.py (revision 8bec4b269f8a86e4ca4a1013d6c434494601ad6c)
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    self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
582    return
583
584  def configureWin32(self):
585    '''Win32 non-cygwin specific stuff'''
586    kernel32=0
587    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
588      self.addDefine('HAVE_WINDOWS_H',1)
589      self.addDefine('HAVE_GETCOMPUTERNAME',1)
590      kernel32=1
591    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
592      self.addDefine('HAVE_WINDOWS_H',1)
593      self.addDefine('HAVE_GETCOMPUTERNAME',1)
594      kernel32=1
595    if kernel32:
596      if self.framework.argDB['with-windows-graphics']:
597        self.addDefine('USE_WINDOWS_GRAPHICS',1)
598      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
599        self.addDefine('HAVE_LOADLIBRARY',1)
600      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
601        self.addDefine('HAVE_GETPROCADDRESS',1)
602      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
603        self.addDefine('HAVE_FREELIBRARY',1)
604      if self.checkLink('#include <Windows.h>','GetLastError()'):
605        self.addDefine('HAVE_GETLASTERROR',1)
606      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
607        self.addDefine('HAVE_SETLASTERROR',1)
608      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
609        self.addDefine('USE_NT_TIME',1)
610    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
611      self.addDefine('HAVE_GET_USER_NAME',1)
612    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
613      self.addDefine('HAVE_GET_USER_NAME',1)
614
615    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
616      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
617    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
618      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
619
620    self.types.check('int32_t', 'int')
621    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
622      self.addTypedef('int', 'uid_t')
623      self.addTypedef('int', 'gid_t')
624    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
625      self.framework.addDefine('R_OK', '04')
626      self.framework.addDefine('W_OK', '02')
627      self.framework.addDefine('X_OK', '01')
628    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
629      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
630      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
631    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
632      self.addDefine('HAVE_LARGE_INTEGER_U',1)
633
634    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
635    if self.checkCompile('#include <Windows.h>\n',''):
636      self.addDefine('HAVE_O_BINARY',1)
637
638    if self.compilers.CC.find('win32fe') >= 0:
639      self.addDefine('PATH_SEPARATOR','\';\'')
640      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
641      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
642      self.addDefine('CANNOT_START_DEBUGGER',1)
643    else:
644      self.addDefine('PATH_SEPARATOR','\':\'')
645      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
646      self.addDefine('DIR_SEPARATOR','\'/\'')
647    return
648
649#-----------------------------------------------------------------------------------------------------
650  def configureDefaultArch(self):
651    conffile = os.path.join('conf', 'petscvariables')
652    if self.framework.argDB['with-default-arch']:
653      fd = file(conffile, 'w')
654      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
655      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
656      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
657      fd.close()
658      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
659    elif os.path.isfile(conffile):
660      try:
661        os.unlink(conffile)
662      except:
663        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
664    return
665
666#-----------------------------------------------------------------------------------------------------
667  def configureScript(self):
668    '''Output a script in the conf directory which will reproduce the configuration'''
669    import nargs
670    import sys
671    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
672    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
673    if 'configModules' in args:
674      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
675        del args['configModules']
676    if 'optionsModule' in args:
677      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
678        del args['optionsModule']
679    if not 'PETSC_ARCH' in args:
680      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
681    f = file(scriptName, 'w')
682    f.write('#!'+sys.executable+'\n')
683    f.write('if __name__ == \'__main__\':\n')
684    f.write('  import sys\n')
685    f.write('  import os\n')
686    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
687    f.write('  import configure\n')
688    # pretty print repr(args.values())
689    f.write('  configure_options = [\n')
690    for itm in args.values():
691      f.write('    \''+str(itm)+'\',\n')
692    f.write('  ]\n')
693    f.write('  configure.petsc_configure(configure_options)\n')
694    f.close()
695    try:
696      os.chmod(scriptName, 0775)
697    except OSError, e:
698      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
699    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
700    return
701
702  def configureInstall(self):
703    '''Setup the directories for installation'''
704    if self.framework.argDB['prefix']:
705      self.installdir = self.framework.argDB['prefix']
706      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
707                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
708                                              '-@echo "========================================="'])
709    else:
710      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
711      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
712                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
713                                              '-@echo "========================================="'])
714      return
715
716  def configureGCOV(self):
717    if self.framework.argDB['with-gcov']:
718      self.addDefine('USE_GCOV','1')
719    return
720
721  def configureFortranFlush(self):
722    if hasattr(self.compilers, 'FC'):
723      for baseName in ['flush','flush_']:
724        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
725          self.addDefine('HAVE_'+baseName.upper(), 1)
726          return
727
728
729  def configure(self):
730    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
731      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
732    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
733      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
734    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)):
735      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR/PETSC_ARCH!')
736    self.framework.header          = os.path.join(self.arch.arch,'include','petscconf.h')
737    self.framework.cHeader         = os.path.join(self.arch.arch,'include','petscfix.h')
738    self.framework.makeMacroHeader = os.path.join(self.arch.arch,'conf','petscvariables')
739    self.framework.makeRuleHeader  = os.path.join(self.arch.arch,'conf','petscrules')
740    if self.libraries.math is None:
741      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
742    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
743      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
744    self.executeTest(self.configureInline)
745    self.executeTest(self.configurePrefetch)
746    self.executeTest(self.configureUnused)
747    self.executeTest(self.configureExpect);
748    self.executeTest(self.configureFunctionName);
749    self.executeTest(self.configureIntptrt);
750    self.executeTest(self.configureSolaris)
751    self.executeTest(self.configureLinux)
752    self.executeTest(self.configureWin32)
753    self.executeTest(self.configureDefaultArch)
754    self.executeTest(self.configureScript)
755    self.executeTest(self.configureInstall)
756    self.executeTest(self.configureGCOV)
757    self.executeTest(self.configureFortranFlush)
758    # dummy rules, always needed except for remote builds
759    self.addMakeRule('remote','')
760    self.addMakeRule('remoteclean','')
761
762    self.Dump()
763    self.dumpConfigInfo()
764    self.dumpMachineInfo()
765    self.dumpCMakeConfig()
766    self.dumpCMakeLists()
767    self.cmakeBoot()
768    self.framework.log.write('================================================================================\n')
769    self.logClear()
770    return
771