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