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 = '' 10 self.substPrefix = '' 11 self.sizes = {} 12 self.c99_complex = 0 13 self.cxx_complex = 0 14 return 15 16 def setupHelp(self, help): 17 import nargs 18 help.addArgument('Types', '-known-endian=<big or little>', nargs.Arg(None, None, 'Are bytes stored in big or little endian?')) 19 help.addArgument('Visibility', '-with-visibility=<bool>', nargs.Arg(None, 0, 'Use compiler visibility flags to limit symbol visibility')) 20 return 21 22 def setupDependencies(self, framework): 23 config.base.Configure.setupDependencies(self, framework) 24 self.compilers = framework.require('config.compilers', self) 25 self.headers = framework.require('config.headers', self) 26 return 27 28 def check(self, typeName, defaultType = None, includes = []): 29 '''Checks that "typeName" exists, and if not defines it to "defaultType" if given''' 30 self.framework.log.write('Checking for type: '+typeName+'\n') 31 include = ''' 32#include <sys/types.h> 33#if STDC_HEADERS 34#include <stdlib.h> 35#include <stddef.h> 36%s 37#endif 38 ''' % ('\n'.join(['#include<%s>' % inc for inc in includes])) 39 found = self.checkCompile(include,typeName+' a;') 40 if not found and defaultType: 41 self.addTypedef(defaultType, typeName) 42 else: 43 self.framework.log.write(typeName+' found\n') 44 return found 45 46 def check_siginfo_t(self): 47 '''Checks if siginfo_t exists in signal.h. This check is for windows, and C89 check.''' 48 if self.check('siginfo_t', includes = ['signal.h']): 49 self.addDefine('HAVE_SIGINFO_T',1) 50 return 51 52 def check__int64(self): 53 '''Checks if __int64 exists. This is primarily for windows.''' 54 if self.check('__int64'): 55 self.addDefine('HAVE___INT64',1) 56 return 57 58 def checkSizeTypes(self): 59 '''Checks for types associated with sizes, such as size_t.''' 60 self.check('size_t', 'int') 61 return 62 63 def checkIntegerTypes(self): 64 '''Checks for types associated with integers, such as int32_t.''' 65 self.check('int32_t', 'int') 66 return 67 68 def checkFileTypes(self): 69 '''Checks for types associated with files, such as mode_t, off_t, etc.''' 70 self.check('mode_t', 'int') 71 self.check('off_t', 'int') 72 return 73 74 def checkPID(self): 75 '''Checks for pid_t, and defines it if necessary''' 76 return self.check('pid_t', 'int') 77 78 def checkUID(self): 79 '''Checks for uid_t and gid_t, and defines them if necessary''' 80 if self.outputPreprocess('#include <sys/types.h>').find('uid_t') < 0: 81 self.addDefine('uid_t', 'int') 82 self.addDefine('gid_t', 'int') 83 return 84 85 def checkSignal(self): 86 '''Checks the return type of signal() and defines RETSIGTYPE to that type name''' 87 includes = ''' 88#include <sys/types.h> 89#include <signal.h> 90#ifdef signal 91#undef signal 92#endif 93#ifdef __cplusplus 94extern "C" void (*signal (int, void(*)(int)))(int); 95#else 96void (*signal())(); 97#endif 98 ''' 99 if self.checkCompile(includes, ''): 100 returnType = 'void' 101 else: 102 returnType = 'int' 103 self.addDefine('RETSIGTYPE', returnType) 104 return 105 106 def checkC99Complex(self): 107 '''Check for complex numbers in in C99 std''' 108 includes = '#include <complex.h>\n' 109 body = 'double complex x;\n x = I;\n' 110 if self.checkLink(includes, body): 111 self.addDefine('HAVE_C99_COMPLEX', 1) 112 self.c99_complex = 1 113 return 114 115 def checkCxxComplex(self): 116 '''Check for complex numbers in namespace std''' 117 self.pushLanguage('C++') 118 includes = '#include <complex>\n' 119 body = 'std::complex<double> x;\n' 120 if self.checkLink(includes, body): 121 self.addDefine('HAVE_CXX_COMPLEX', 1) 122 self.cxx_complex = 1 123 self.popLanguage() 124 return 125 126 def checkFortranStar(self): 127 '''Checks whether integer*4, etc. is handled in Fortran, and if not defines MISSING_FORTRANSTAR''' 128 self.pushLanguage('FC') 129 body = ' integer*4 i\n real*8 d\n' 130 if not self.checkCompile('', body): 131 self.addDefine('MISSING_FORTRANSTAR', 1) 132 self.popLanguage() 133 return 134 135# reverse of the above - but more standard thing to do for F90 compilers 136 def checkFortranKind(self): 137 '''Checks whether selected_int_kind etc work USE_FORTRANKIND''' 138 self.pushLanguage('FC') 139 body = ''' 140 integer(kind=selected_int_kind(10)) i 141 real(kind=selected_real_kind(10)) d 142''' 143 if self.checkCompile('', body): 144 self.addDefine('USE_FORTRANKIND', 1) 145 self.popLanguage() 146 return 147 148 def checkFortranDReal(self): 149 '''Checks whether dreal is provided in Fortran, and if not defines MISSING_DREAL''' 150 self.pushLanguage('FC') 151 if not self.checkLink('', ' double precision d\n d = dreal(3.0)'): 152 self.addDefine('MISSING_DREAL', 1) 153 self.popLanguage() 154 return 155 156 def checkConst(self): 157 '''Checks for working const, and if not found defines it to empty string''' 158 body = ''' 159 /* Ultrix mips cc rejects this. */ 160 typedef int charset[2]; const charset x; 161 /* SunOS 4.1.1 cc rejects this. */ 162 char const *const *ccp; 163 char **p; 164 /* NEC SVR4.0.2 mips cc rejects this. */ 165 struct point {int x, y;}; 166 static struct point const zero = {0,0}; 167 /* AIX XL C 1.02.0.0 rejects this. 168 It does not let you subtract one const X* pointer from another in an arm 169 of an if-expression whose if-part is not a constant expression */ 170 const char *g = "string"; 171 ccp = &g + (g ? g-g : 0); 172 /* HPUX 7.0 cc rejects these. */ 173 ++ccp; 174 p = (char**) ccp; 175 ccp = (char const *const *) p; 176 /* This section avoids unused variable warnings */ 177 if (zero.x); 178 if (x[0]); 179 { /* SCO 3.2v4 cc rejects this. */ 180 char *t; 181 char const *s = 0 ? (char *) 0 : (char const *) 0; 182 183 *t++ = 0; 184 if (*s); 185 } 186 { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ 187 int x[] = {25, 17}; 188 const int *foo = &x[0]; 189 ++foo; 190 } 191 { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ 192 typedef const int *iptr; 193 iptr p = 0; 194 ++p; 195 } 196 { /* AIX XL C 1.02.0.0 rejects this saying 197 "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ 198 struct s { int j; const int *ap[3]; }; 199 struct s *b; b->j = 5; 200 } 201 { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ 202 const int foo = 10; 203 204 /* Get rid of unused variable warning */ 205 if (foo); 206 } 207 ''' 208 if not self.checkCompile('', body): 209 self.addDefine('const', '') 210 return 211 212 def checkEndian(self): 213 '''If the machine is big endian, defines WORDS_BIGENDIAN''' 214 if 'known-endian' in self.framework.argDB: 215 endian = self.framework.argDB['known-endian'] 216 else: 217 # See if sys/param.h defines the BYTE_ORDER macro 218 includes = '#include <sys/types.h>\n#ifdef HAVE_SYS_PARAM_H\n #include <sys/param.h>\n#endif\n' 219 body = ''' 220#if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN 221 bogus endian macros 222#endif 223 ''' 224 if self.checkCompile(includes, body): 225 # It does, so check whether it is defined to BIG_ENDIAN or not 226 body = ''' 227#if BYTE_ORDER != BIG_ENDIAN 228 not big endian 229#endif 230 ''' 231 if self.checkCompile(includes, body): 232 endian = 'big' 233 else: 234 endian = 'little' 235 else: 236 if not self.framework.argDB['with-batch']: 237 body = ''' 238 /* Are we little or big endian? From Harbison&Steele. */ 239 union 240 { 241 long l; 242 char c[sizeof(long)]; 243 } u; 244 u.l = 1; 245 exit(u.c[sizeof(long) - 1] == 1); 246 ''' 247 self.pushLanguage('C') 248 if self.checkRun('#include <stdlib.h>\n', body, defaultArg = 'isLittleEndian'): 249 endian = 'little' 250 else: 251 endian = 'big' 252 self.popLanguage() 253 else: 254 self.framework.addBatchBody(['{', 255 ' union {long l; char c[sizeof(long)];} u;', 256 ' u.l = 1;', 257 ' fprintf(output, " \'--known-endian=%s\',\\n", (u.c[sizeof(long) - 1] == 1) ? "big" : "little");', 258 '}']) 259 # Dummy value 260 endian = 'little' 261 if endian == 'big': 262 self.addDefine('WORDS_BIGENDIAN', 1) 263 return 264 265 def checkSizeof(self, typeName, otherInclude = None): 266 '''Determines the size of type "typeName", and defines SIZEOF_"typeName" to be the size''' 267 self.framework.log.write('Checking for size of type: '+typeName+'\n') 268 filename = 'conftestval' 269 includes = ''' 270#include <sys/types.h> 271#if STDC_HEADERS 272#include <stdlib.h> 273#include <stdio.h> 274#include <stddef.h> 275#endif\n''' 276 mpiFix = ''' 277#define MPICH_IGNORE_CXX_SEEK 278#define MPICH_SKIP_MPICXX 1 279#define OMPI_SKIP_MPICXX 1\n''' 280 if otherInclude: 281 if otherInclude == 'mpi.h': 282 includes += mpiFix 283 includes += '#include <'+otherInclude+'>\n' 284 body = 'FILE *f = fopen("'+filename+'", "w");\n\nif (!f) exit(1);\nfprintf(f, "%lu\\n", (unsigned long)sizeof('+typeName+'));\n' 285 typename = typeName.replace(' ', '-').replace('*', 'p') 286 if not 'known-sizeof-'+typename in self.framework.argDB: 287 if not self.framework.argDB['with-batch']: 288 self.pushLanguage('C') 289 if self.checkRun(includes, body) and os.path.exists(filename): 290 f = file(filename) 291 size = int(f.read()) 292 f.close() 293 os.remove(filename) 294 elif not typename == 'long-long': 295 msg = 'Cannot run executable to determine size of '+typeName+'. If this machine uses a batch system \nto submit jobs you will need to configure using ./configure with the additional option --with-batch.\n Otherwise there is problem with the compilers. Can you compile and run code with your C/C++ (and maybe Fortran) compilers?\n' 296 raise RuntimeError(msg) 297 else: 298 self.framework.log.write('Compiler does not support long long\n') 299 size = 0 300 self.popLanguage() 301 else: 302 self.framework.addBatchInclude(['#include <stdlib.h>', '#include <stdio.h>', '#include <sys/types.h>']) 303 if otherInclude: 304 if otherInclude == 'mpi.h': 305 self.framework.addBatchInclude(mpiFix) 306 self.framework.addBatchInclude('#include <'+otherInclude+'>') 307 self.framework.addBatchBody('fprintf(output, " \'--known-sizeof-'+typename+'=%d\',\\n", sizeof('+typeName+'));') 308 # dummy value 309 size = 4 310 else: 311 size = self.framework.argDB['known-sizeof-'+typename] 312 self.sizes['known-sizeof-'+typename] = int(size) 313 self.addDefine('SIZEOF_'+typeName.replace(' ', '_').replace('*', 'p').upper(), size) 314 return size 315 316 def checkBitsPerByte(self): 317 '''Determine the nubmer of bits per byte and define BITS_PER_BYTE''' 318 filename = 'conftestval' 319 includes = ''' 320#if STDC_HEADERS 321#include <stdlib.h> 322#include <stdio.h> 323#endif\n''' 324 body = 'FILE *f = fopen("'+filename+'", "w");\n'+''' 325 char val[2]; 326 int i = 0; 327 328 if (!f) exit(1); 329 val[0]=\'\\1\'; 330 val[1]=\'\\0\'; 331 while(val[0]) {val[0] <<= 1; i++;} 332 fprintf(f, "%d\\n", i);\n 333 ''' 334 if 'known-bits-per-byte' in self.framework.argDB: 335 bits = self.framework.argDB['known-bits-per-byte'] 336 elif not self.framework.argDB['with-batch']: 337 if self.checkRun(includes, body) and os.path.exists(filename): 338 f = file(filename) 339 bits = int(f.read()) 340 f.close() 341 os.remove(filename) 342 else: 343 msg = 'Cannot run executable to determine bits per bit. If this machine uses a batch system \nto submit jobs you will need to configure using ./configure with the additional option --with-batch.\n Otherwise there is problem with the compilers. Can you compile and run code with your C/C++ (and maybe Fortran) compilers?\n' 344 raise RuntimeError(msg) 345 else: 346 self.framework.addBatchBody(['{', 347 ' int i = 0;', 348 ' char val[2];', 349 ' val[0]=\'\\1\';', 350 ' val[1]=\'\\0\';', 351 ' while(val[0]) {val[0] <<= 1; i++;}', 352 ' fprintf(output, " \'--known-bits-per-byte=%d\',\\n", i);', 353 '}']) 354 # dummy value 355 bits = 8 356 357 self.bits_per_byte = int(bits) 358 self.addDefine('BITS_PER_BYTE', bits) 359 return 360 361 362 def checkVisibility(self): 363 if self.framework.argDB['with-visibility']: 364 if not self.checkCompile('','__attribute__((visibility ("default"))) int foo(void);'): 365 raise RuntimeError('Cannot use visibility attributes') 366 self.addDefine('USE_VISIBILITY',1) 367 368 def configure(self): 369 self.executeTest(self.check_siginfo_t) 370 self.executeTest(self.check__int64) 371 self.executeTest(self.checkSizeTypes) 372 self.executeTest(self.checkFileTypes) 373 self.executeTest(self.checkIntegerTypes) 374 self.executeTest(self.checkPID) 375 self.executeTest(self.checkUID) 376 self.executeTest(self.checkSignal) 377 self.executeTest(self.checkC99Complex) 378 if hasattr(self.compilers, 'CXX'): 379 self.executeTest(self.checkCxxComplex) 380 if hasattr(self.compilers, 'FC'): 381 #self.executeTest(self.checkFortranStar) 382 self.executeTest(self.checkFortranKind) 383 self.executeTest(self.checkFortranDReal) 384 self.executeTest(self.checkConst) 385 self.executeTest(self.checkEndian) 386 map(lambda type: self.executeTest(self.checkSizeof, type), ['char','void *', 'short', 'int', 'long', 'long long', 'float', 'double', 'size_t']) 387 self.executeTest(self.checkBitsPerByte) 388 self.executeTest(self.checkVisibility) 389 return 390