1import config.base 2import os.path 3 4class Configure(config.base.Configure): 5 def __init__(self, framework, functions = []): 6 config.base.Configure.__init__(self, framework) 7 self.headerPrefix = '' 8 self.substPrefix = '' 9 self.functions = functions 10 return 11 12 def getDefineName(self, funcName): 13 return 'HAVE_'+funcName.upper() 14 15 def setupDependencies(self, framework): 16 config.base.Configure.setupDependencies(self, framework) 17 self.compilers = self.framework.require('config.compilers', self) 18 self.libraries = self.framework.require('config.libraries', self) # setCompilers.LIBS is setup here 19 self.headers = self.framework.require('config.headers', self) 20 return 21 22 def haveFunction(self, function): 23 return self.getDefineName(function) in self.defines 24 25 def check(self, funcs, libraries = None, examineOutput=lambda ret,out,err:None): 26 '''Checks for the function "funcName", and if found defines HAVE_"funcName"''' 27 if isinstance(funcs, set): funcs = list(funcs) 28 if isinstance(funcs, str): funcs = [funcs] 29 self.log.write('Checking for functions ['+' '.join(funcs)+']\n') 30 def genIncludes(funcName): 31 return 'char %s(void);\n' % funcName 32 def genBody(funcName): 33 # The GNU C library defines __stub_* for functions that it implements 34 # to always fail with ENOSYS. Some functions are actually named 35 # something starting with __ and the normal name is an alias. 36 return ''' 37#if defined (__stub_%(func)s) || defined (__stub___%(func)s) 38%(func)s_will_always_fail_with_ENOSYS(); 39#else 40%(func)s(); 41#endif 42''' % dict(func=funcName) 43 44 # Don't include <ctype.h> because on OSF/1 3.0 it includes <sys/types.h> 45 # which includes <sys/select.h> which contains a prototype for 46 # select. Similarly for bzero. 47 includes = ''' 48/* System header to define __stub macros and hopefully no other prototypes since they would conflict with our 'char funcname()' declaration below. */ 49#include <assert.h> 50/* Override any gcc2 internal prototype to avoid an error. */ 51#ifdef __cplusplus 52extern "C" { 53#endif 54''' 55 includes += ''' 56/* We use char because int might match the return type of a gcc2 57builtin and then its argument prototype would still apply. */ 58''' 59 includes += ''.join(map(genIncludes,funcs)) 60 includes += ''' 61#ifdef __cplusplus 62} 63#endif 64''' 65 body = ''.join(map(genBody,funcs)) 66 if libraries: 67 # TODO: Same code as libraries.toStringNoDupes() should call that and not repeat code here 68 oldLibs = self.compilers.LIBS 69 if not isinstance(libraries, list): 70 libraries = [libraries] 71 for library in libraries: 72 root,ext=os.path.splitext(library) 73 if library.strip()[0] == '-' or ext == '.a' or ext == '.so' or ext == '.o': 74 self.compilers.LIBS += ' '+library 75 else: 76 self.compilers.LIBS += ' -l'+library 77 found = self.checkLink(includes, body, examineOutput=examineOutput) 78 if libraries: 79 self.compilers.LIBS = oldLibs 80 if found: 81 for funcName in funcs: 82 self.addDefine(self.getDefineName(funcName), 1) 83 return found 84 85 def checkClassify(self, funcs, libraries = None): 86 '''Recursive decompose to rapidly classify functions as found or missing 87 To confirm that a function is missing, we require a compile/link 88 failure with only that function in a compilation unit. In contrast, 89 we can confirm that many functions are present by compiling them all 90 together in a large compilation unit. We optimistically compile 91 everything together, then trim all functions that were named in the 92 error message and bisect the result. The trimming is only an 93 optimization to increase the likelihood of a big-batch compile 94 succeeding; we do not rely on the compiler naming missing functions. 95 ''' 96 def functional(funcs): 97 named = config.NamedInStderr(funcs) 98 if self.check(funcs, libraries, named.examineStderr): 99 return True 100 else: 101 return named.named 102 import config 103 found, missing = config.classify(funcs, functional) 104 return found, missing 105 106 def checkVSNPrintf(self): 107 '''Checks whether vsnprintf requires a char * last argument, and if it does defines HAVE_VSNPRINTF_CHAR''' 108 if self.checkLink('#include <stdio.h>\n#include <stdarg.h>\n', 'va_list Argp = { 0 };char str[6];\nvsnprintf(str,5, "%d", Argp )'): 109 self.addDefine('HAVE_VSNPRINTF', 1) 110 return 111 112 def checkSignalHandlerType(self): 113 '''Checks the type of C++ signals handlers, and defines SIGNAL_CAST to the correct value''' 114 self.pushLanguage('C++') 115 if not self.checkLink('#include <signal.h>\nstatic void myhandler(int sig) { (void)sig; }\n', 'signal(SIGFPE,myhandler)'): 116 self.addDefine('SIGNAL_CAST', '(void (*)(int))') 117 else: 118 self.addDefine('SIGNAL_CAST', ' ') 119 self.popLanguage() 120 return 121 122 def checkFreeReturnType(self): 123 '''Checks whether free returns void or int, and defines HAVE_FREE_RETURN_INT''' 124 if self.checkLink('#include <stdlib.h>\n', 'int ierr; void *p; ierr = free(p); return ierr'): 125 self.addDefine('HAVE_FREE_RETURN_INT', 1) 126 return 127 128 def checkVariableArgumentLists(self): 129 '''Checks whether the variable argument list functionality is working''' 130 if self.checkLink('#include <stdarg.h>\n', ' va_list l1, l2;\n va_copy(l1, l2)'): 131 self.addDefine('HAVE_VA_COPY', 1) 132 elif self.checkLink('#include <stdarg.h>\n', ' va_list l1, l2;\n __va_copy(l1, l2)'): 133 self.addDefine('HAVE___VA_COPY', 1) 134 return 135 136 def checkNanosleep(self): 137 '''Check for functional nanosleep() - as time.h behaves differently for different compiler flags - like -std=c89''' 138 if self.checkLink('#include <time.h>','struct timespec tp;\n tp.tv_sec = 0;\n tp.tv_nsec = (long)(1e9);\n nanosleep(&tp,0)'): 139 self.addDefine('HAVE_NANOSLEEP', 1) 140 return 141 142 def checkMemmove(self): 143 '''Check for functional memmove() - as MS VC requires correct includes to for this test''' 144 if self.checkLink('#include <string.h>',' char c1[1], c2[1] = "c";\n size_t n=1;\n memmove(c1,c2,n)'): 145 self.addDefine('HAVE_MEMMOVE', 1) 146 return 147 148 def checkMmap(self): 149 '''Check for functional mmap() to allocate shared memory and define HAVE_MMAP''' 150 if self.checkLink('#include <sys/mman.h>\n#include <sys/types.h>\n#include <sys/stat.h>\n#include <fcntl.h>\n','int fd;\n fd=open("/tmp/file",O_RDWR);\n mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0)'): 151 self.addDefine('HAVE_MMAP', 1) 152 return 153 154 def checkMkstemp(self): 155 '''Check for mkstemp() to avoid using tmpnam as it is often deprecated''' 156 if self.checkLink('#define _XOPEN_SOURCE 600\n#include <stdlib.h>\n#include <string.h>', 'char filename[100];\n strcpy(filename, "/tmp/fileXXXXXX");\n mkstemp(filename)'): 157 self.addDefine('HAVE_MKSTEMP', 1) 158 159 def checkTmpnam_s(self): 160 '''Check for tmpnam_s() to avoid using tmpnam as it is often deprecated''' 161 if self.checkLink('#include <stdio.h>', 'char filename[L_tmpnam];\n tmpnam_s(filename, sizeof(filename))'): 162 self.addDefine('HAVE_TMPNAM_S', 1) 163 164 def configure(self): 165 self.executeTest(self.checkVSNPrintf) 166 self.executeTest(self.checkNanosleep) 167 self.executeTest(self.checkMemmove) 168 if hasattr(self.compilers, 'CXX'): 169 self.executeTest(self.checkSignalHandlerType) 170 self.executeTest(self.checkFreeReturnType) 171 self.executeTest(self.checkVariableArgumentLists) 172 self.executeTest(self.checkClassify, set(self.functions)) 173 if 'HAVE_GETPAGESIZE' in self.defines and self.compilers.setCompilers.isMINGW(self.framework.getCompiler(), self.log): 174 self.delDefine('HAVE_GETPAGESIZE') 175 self.executeTest(self.checkMmap) 176 self.executeTest(self.checkMkstemp) 177 self.executeTest(self.checkTmpnam_s) 178 return 179