1import config.base 2 3class Configure(config.base.Configure): 4 def __init__(self, framework, headers = []): 5 config.base.Configure.__init__(self, framework) 6 self.headerPrefix = '' 7 self.substPrefix = '' 8 self.headers = headers 9 return 10 11 def setupDependencies(self, framework): 12 config.base.Configure.setupDependencies(self, framework) 13 self.compilers = self.framework.require('config.compilers', self) 14 self.setCompilers = self.framework.require('config.setCompilers', self) 15 return 16 17 def getIncludeArgumentList(self, include): 18 '''Return the proper include line argument for the given filename as a list 19 - If the path is empty, return it unchanged 20 - If starts with - then return unchanged 21 - Otherwise return -I<include>''' 22 if not include: 23 return [] 24 include = include.replace('\\ ',' ').replace(' ', '\\ ') 25 include = include.replace('\\(','(').replace('(', '\\(') 26 include = include.replace('\\)',')').replace(')', '\\)') 27 if include[0] == '-': 28 return [include] 29 return ['-I'+include] 30 31 def getIncludeModulesArgumentList(self, include): 32 '''Return the proper include line argument for the given filename as a list 33 - If the path is empty, return it unchanged 34 - If starts with - then return unchanged 35 - Otherwise return -fortranmoduleflag includedirectory''' 36 if not include: 37 return [] 38 include = include.replace('\\ ',' ').replace(' ', '\\ ') 39 include = include.replace('\\(','(').replace('(', '\\(') 40 include = include.replace('\\)',')').replace(')', '\\)') 41 if include[0] == '-': 42 return [include] 43 44 self.pushLanguage('FC') 45 string = self.setCompilers.fortranModuleIncludeFlag+include 46 self.popLanguage() 47 return [string] 48 49 def getIncludeArgument(self, include): 50 '''Same as getIncludeArgumentList - except it returns a string instead of list.''' 51 return ' '.join(self.getIncludeArgumentList(include)) 52 53 def toString(self,includes): 54 '''Converts a list of includes to a string suitable for a compiler''' 55 return ' '.join([self.getIncludeArgument(include) for include in includes]) 56 57 def toStringNoDupes(self,includes,modincludes=[]): 58 '''Converts a list of -Iincludes and -fmodule flags to a string suitable for a compiler, removes duplicates''' 59 newincludes = [] 60 for include in includes: 61 newincludes += self.getIncludeArgumentList(include) 62 for modinclude in modincludes: 63 newincludes += self.getIncludeModulesArgumentList(modinclude) 64 includes = newincludes 65 newincludes = [] 66 for j in includes: 67 if j in newincludes: continue 68 newincludes.append(j) 69 return ' '.join(newincludes) 70 71 def getDefineMacro(self, macro): 72 return 'HAVE_MACRO_'+macro 73 74 def getDefineName(self, header): 75 return 'HAVE_'+header.upper().replace('.', '_').replace('/', '_') 76 77 def haveHeader(self, header): 78 return self.getDefineName(header) in self.defines 79 80 def check(self,header, adddefine = 1): 81 '''Checks for "header", and defines HAVE_"header" if found''' 82 self.log.write('Checking for header: '+header+'\n') 83 found = 0 84 if self.checkPreprocess('#include <'+header+'>\n'): 85 found = 1 86 if adddefine: self.addDefine(self.getDefineName(header), found) 87 return found 88 89 def checkInclude(self, incl, hfiles, otherIncludes = [], macro = None, timeout = 600.0): 90 '''Checks if a particular include file can be found along particular include paths''' 91 if not isinstance(hfiles, list): 92 hfiles = [hfiles] 93 if not isinstance(incl, list): 94 incl = [incl] 95 strmac = '' 96 if macro is not None: 97 strmac = 'defined macro {} in '.format(macro) 98 self.log.write('Checking for ' + strmac + 'header files ' +str(hfiles)+ ' in '+str(incl)+'\n') 99 found = False 100 for hfile in hfiles: 101 flagsArg = self.getPreprocessorFlagsArg() 102 self.logPrint('Checking include with compiler flags var '+flagsArg+' '+str(incl+otherIncludes)) 103 #oldFlags = self.compilers.CPPFLAGS 104 oldFlags = getattr(self.compilers, flagsArg) 105 #self.compilers.CPPFLAGS += ' '+' '.join([self.getIncludeArgument(inc) for inc in incl+otherIncludes]) 106 setattr(self.compilers, flagsArg, getattr(self.compilers, flagsArg)+' '+' '.join([self.getIncludeArgument(inc) for inc in incl+otherIncludes])) 107 body = '#include <' +hfile+ '>\n' 108 if macro is not None: 109 body += '#if !defined({})\n#error {} not defined\n#endif\n'.format(macro,macro) 110 found = self.checkPreprocess(body, timeout = timeout) 111 #self.compilers.CPPFLAGS = oldFlags 112 setattr(self.compilers, flagsArg, oldFlags) 113 if found and macro is not None: 114 self.addDefine(self.getDefineMacro(macro), 1) 115 if not found and macro is None: return 0 116 if macro is not None and not found: 117 return 0 118 self.log.write('Found ' + strmac + 'header files ' +str(hfiles)+ ' in '+str(incl)+'\n') 119 return 1 120 121 def checkStdC(self): 122 '''Determine if C standard headers support everything PETSc needs''' 123 haveStdC = 0 124 includes = ''' 125#include <stdlib.h> 126#include <stdarg.h> 127#include <string.h> 128#include <float.h> 129''' 130 haveStdC = self.checkCompile(includes) 131 # SunOS 4.x string.h does not declare mem*, contrary to ANSI. 132 if haveStdC and not self.outputPreprocess('#include <string.h>').find('memchr'): haveStdC = 0 133 # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. 134 if haveStdC and not self.outputPreprocess('#include <stdlib.h>').find('free'): haveStdC = 0 135 # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. 136 if haveStdC and not self.argDB['with-batch']: 137 includes = ''' 138#include <stdlib.h> 139#include <ctype.h> 140#define ISLOWER(c) (\'a\' <= (c) && (c) <= \'z\') 141#define TOUPPER(c) (ISLOWER(c) ? \'A\' + ((c) - \'a\') : (c)) 142#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) 143''' 144 body = ''' 145 int i; 146 147 for(i = 0; i < 256; i++) if (XOR(islower(i), ISLOWER(i)) || toupper(i) != TOUPPER(i)) exit(2); 148 exit(0); 149 ''' 150 if not self.checkRun(includes, body): haveStdC = 0 151 if not haveStdC: 152 raise RuntimeError("Cannot locate all the standard C header files needed by PETSc") 153 return 154 155 def checkSysWait(self): 156 '''Check for POSIX.1 compatible sys/wait.h, and defines HAVE_SYS_WAIT_H if found''' 157 includes = ''' 158#include <sys/types.h> 159#include <sys/wait.h> 160#ifndef WEXITSTATUS 161#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 162#endif 163#ifndef WIFEXITED 164#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) 165#endif 166''' 167 body = ''' 168 int s; 169 wait (&s); 170 s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; 171 ''' 172 if self.checkCompile(includes, body): 173 self.addDefine('HAVE_SYS_WAIT_H', 1) 174 return 1 175 return 0 176 177 def checkTime(self): 178 '''Checks if you can safely include both <sys/time.h> and <time.h>, and if so defines TIME_WITH_SYS_TIME''' 179 self.check('time.h') 180 self.check('sys/time.h') 181 return 182 183 def checkMath(self): 184 '''Checks for the math headers and defines''' 185 haveMath = self.check('math.h',adddefine=0) 186 if haveMath: 187 if self.checkCompile('#include <math.h>\n', 'double pi = M_PI;\n(void)pi'): 188 self.logPrint('Found math #defines, like M_PI') 189 elif self.checkCompile('#define _USE_MATH_DEFINES 1\n#include <math.h>\n', 'double pi = M_PI;\n(void)pi'): 190 self.framework.addDefine('_USE_MATH_DEFINES', 1) 191 self.logPrint('Activated Windows math #defines, like M_PI') 192 else: 193 self.logPrint('Missing math #defines, like M_PI') 194 else: 195 raise RuntimeError("PETSc requires math.h") 196 return 197 198 def checkRecursiveMacros(self): 199 '''Checks that the preprocessor allows recursive macros, and if not defines HAVE_BROKEN_RECURSIVE_MACRO''' 200 includes = 'void a(int i, int j) {}\n#define a(b) a(b,__LINE__)' 201 body = 'a(0);\n' 202 if not self.checkCompile(includes, body): 203 self.addDefine('HAVE_BROKEN_RECURSIVE_MACRO', 1) 204 return 0 205 return 1 206 207 def configure(self): 208 self.executeTest(self.checkStdC) 209 self.executeTest(self.checkSysWait) 210 self.executeTest(self.checkTime) 211 self.executeTest(self.checkMath) 212 for header in self.headers: 213 self.executeTest(self.check, header) 214 self.executeTest(self.checkRecursiveMacros) 215 return 216