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