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