xref: /petsc/config/PETSc/Configure.py (revision 3e39abd9c4a26f4eec712b4f662a70ce68a962fa)
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=<path>',                  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=<no,yes>',            nargs.ArgDownload(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    #force blaslapack to depend on scalarType so precision is set before BlasLapack is built
62    self.blaslapack    = framework.require('config.packages.BlasLapack', self)
63    framework.require('PETSc.utilities.scalarTypes', self.blaslapack)
64    self.blaslapack.archProvider      = self.arch
65    self.blaslapack.precisionProvider = self.scalartypes
66    self.blaslapack.installDirProvider= self.petscdir
67
68    self.mpi           = framework.require('config.packages.MPI',        self)
69    self.mpi.archProvider             = self.arch
70    self.mpi.languageProvider         = self.languages
71    self.mpi.installDirProvider       = self.petscdir
72    self.umfpack       = framework.require('config.packages.UMFPACK',    self)
73    self.umfpack.archProvider         = self.arch
74    self.umfpack.languageProvider     = self.languages
75    self.umfpack.installDirProvider   = self.petscdir
76    self.boost         = framework.require('config.packages.boost',      self)
77    self.boost.archProvider           = self.arch
78    self.boost.languageProvider       = self.languages
79    self.boost.installDirProvider     = self.petscdir
80    self.Fiat          = framework.require('config.packages.Fiat',       self)
81    self.Fiat.archProvider            = self.arch
82    self.Fiat.languageProvider        = self.languages
83    self.Fiat.installDirProvider      = self.petscdir
84    self.ExodusII      = framework.require('config.packages.ExodusII',   self)
85    self.ExodusII.archProvider        = self.arch
86    self.ExodusII.languageProvider    = self.languages
87    self.ExodusII.installDirProvider  = self.petscdir
88
89    self.compilers.headerPrefix = self.headerPrefix
90    self.types.headerPrefix     = self.headerPrefix
91    self.headers.headerPrefix   = self.headerPrefix
92    self.functions.headerPrefix = self.headerPrefix
93    self.libraries.headerPrefix = self.headerPrefix
94    self.blaslapack.headerPrefix = self.headerPrefix
95    self.mpi.headerPrefix        = self.headerPrefix
96    headersC = map(lambda name: name+'.h', ['dos', 'endian', 'fcntl', 'float', 'io', 'limits', 'malloc', 'pwd', 'search', 'strings',
97                                            'unistd', 'machine/endian', 'sys/param', 'sys/procfs', 'sys/resource',
98                                            'sys/systeminfo', 'sys/times', 'sys/utsname','string', 'stdlib','memory',
99                                            'sys/socket','sys/wait','netinet/in','netdb','Direct','time','Ws2tcpip','sys/types',
100                                            'WindowsX', 'cxxabi','float','ieeefp','stdint','fenv'])
101    functions = ['access', '_access', 'clock', 'drand48', 'getcwd', '_getcwd', 'getdomainname', 'gethostname', 'getpwuid',
102                 'gettimeofday', 'getwd', 'memalign', 'memmove', 'mkstemp', 'popen', 'PXFGETARG', 'rand', 'getpagesize',
103                 'readlink', 'realpath',  'sigaction', 'signal', 'sigset', 'nanosleep', 'usleep', 'sleep', '_sleep', 'socket',
104                 'times', 'gethostbyname', 'uname','snprintf','_snprintf','_fullpath','lseek','_lseek','time','fork','stricmp',
105                 'strcasecmp', 'bzero', 'dlopen', 'dlsym', 'dlclose', 'dlerror',
106                 '_intel_fast_memcpy','_intel_fast_memset']
107    libraries1 = [(['socket', 'nsl'], 'socket'), (['fpe'], 'handle_sigfpes')]
108    self.headers.headers.extend(headersC)
109    self.functions.functions.extend(functions)
110    self.libraries.libraries.extend(libraries1)
111    return
112
113  def defineAutoconfMacros(self):
114    self.hostMacro = 'dnl Version: 2.13\ndnl Variable: host_cpu\ndnl Variable: host_vendor\ndnl Variable: host_os\nAC_CANONICAL_HOST'
115    return
116
117  def Dump(self):
118    ''' Actually put the values into the configuration files '''
119    # eventually everything between -- should be gone
120#-----------------------------------------------------------------------------------------------------
121
122    # Sometimes we need C compiler, even if built with C++
123    self.setCompilers.pushLanguage('C')
124    self.addMakeMacro('CC_FLAGS',self.setCompilers.getCompilerFlags())
125    self.setCompilers.popLanguage()
126
127    # C preprocessor values
128    self.addMakeMacro('CPP_FLAGS',self.setCompilers.CPPFLAGS+self.CHUD.CPPFLAGS)
129
130    # compiler values
131    self.setCompilers.pushLanguage(self.languages.clanguage)
132    self.addMakeMacro('PCC',self.setCompilers.getCompiler())
133    self.addMakeMacro('PCC_FLAGS',self.setCompilers.getCompilerFlags())
134    self.setCompilers.popLanguage()
135    # .o or .obj
136    self.addMakeMacro('CC_SUFFIX','o')
137
138    # executable linker values
139    self.setCompilers.pushLanguage(self.languages.clanguage)
140    pcc_linker = self.setCompilers.getLinker()
141    self.addMakeMacro('PCC_LINKER',pcc_linker)
142    self.addMakeMacro('PCC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
143    self.setCompilers.popLanguage()
144    # '' for Unix, .exe for Windows
145    self.addMakeMacro('CC_LINKER_SUFFIX','')
146    self.addMakeMacro('PCC_LINKER_LIBS',self.libraries.toStringNoDupes(self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' '))+self.CHUD.LIBS)
147
148    if hasattr(self.compilers, 'FC'):
149      self.setCompilers.pushLanguage('FC')
150      # need FPPFLAGS in config/setCompilers
151      self.addDefine('HAVE_FORTRAN','1')
152      self.addMakeMacro('FPP_FLAGS',self.setCompilers.CPPFLAGS)
153
154      # compiler values
155      self.addMakeMacro('FC_FLAGS',self.setCompilers.getCompilerFlags())
156      self.setCompilers.popLanguage()
157      # .o or .obj
158      self.addMakeMacro('FC_SUFFIX','o')
159
160      # executable linker values
161      self.setCompilers.pushLanguage('FC')
162      # Cannot have NAG f90 as the linker - so use pcc_linker as fc_linker
163      fc_linker = self.setCompilers.getLinker()
164      if config.setCompilers.Configure.isNAG(fc_linker):
165        self.addMakeMacro('FC_LINKER',pcc_linker)
166      else:
167        self.addMakeMacro('FC_LINKER',fc_linker)
168      self.addMakeMacro('FC_LINKER_FLAGS',self.setCompilers.getLinkerFlags())
169      # apple requires this shared library linker flag on SOME versions of the os
170      if self.setCompilers.getLinkerFlags().find('-Wl,-commons,use_dylibs') > -1:
171        self.addMakeMacro('DARWIN_COMMONS_USE_DYLIBS',' -Wl,-commons,use_dylibs ')
172      self.setCompilers.popLanguage()
173
174      # F90 Modules
175      if self.setCompilers.fortranModuleIncludeFlag:
176        self.addMakeMacro('FC_MODULE_FLAG', self.setCompilers.fortranModuleIncludeFlag)
177      else: # for non-f90 compilers like g77
178        self.addMakeMacro('FC_MODULE_FLAG', '-I')
179      if self.setCompilers.fortranModuleIncludeFlag:
180        self.addMakeMacro('FC_MODULE_OUTPUT_FLAG', self.setCompilers.fortranModuleOutputFlag)
181    else:
182      self.addMakeMacro('FC','')
183
184    # shared library linker values
185    self.setCompilers.pushLanguage(self.languages.clanguage)
186    # need to fix BuildSystem to collect these separately
187    self.addMakeMacro('SL_LINKER',self.setCompilers.getLinker())
188    self.addMakeMacro('SL_LINKER_FLAGS','${PCC_LINKER_FLAGS}')
189    self.setCompilers.popLanguage()
190    # One of 'a', 'so', 'lib', 'dll', 'dylib' (perhaps others also?) depending on the library generator and architecture
191    # Note: . is not included in this macro, consistent with AR_LIB_SUFFIX
192    if self.setCompilers.sharedLibraryExt == self.setCompilers.AR_LIB_SUFFIX:
193      self.addMakeMacro('SL_LINKER_SUFFIX', '')
194      self.addDefine('SLSUFFIX','""')
195    else:
196      self.addMakeMacro('SL_LINKER_SUFFIX', self.setCompilers.sharedLibraryExt)
197      self.addDefine('SLSUFFIX','"'+self.setCompilers.sharedLibraryExt+'"')
198
199    #SL_LINKER_LIBS is currently same as PCC_LINKER_LIBS - so simplify
200    self.addMakeMacro('SL_LINKER_LIBS','${PCC_LINKER_LIBS}')
201    #self.addMakeMacro('SL_LINKER_LIBS',self.libraries.toStringNoDupes(self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' ')))
202
203#-----------------------------------------------------------------------------------------------------
204
205    # CONLY or CPP. We should change the PETSc makefiles to do this better
206    if self.languages.clanguage == 'C': lang = 'CONLY'
207    else: lang = 'CXXONLY'
208    self.addMakeMacro('PETSC_LANGUAGE',lang)
209
210    # real or complex
211    self.addMakeMacro('PETSC_SCALAR',self.scalartypes.scalartype)
212    # double or float
213    self.addMakeMacro('PETSC_PRECISION',self.scalartypes.precision)
214
215    if self.framework.argDB['with-batch']:
216      self.addMakeMacro('PETSC_WITH_BATCH','1')
217
218    # Test for compiler-specific macros that need to be defined.
219    if self.setCompilers.isCray('CC'):
220      self.addDefine('HAVE_CRAYC','1')
221
222#-----------------------------------------------------------------------------------------------------
223    if self.functions.haveFunction('gethostbyname') and self.functions.haveFunction('socket'):
224      self.addDefine('USE_SOCKET_VIEWER','1')
225
226#-----------------------------------------------------------------------------------------------------
227    # print include and lib for external packages
228    self.framework.packages.reverse()
229    includes = []
230    libs = []
231    for i in self.framework.packages:
232      if i.useddirectly:
233        self.addDefine('HAVE_'+i.PACKAGE, 1)  # ONLY list package if it is used directly by PETSc (and not only by another package)
234      if not isinstance(i.lib, list):
235        i.lib = [i.lib]
236      libs.extend(i.lib)
237      self.addMakeMacro(i.PACKAGE+'_LIB', self.libraries.toStringNoDupes(i.lib))
238      if hasattr(i,'include'):
239        if not isinstance(i.include,list):
240          i.include = [i.include]
241        includes.extend(i.include)
242        self.addMakeMacro(i.PACKAGE+'_INCLUDE',self.headers.toStringNoDupes(i.include))
243    self.addMakeMacro('PACKAGES_LIBS',self.libraries.toStringNoDupes(libs+self.libraries.math))
244    self.PACKAGES_LIBS = self.libraries.toStringNoDupes(libs+self.libraries.math)
245    self.addMakeMacro('PACKAGES_INCLUDES',self.headers.toStringNoDupes(includes))
246    self.PACKAGES_INCLUDES = self.headers.toStringNoDupes(includes)
247    if hasattr(self.compilers, 'FC'):
248      if self.compilers.fortranIsF90:
249        self.addMakeMacro('PACKAGES_MODULES_INCLUDES',self.headers.toStringModulesNoDupes(includes))
250
251    self.addMakeMacro('DESTDIR',self.installdir)
252    self.addDefine('LIB_DIR','"'+os.path.join(self.installdir,'lib')+'"')
253
254    if self.framework.argDB['with-single-library']:
255      # overrides the values set in conf/variables
256      self.addMakeMacro('LIBNAME','${INSTALL_LIB_DIR}/libpetsc.${AR_LIB_SUFFIX}')
257      self.addMakeMacro('PETSC_SYS_LIB_BASIC','-lpetsc')
258      self.addMakeMacro('PETSC_VEC_LIB_BASIC','-lpetsc')
259      self.addMakeMacro('PETSC_MAT_LIB_BASIC','-lpetsc')
260      self.addMakeMacro('PETSC_DM_LIB_BASIC','-lpetsc')
261      self.addMakeMacro('PETSC_KSP_LIB_BASIC','-lpetsc')
262      self.addMakeMacro('PETSC_SNES_LIB_BASIC','-lpetsc')
263      self.addMakeMacro('PETSC_TS_LIB_BASIC','-lpetsc')
264      self.addMakeMacro('PETSC_LIB_BASIC','-lpetsc')
265      self.addMakeMacro('PETSC_CONTRIB_BASIC','-lpetsc')
266      self.addMakeMacro('SHLIBS','libpetsc')
267      self.addDefine('USE_SINGLE_LIBRARY', '1')
268
269    if not os.path.exists(os.path.join(self.petscdir.dir,self.arch.arch,'lib')):
270      os.makedirs(os.path.join(self.petscdir.dir,self.arch.arch,'lib'))
271
272    # add a makefile entry for configure options
273    self.addMakeMacro('CONFIGURE_OPTIONS', self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"'))
274    return
275
276  def dumpConfigInfo(self):
277    import time
278    fd = file(os.path.join(self.arch.arch,'include','petscconfiginfo.h'),'w')
279    fd.write('static const char *petscconfigureruntime = "'+time.ctime(time.time())+'";\n')
280    fd.write('static const char *petscconfigureoptions = "'+self.framework.getOptionsString(['configModules', 'optionsModule']).replace('\"','\\"')+'";\n')
281    fd.close()
282    return
283
284  def dumpMachineInfo(self):
285    import platform
286    import time
287    import script
288    fd = file(os.path.join(self.arch.arch,'include','petscmachineinfo.h'),'w')
289    fd.write('static const char *petscmachineinfo = \"\\n\"\n')
290    fd.write('\"-----------------------------------------\\n\"\n')
291    if os.path.isfile(os.path.join('/usr', 'bin', 'cygcheck.exe')):
292      fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), script.Script.executeShellCommand('hostname|/usr/bin/dos2unix')))
293    else:
294      fd.write('\"Libraries compiled on %s on %s \\n\"\n' % (time.ctime(time.time()), platform.node()))
295    fd.write('\"Machine characteristics: %s\\n\"' % (platform.platform()))
296    fd.write('\"Using PETSc directory: %s\\n\"' % (self.petscdir.dir))
297    fd.write('\"Using PETSc arch: %s\\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\"' % (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\"' % (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\"' % ('-I'+os.path.join(self.petscdir.dir, self.arch.arch, 'include'), '-I'+os.path.join(self.petscdir.dir, 'include'), self.PACKAGES_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\"' % (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\"' % (self.setCompilers.getLinker()))
318      self.setCompilers.popLanguage()
319    fd.write('\"Using libraries: %s%s -L%s %s %s %s\\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.PACKAGES_LIBS, self.libraries.toStringNoDupes(self.compilers.flibs+self.compilers.cxxlibs+self.compilers.LIBS.split(' '))+self.CHUD.LIBS))
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(list,new):
366      for x in ensurelist(new):
367        if x not in list:
368          list.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
393    def writeBuildFlags(fd):
394      lib_paths = []
395      lib_libs  = []
396      includes  = []
397      libvars   = []
398      for pkg in self.framework.packages:
399        libs = ensurelist(pkg.lib)
400        lib_paths.extend(map(libpath,libs))
401        lib_libs.extend(map(cleanlib,libs))
402        uniqextend(includes,pkg.include)
403      for libname in nub(lib_libs):
404        libvar = 'PETSC_' + libname.upper() + '_LIB'
405        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + ' '.join('"' + path + '"' for path in nub(lib_paths)) + ')\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 configurePrefetch(self):
417    '''Sees if there are any prefetch functions supported'''
418    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-iphone']:
419      self.addDefine('Prefetch(a,b,c)', ' ')
420      return
421    self.pushLanguage(self.languages.clanguage)
422    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,(int)0);\n'):
423      self.addDefine('HAVE_XMMINTRIN_H', 1)
424      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(int)(c))')
425    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,(int)0);\n'):
426      self.addDefine('HAVE_XMMINTRIN_H', 1)
427      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(int)(c))')
428    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
429      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
430    else:
431      self.addDefine('Prefetch(a,b,c)', ' ')
432    self.popLanguage()
433
434  def configureExpect(self):
435    '''Sees if the __builtin_expect directive is supported'''
436    self.pushLanguage(self.languages.clanguage)
437    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
438      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
439    self.popLanguage()
440
441  def configureIntptrt(self):
442    '''Determine what to use for uintptr_t'''
443    def staticAssertSizeMatchesVoidStar(inc,typename):
444      # The declaration is an error if either array size is negative.
445      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
446      return self.checkCompile(inc, '#define SZ (sizeof(void*)-sizeof(%s))\nint type_is_too_large[SZ],type_is_too_small[-SZ];'%typename)
447    self.pushLanguage(self.languages.clanguage)
448    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
449      self.addDefine('UINTPTR_T', 'uintptr_t')
450    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
451      self.addDefine('UINTPTR_T', 'unsigned long long')
452    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
453      self.addDefine('UINTPTR_T', 'size_t')
454    elif staticAssertSizeMatchesVoidStar('','unsigned'):
455      self.addDefine('UINTPTR_T', 'unsigned')
456    self.popLanguage()
457
458  def configureInline(self):
459    '''Get a generic inline keyword, depending on the language'''
460    if self.languages.clanguage == 'C':
461      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
462      self.addDefine('RESTRICT', self.compilers.cRestrict)
463    elif self.languages.clanguage == 'Cxx':
464      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
465      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
466    return
467
468  def configureSolaris(self):
469    '''Solaris specific stuff'''
470    if self.arch.hostOsBase.startswith('solaris'):
471      if os.path.isdir(os.path.join('/usr','ucblib')):
472        try:
473          flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
474        except AttributeError:
475          flag = None
476        if flag is None:
477          self.compilers.LIBS += ' -L/usr/ucblib'
478        else:
479          self.compilers.LIBS += ' '+flag+'/usr/ucblib'
480    return
481
482  def configureLinux(self):
483    '''Linux specific stuff'''
484    if self.arch.hostOsBase == 'linux':
485      self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
486    return
487
488  def configureWin32(self):
489    '''Win32 non-cygwin specific stuff'''
490    kernel32=0
491    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
492      self.addDefine('HAVE_WINDOWS_H',1)
493      self.addDefine('HAVE_GETCOMPUTERNAME',1)
494      kernel32=1
495    elif self.libraries.add('kernel32','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
496      self.addDefine('HAVE_WINDOWS_H',1)
497      self.addDefine('HAVE_GETCOMPUTERNAME',1)
498      kernel32=1
499    if kernel32:
500      if self.framework.argDB['with-windows-graphics']:
501        self.addDefine('USE_WINDOWS_GRAPHICS',1)
502      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
503        self.addDefine('HAVE_LOADLIBRARY',1)
504      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
505        self.addDefine('HAVE_GETPROCADDRESS',1)
506      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
507        self.addDefine('HAVE_FREELIBRARY',1)
508      if self.checkLink('#include <Windows.h>','GetLastError()'):
509        self.addDefine('HAVE_GETLASTERROR',1)
510      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
511        self.addDefine('HAVE_SETLASTERROR',1)
512      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
513        self.addDefine('USE_NT_TIME',1)
514    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
515      self.addDefine('HAVE_GET_USER_NAME',1)
516    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
517      self.addDefine('HAVE_GET_USER_NAME',1)
518
519    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
520      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
521    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
522      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
523
524    self.types.check('int32_t', 'int')
525    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
526      self.addTypedef('int', 'uid_t')
527      self.addTypedef('int', 'gid_t')
528    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
529      self.framework.addDefine('R_OK', '04')
530      self.framework.addDefine('W_OK', '02')
531      self.framework.addDefine('X_OK', '01')
532    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
533      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
534      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
535    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
536      self.addDefine('HAVE_LARGE_INTEGER_U',1)
537
538    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
539    if self.checkCompile('#include <Windows.h>\n',''):
540      self.addDefine('HAVE_O_BINARY',1)
541
542    if self.compilers.CC.find('win32fe') >= 0:
543      self.addDefine('PATH_SEPARATOR','\';\'')
544      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
545      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
546      self.addDefine('CANNOT_START_DEBUGGER',1)
547    else:
548      self.addDefine('PATH_SEPARATOR','\':\'')
549      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
550      self.addDefine('DIR_SEPARATOR','\'/\'')
551    return
552
553#-----------------------------------------------------------------------------------------------------
554  def configureDefaultArch(self):
555    conffile = os.path.join('conf', 'petscvariables')
556    if self.framework.argDB['with-default-arch']:
557      fd = file(conffile, 'w')
558      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
559      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
560      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
561      fd.close()
562      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
563    elif os.path.isfile(conffile):
564      try:
565        os.unlink(conffile)
566      except:
567        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
568    return
569
570#-----------------------------------------------------------------------------------------------------
571  def configureScript(self):
572    '''Output a script in the conf directory which will reproduce the configuration'''
573    import nargs
574    import sys
575    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
576    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
577    if 'configModules' in args:
578      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
579        del args['configModules']
580    if 'optionsModule' in args:
581      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
582        del args['optionsModule']
583    if not 'PETSC_ARCH' in args:
584      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
585    f = file(scriptName, 'w')
586    f.write('#!'+sys.executable+'\n')
587    f.write('if __name__ == \'__main__\':\n')
588    f.write('  import sys\n')
589    f.write('  import os\n')
590    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
591    f.write('  import configure\n')
592    # pretty print repr(args.values())
593    f.write('  configure_options = [\n')
594    for itm in args.values():
595      f.write('    \''+str(itm)+'\',\n')
596    f.write('  ]\n')
597    f.write('  configure.petsc_configure(configure_options)\n')
598    f.close()
599    try:
600      os.chmod(scriptName, 0775)
601    except OSError, e:
602      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
603    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
604    return
605
606  def configureInstall(self):
607    '''Setup the directories for installation'''
608    if self.framework.argDB['prefix']:
609      self.installdir = self.framework.argDB['prefix']
610      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
611                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
612                                              '-@echo "========================================="'])
613    else:
614      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
615      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
616                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
617                                              '-@echo "========================================="'])
618      return
619
620  def configureGCOV(self):
621    if self.framework.argDB['with-gcov']:
622      self.addDefine('USE_GCOV','1')
623    return
624
625  def configureFortranFlush(self):
626    if hasattr(self.compilers, 'FC'):
627      for baseName in ['flush','flush_']:
628        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
629          self.addDefine('HAVE_'+baseName.upper(), 1)
630          return
631
632
633  def configure(self):
634    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
635      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
636    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
637      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
638    self.framework.header          = self.arch.arch+'/include/petscconf.h'
639    self.framework.cHeader         = self.arch.arch+'/include/petscfix.h'
640    self.framework.makeMacroHeader = self.arch.arch+'/conf/petscvariables'
641    self.framework.makeRuleHeader  = self.arch.arch+'/conf/petscrules'
642    if self.libraries.math is None:
643      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
644    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
645      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
646    self.executeTest(self.configureInline)
647    self.executeTest(self.configurePrefetch)
648    self.executeTest(self.configureExpect);
649    self.executeTest(self.configureIntptrt);
650    self.executeTest(self.configureSolaris)
651    self.executeTest(self.configureLinux)
652    self.executeTest(self.configureWin32)
653    self.executeTest(self.configureDefaultArch)
654    self.executeTest(self.configureScript)
655    self.executeTest(self.configureInstall)
656    self.executeTest(self.configureGCOV)
657    self.executeTest(self.configureFortranFlush)
658    # dummy rules, always needed except for remote builds
659    self.addMakeRule('remote','')
660    self.addMakeRule('remoteclean','')
661
662    self.Dump()
663    self.dumpConfigInfo()
664    self.dumpMachineInfo()
665    self.dumpCMakeConfig()
666    self.framework.log.write('================================================================================\n')
667    self.logClear()
668    return
669