import config.base class Configure(config.base.Configure): def __init__(self, framework, headers = []): config.base.Configure.__init__(self, framework) self.headerPrefix = '' self.substPrefix = '' self.headers = headers return def setupDependencies(self, framework): config.base.Configure.setupDependencies(self, framework) self.compilers = self.framework.require('config.compilers', self) self.setCompilers = self.framework.require('config.setCompilers', self) return def getIncludeArgumentList(self, include): '''Return the proper include line argument for the given filename as a list - If the path is empty, return it unchanged - If starts with - then return unchanged - Otherwise return -I''' if not include: return [] include = include.replace('\\ ',' ').replace(' ', '\\ ') include = include.replace('\\(','(').replace('(', '\\(') include = include.replace('\\)',')').replace(')', '\\)') if include[0] == '-': return [include] return ['-I'+include] def getIncludeModulesArgumentList(self, include): '''Return the proper include line argument for the given filename as a list - If the path is empty, return it unchanged - If starts with - then return unchanged - Otherwise return -fortranmoduleflag includedirectory''' if not include: return [] include = include.replace('\\ ',' ').replace(' ', '\\ ') include = include.replace('\\(','(').replace('(', '\\(') include = include.replace('\\)',')').replace(')', '\\)') if include[0] == '-': return [include] self.pushLanguage('FC') string = self.setCompilers.fortranModuleIncludeFlag+include self.popLanguage() return [string] def getIncludeArgument(self, include): '''Same as getIncludeArgumentList - except it returns a string instead of list.''' return ' '.join(self.getIncludeArgumentList(include)) def toString(self,includes): '''Converts a list of includes to a string suitable for a compiler''' return ' '.join([self.getIncludeArgument(include) for include in includes]) def toStringNoDupes(self,includes,modincludes=[]): '''Converts a list of -Iincludes and -fmodule flags to a string suitable for a compiler, removes duplicates''' newincludes = [] for include in includes: newincludes += self.getIncludeArgumentList(include) for modinclude in modincludes: newincludes += self.getIncludeModulesArgumentList(modinclude) includes = newincludes newincludes = [] for j in includes: if j in newincludes: continue newincludes.append(j) return ' '.join(newincludes) def getDefineMacro(self, macro): return 'HAVE_MACRO_'+macro def getDefineName(self, header): return 'HAVE_'+header.upper().replace('.', '_').replace('/', '_') def haveHeader(self, header): return self.getDefineName(header) in self.defines def check(self,header, adddefine = 1): '''Checks for "header", and defines HAVE_"header" if found''' self.log.write('Checking for header: '+header+'\n') found = 0 if self.checkPreprocess('#include <'+header+'>\n'): found = 1 if adddefine: self.addDefine(self.getDefineName(header), found) return found def checkInclude(self, incl, hfiles, otherIncludes = [], macro = None, timeout = 600.0): '''Checks if a particular include file can be found along particular include paths''' if not isinstance(hfiles, list): hfiles = [hfiles] if not isinstance(incl, list): incl = [incl] strmac = '' if macro is not None: strmac = 'defined macro {} in '.format(macro) self.log.write('Checking for ' + strmac + 'header files ' +str(hfiles)+ ' in '+str(incl)+'\n') found = False for hfile in hfiles: flagsArg = self.getPreprocessorFlagsArg() self.logPrint('Checking include with compiler flags var '+flagsArg+' '+str(incl+otherIncludes)) #oldFlags = self.compilers.CPPFLAGS oldFlags = getattr(self.compilers, flagsArg) #self.compilers.CPPFLAGS += ' '+' '.join([self.getIncludeArgument(inc) for inc in incl+otherIncludes]) setattr(self.compilers, flagsArg, getattr(self.compilers, flagsArg)+' '+' '.join([self.getIncludeArgument(inc) for inc in incl+otherIncludes])) body = '#include <' +hfile+ '>\n' if macro is not None: body += '#if !defined({})\n#error {} not defined\n#endif\n'.format(macro,macro) found = self.checkPreprocess(body, timeout = timeout) #self.compilers.CPPFLAGS = oldFlags setattr(self.compilers, flagsArg, oldFlags) if found and macro is not None: self.addDefine(self.getDefineMacro(macro), 1) if not found and macro is None: return 0 if macro is not None and not found: return 0 self.log.write('Found ' + strmac + 'header files ' +str(hfiles)+ ' in '+str(incl)+'\n') return 1 def checkStdC(self): '''Determine if C standard headers support everything PETSc needs''' haveStdC = 0 includes = ''' #include #include #include #include ''' haveStdC = self.checkCompile(includes) # SunOS 4.x string.h does not declare mem*, contrary to ANSI. if haveStdC and not self.outputPreprocess('#include ').find('memchr'): haveStdC = 0 # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. if haveStdC and not self.outputPreprocess('#include ').find('free'): haveStdC = 0 # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. if haveStdC and not self.argDB['with-batch']: includes = ''' #include #include #define ISLOWER(c) (\'a\' <= (c) && (c) <= \'z\') #define TOUPPER(c) (ISLOWER(c) ? \'A\' + ((c) - \'a\') : (c)) #define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) ''' body = ''' int i; for(i = 0; i < 256; i++) if (XOR(islower(i), ISLOWER(i)) || toupper(i) != TOUPPER(i)) exit(2); exit(0); ''' if not self.checkRun(includes, body): haveStdC = 0 if not haveStdC: raise RuntimeError("Cannot locate all the standard C header files needed by PETSc") return def checkSysWait(self): '''Check for POSIX.1 compatible sys/wait.h, and defines HAVE_SYS_WAIT_H if found''' includes = ''' #include #include #ifndef WEXITSTATUS #define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) #endif #ifndef WIFEXITED #define WIFEXITED(stat_val) (((stat_val) & 255) == 0) #endif ''' body = ''' int s; wait (&s); s = WIFEXITED (s) ? WEXITSTATUS (s) : 1; ''' if self.checkCompile(includes, body): self.addDefine('HAVE_SYS_WAIT_H', 1) return 1 return 0 def checkTime(self): '''Checks if you can safely include both and , and if so defines TIME_WITH_SYS_TIME''' self.check('time.h') self.check('sys/time.h') return def checkMath(self): '''Checks for the math headers and defines''' haveMath = self.check('math.h',adddefine=0) if haveMath: if self.checkCompile('#include \n', 'double pi = M_PI;\n(void)pi'): self.logPrint('Found math #defines, like M_PI') elif self.checkCompile('#define _USE_MATH_DEFINES 1\n#include \n', 'double pi = M_PI;\n(void)pi'): self.framework.addDefine('_USE_MATH_DEFINES', 1) self.logPrint('Activated Windows math #defines, like M_PI') else: self.logPrint('Missing math #defines, like M_PI') else: raise RuntimeError("PETSc requires math.h") return def checkRecursiveMacros(self): '''Checks that the preprocessor allows recursive macros, and if not defines HAVE_BROKEN_RECURSIVE_MACRO''' includes = 'void a(int i, int j) {}\n#define a(b) a(b,__LINE__)' body = 'a(0);\n' if not self.checkCompile(includes, body): self.addDefine('HAVE_BROKEN_RECURSIVE_MACRO', 1) return 0 return 1 def configure(self): self.executeTest(self.checkStdC) self.executeTest(self.checkSysWait) self.executeTest(self.checkTime) self.executeTest(self.checkMath) for header in self.headers: self.executeTest(self.check, header) self.executeTest(self.checkRecursiveMacros) return