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