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