xref: /petsc/config/PETSc/Configure.py (revision 511a6afc270b1ade72e0742a89628c8778c6cbf8)
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      return a if isinstance(a,list) else [a]
336    def libpath(lib):
337      'Returns a search path if that is what this item provides, else "" which will be cleaned out later'
338      if lib.startswith('-L'): return lib[2:]
339      if lib.startswith('-R'): return lib[2:]
340      if lib.startswith('-Wl,-rpath,'):
341        # This case occurs when an external package needs a specific system library that is normally provided by the compiler.
342        # In other words, the -L path is builtin to the wrapper or compiler, here we provide it so that CMake can locate the
343        # corresponding library.
344        return lib[len('-Wl,-rpath,'):]
345      if lib.startswith('-'): return ''
346      return os.path.dirname(lib)
347    def cleanlib(lib):
348      'Returns a library name if that is what this item provides, else "" which will be cleaned out later'
349      if lib.startswith('-l'):  return lib[2:]
350      if lib.startswith('-Wl') or lib.startswith('-L'): return ''
351      lib = os.path.splitext(os.path.basename(lib))[0]
352      if lib.startswith('lib'): return lib[3:]
353      return lib
354    def nub(lst):
355      unique = []
356      for elem in lst:
357        if elem not in unique and elem != '':
358          unique.append(elem)
359      return unique
360    def cmakeexpand(varname):
361      return r'"${' + varname + r'}"'
362    def uniqextend(list,new):
363      for x in ensurelist(new):
364        if x not in list:
365          list.append(x)
366    def notstandardinclude(path):
367      return path not in '/usr/include /usr/local/include'.split()
368    def writeMacroDefinitions(fd):
369      if self.mpi.usingMPIUni:
370        cmakeset(fd,'PETSC_HAVE_MPIUNI')
371      for pkg in self.framework.packages:
372        if pkg.useddirectly:
373          cmakeset(fd,'PETSC_HAVE_' + pkg.PACKAGE)
374      for name,val in self.functions.defines.items():
375        cmakeset(fd,'PETSC_'+name,val)
376      for dct in [self.defines, self.libraryoptions.defines]:
377        for k,v in dct.items():
378          if k.startswith('USE_'):
379            cmakeset(fd,'PETSC_' + k, v)
380      cmakeset(fd,'PETSC_USE_COMPLEX', self.scalartypes.scalartype == 'complex')
381      cmakeset(fd,'PETSC_USE_SCALAR_' + self.scalartypes.precision.upper())
382      cmakeset(fd,'PETSC_CLANGUAGE_'+self.languages.clanguage)
383      if hasattr(self.compilers, 'FC'):
384        cmakeset(fd,'PETSC_HAVE_FORTRAN')
385      if self.compilers.fortranIsF90:
386        cmakeset(fd,'PETSC_USING_F90')
387      if self.sharedlibraries.useShared:
388        cmakeset(fd,'BUILD_SHARED_LIBS')
389    def writeBuildFlags(fd):
390      lib_paths = []
391      lib_libs  = []
392      includes  = []
393      libvars   = []
394      for pkg in self.framework.packages:
395        libs = ensurelist(pkg.lib)
396        lib_paths.extend(map(libpath,libs))
397        lib_libs.extend(map(cleanlib,libs))
398        uniqextend(includes,pkg.include)
399      for libname in nub(lib_libs):
400        libvar = 'PETSC_' + libname.upper() + '_LIB'
401        fd.write('find_library (' + libvar + ' ' + libname + ' HINTS ' + ' '.join('"' + path + '"' for path in nub(lib_paths)) + ')\n')
402        libvars.append(libvar)
403      fd.write('mark_as_advanced (' + ' '.join(libvars) + ')\n')
404      fd.write('set (PETSC_PACKAGE_LIBS ' + ' '.join(map(cmakeexpand,libvars)) + ')\n')
405      fd.write('set (PETSC_PACKAGE_INCLUDES ' + ' '.join(map(lambda i: '"'+i+'"',filter(notstandardinclude,includes))) + ')\n')
406    fd = open(os.path.join(self.arch.arch,'conf','PETScConfig.cmake'), 'w')
407    writeMacroDefinitions(fd)
408    writeBuildFlags(fd)
409    fd.close()
410    return
411
412  def configurePrefetch(self):
413    '''Sees if there are any prefetch functions supported'''
414    if config.setCompilers.Configure.isSolaris() or self.framework.argDB['with-iphone']:
415      self.addDefine('Prefetch(a,b,c)', ' ')
416      return
417    self.pushLanguage(self.languages.clanguage)
418    if self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch(v,(int)0);\n'):
419      self.addDefine('HAVE_XMMINTRIN_H', 1)
420      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const void*)(a),(int)(c))')
421    elif self.checkLink('#include <xmmintrin.h>', 'void *v = 0;_mm_prefetch((const char*)v,(int)0);\n'):
422      self.addDefine('HAVE_XMMINTRIN_H', 1)
423      self.addDefine('Prefetch(a,b,c)', '_mm_prefetch((const char*)(a),(int)(c))')
424    elif self.checkLink('', 'void *v = 0;__builtin_prefetch(v,0,0);\n'):
425      self.addDefine('Prefetch(a,b,c)', '__builtin_prefetch((a),(b),(c))')
426    else:
427      self.addDefine('Prefetch(a,b,c)', ' ')
428    self.popLanguage()
429
430  def configureExpect(self):
431    '''Sees if the __builtin_expect directive is supported'''
432    self.pushLanguage(self.languages.clanguage)
433    if self.checkLink('', 'if (__builtin_expect(0,1)) return 1;'):
434      self.addDefine('HAVE_BUILTIN_EXPECT', 1)
435    self.popLanguage()
436
437  def configureIntptrt(self):
438    '''Determine what to use for uintptr_t'''
439    def staticAssertSizeMatchesVoidStar(inc,typename):
440      # The declaration is an error if either array size is negative.
441      # It should be okay to use an int that is too large, but it would be very unlikely for this to be the case
442      return self.checkCompile(inc, '#define SZ (sizeof(void*)-sizeof(%s))\nint type_is_too_large[SZ],type_is_too_small[-SZ];'%typename)
443    self.pushLanguage(self.languages.clanguage)
444    if self.checkCompile('#include <stdint.h>', 'int x; uintptr_t i = (uintptr_t)&x;'):
445      self.addDefine('UINTPTR_T', 'uintptr_t')
446    elif staticAssertSizeMatchesVoidStar('','unsigned long long'):
447      self.addDefine('UINTPTR_T', 'unsigned long long')
448    elif staticAssertSizeMatchesVoidStar('#include <stdlib.h>','size_t') or staticAssertSizeMatchesVoidStar('#include <string.h>', 'size_t'):
449      self.addDefine('UINTPTR_T', 'size_t')
450    elif staticAssertSizeMatchesVoidStar('','unsigned'):
451      self.addDefine('UINTPTR_T', 'unsigned')
452    self.popLanguage()
453
454  def configureInline(self):
455    '''Get a generic inline keyword, depending on the language'''
456    if self.languages.clanguage == 'C':
457      self.addDefine('STATIC_INLINE', self.compilers.cStaticInlineKeyword)
458      self.addDefine('RESTRICT', self.compilers.cRestrict)
459    elif self.languages.clanguage == 'Cxx':
460      self.addDefine('STATIC_INLINE', self.compilers.cxxStaticInlineKeyword)
461      self.addDefine('RESTRICT', self.compilers.cxxRestrict)
462    return
463
464  def configureSolaris(self):
465    '''Solaris specific stuff'''
466    if self.arch.hostOsBase.startswith('solaris'):
467      if os.path.isdir(os.path.join('/usr','ucblib')):
468        try:
469          flag = getattr(self.setCompilers, self.language[-1]+'SharedLinkerFlag')
470        except AttributeError:
471          flag = None
472        if flag is None:
473          self.compilers.LIBS += ' -L/usr/ucblib'
474        else:
475          self.compilers.LIBS += ' '+flag+'/usr/ucblib'
476    return
477
478  def configureLinux(self):
479    '''Linux specific stuff'''
480    if self.arch.hostOsBase == 'linux':
481      self.addDefine('HAVE_DOUBLE_ALIGN_MALLOC', 1)
482    return
483
484  def configureWin32(self):
485    '''Win32 non-cygwin specific stuff'''
486    kernel32=0
487    if self.libraries.add('Kernel32.lib','GetComputerName',prototype='#include <Windows.h>', call='GetComputerName(NULL,NULL);'):
488      self.addDefine('HAVE_WINDOWS_H',1)
489      self.addDefine('HAVE_GETCOMPUTERNAME',1)
490      kernel32=1
491    elif self.libraries.add('kernel32','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    if kernel32:
496      if self.framework.argDB['with-windows-graphics']:
497        self.addDefine('USE_WINDOWS_GRAPHICS',1)
498      if self.checkLink('#include <Windows.h>','LoadLibrary(0)'):
499        self.addDefine('HAVE_LOADLIBRARY',1)
500      if self.checkLink('#include <Windows.h>','GetProcAddress(0,0)'):
501        self.addDefine('HAVE_GETPROCADDRESS',1)
502      if self.checkLink('#include <Windows.h>','FreeLibrary(0)'):
503        self.addDefine('HAVE_FREELIBRARY',1)
504      if self.checkLink('#include <Windows.h>','GetLastError()'):
505        self.addDefine('HAVE_GETLASTERROR',1)
506      if self.checkLink('#include <Windows.h>','SetLastError(0)'):
507        self.addDefine('HAVE_SETLASTERROR',1)
508      if self.checkLink('#include <Windows.h>\n','QueryPerformanceCounter(0);\n'):
509        self.addDefine('USE_NT_TIME',1)
510    if self.libraries.add('Advapi32.lib','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
511      self.addDefine('HAVE_GET_USER_NAME',1)
512    elif self.libraries.add('advapi32','GetUserName',prototype='#include <Windows.h>', call='GetUserName(NULL,NULL);'):
513      self.addDefine('HAVE_GET_USER_NAME',1)
514
515    if not self.libraries.add('User32.lib','GetDC',prototype='#include <Windows.h>',call='GetDC(0);'):
516      self.libraries.add('user32','GetDC',prototype='#include <Windows.h>',call='GetDC(0);')
517    if not self.libraries.add('Gdi32.lib','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);'):
518      self.libraries.add('gdi32','CreateCompatibleDC',prototype='#include <Windows.h>',call='CreateCompatibleDC(0);')
519
520    self.types.check('int32_t', 'int')
521    if not self.checkCompile('#include <sys/types.h>\n','uid_t u;\n'):
522      self.addTypedef('int', 'uid_t')
523      self.addTypedef('int', 'gid_t')
524    if not self.checkLink('#if defined(PETSC_HAVE_UNISTD_H)\n#include <unistd.h>\n#endif\n','int a=R_OK;\n'):
525      self.framework.addDefine('R_OK', '04')
526      self.framework.addDefine('W_OK', '02')
527      self.framework.addDefine('X_OK', '01')
528    if not self.checkLink('#include <sys/stat.h>\n','int a=0;\nif (S_ISDIR(a)){}\n'):
529      self.framework.addDefine('S_ISREG(a)', '(((a)&_S_IFMT) == _S_IFREG)')
530      self.framework.addDefine('S_ISDIR(a)', '(((a)&_S_IFMT) == _S_IFDIR)')
531    if self.checkCompile('#include <Windows.h>\n','LARGE_INTEGER a;\nDWORD b=a.u.HighPart;\n'):
532      self.addDefine('HAVE_LARGE_INTEGER_U',1)
533
534    # Windows requires a Binary file creation flag when creating/opening binary files.  Is a better test in order?
535    if self.checkCompile('#include <Windows.h>\n',''):
536      self.addDefine('HAVE_O_BINARY',1)
537
538    if self.compilers.CC.find('win32fe') >= 0:
539      self.addDefine('PATH_SEPARATOR','\';\'')
540      self.addDefine('DIR_SEPARATOR','\'\\\\\'')
541      self.addDefine('REPLACE_DIR_SEPARATOR','\'/\'')
542      self.addDefine('CANNOT_START_DEBUGGER',1)
543    else:
544      self.addDefine('PATH_SEPARATOR','\':\'')
545      self.addDefine('REPLACE_DIR_SEPARATOR','\'\\\\\'')
546      self.addDefine('DIR_SEPARATOR','\'/\'')
547    return
548
549#-----------------------------------------------------------------------------------------------------
550  def configureDefaultArch(self):
551    conffile = os.path.join('conf', 'petscvariables')
552    if self.framework.argDB['with-default-arch']:
553      fd = file(conffile, 'w')
554      fd.write('PETSC_ARCH='+self.arch.arch+'\n')
555      fd.write('PETSC_DIR='+self.petscdir.dir+'\n')
556      fd.write('include ${PETSC_DIR}/${PETSC_ARCH}/conf/petscvariables\n')
557      fd.close()
558      self.framework.actions.addArgument('PETSc', 'Build', 'Set default architecture to '+self.arch.arch+' in '+conffile)
559    elif os.path.isfile(conffile):
560      try:
561        os.unlink(conffile)
562      except:
563        raise RuntimeError('Unable to remove file '+conffile+'. Did a different user create it?')
564    return
565
566#-----------------------------------------------------------------------------------------------------
567  def configureScript(self):
568    '''Output a script in the conf directory which will reproduce the configuration'''
569    import nargs
570    import sys
571    scriptName = os.path.join(self.arch.arch,'conf', 'reconfigure-'+self.arch.arch+'.py')
572    args = dict([(nargs.Arg.parseArgument(arg)[0], arg) for arg in self.framework.clArgs])
573    if 'configModules' in args:
574      if nargs.Arg.parseArgument(args['configModules'])[1] == 'PETSc.Configure':
575        del args['configModules']
576    if 'optionsModule' in args:
577      if nargs.Arg.parseArgument(args['optionsModule'])[1] == 'PETSc.compilerOptions':
578        del args['optionsModule']
579    if not 'PETSC_ARCH' in args:
580      args['PETSC_ARCH'] = 'PETSC_ARCH='+str(self.arch.arch)
581    f = file(scriptName, 'w')
582    f.write('#!'+sys.executable+'\n')
583    f.write('if __name__ == \'__main__\':\n')
584    f.write('  import sys\n')
585    f.write('  import os\n')
586    f.write('  sys.path.insert(0, os.path.abspath(\'config\'))\n')
587    f.write('  import configure\n')
588    # pretty print repr(args.values())
589    f.write('  configure_options = [\n')
590    for itm in args.values():
591      f.write('    \''+str(itm)+'\',\n')
592    f.write('  ]\n')
593    f.write('  configure.petsc_configure(configure_options)\n')
594    f.close()
595    try:
596      os.chmod(scriptName, 0775)
597    except OSError, e:
598      self.framework.logPrint('Unable to make reconfigure script executable:\n'+str(e))
599    self.framework.actions.addArgument('PETSc', 'File creation', 'Created '+scriptName+' for automatic reconfiguration')
600    return
601
602  def configureInstall(self):
603    '''Setup the directories for installation'''
604    if self.framework.argDB['prefix']:
605      self.installdir = self.framework.argDB['prefix']
606      self.addMakeRule('shared_install','',['-@echo "Now to install the libraries do:"',\
607                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} install"',\
608                                              '-@echo "========================================="'])
609    else:
610      self.installdir = os.path.join(self.petscdir.dir,self.arch.arch)
611      self.addMakeRule('shared_install','',['-@echo "Now to check if the libraries are working do:"',\
612                                              '-@echo "make PETSC_DIR=${PETSC_DIR} PETSC_ARCH=${PETSC_ARCH} test"',\
613                                              '-@echo "========================================="'])
614      return
615
616  def configureGCOV(self):
617    if self.framework.argDB['with-gcov']:
618      self.addDefine('USE_GCOV','1')
619    return
620
621  def configureFortranFlush(self):
622    if hasattr(self.compilers, 'FC'):
623      for baseName in ['flush','flush_']:
624        if self.libraries.check('', baseName, otherLibs = self.compilers.flibs, fortranMangle = 1):
625          self.addDefine('HAVE_'+baseName.upper(), 1)
626          return
627
628
629  def configure(self):
630    if not os.path.samefile(self.petscdir.dir, os.getcwd()):
631      raise RuntimeError('Wrong PETSC_DIR option specified: '+str(self.petscdir.dir) + '\n  Configure invoked in: '+os.path.realpath(os.getcwd()))
632    if self.framework.argDB['prefix'] and os.path.isdir(self.framework.argDB['prefix']) and os.path.samefile(self.framework.argDB['prefix'],self.petscdir.dir):
633      raise RuntimeError('Incorrect option --prefix='+self.framework.argDB['prefix']+' specified. It cannot be same as PETSC_DIR!')
634    self.framework.header          = self.arch.arch+'/include/petscconf.h'
635    self.framework.cHeader         = self.arch.arch+'/include/petscfix.h'
636    self.framework.makeMacroHeader = self.arch.arch+'/conf/petscvariables'
637    self.framework.makeRuleHeader  = self.arch.arch+'/conf/petscrules'
638    if self.libraries.math is None:
639      raise RuntimeError('PETSc requires a functional math library. Please send configure.log to petsc-maint@mcs.anl.gov.')
640    if self.languages.clanguage == 'Cxx' and not hasattr(self.compilers, 'CXX'):
641      raise RuntimeError('Cannot set C language to C++ without a functional C++ compiler.')
642    self.executeTest(self.configureInline)
643    self.executeTest(self.configurePrefetch)
644    self.executeTest(self.configureExpect);
645    self.executeTest(self.configureIntptrt);
646    self.executeTest(self.configureSolaris)
647    self.executeTest(self.configureLinux)
648    self.executeTest(self.configureWin32)
649    self.executeTest(self.configureDefaultArch)
650    self.executeTest(self.configureScript)
651    self.executeTest(self.configureInstall)
652    self.executeTest(self.configureGCOV)
653    self.executeTest(self.configureFortranFlush)
654    # dummy rules, always needed except for remote builds
655    self.addMakeRule('remote','')
656    self.addMakeRule('remoteclean','')
657
658    self.Dump()
659    self.dumpConfigInfo()
660    self.dumpMachineInfo()
661    self.dumpCMakeConfig()
662    self.framework.log.write('================================================================================\n')
663    self.logClear()
664    return
665