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.ArgBool(None, 1, '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.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.log.write(typeName+' found\n') 44 return found 45 46 def check_struct_sigaction(self): 47 '''Checks if "struct sigaction" exists in signal.h. This check is for C89 check.''' 48 if self.check('struct sigaction', includes = ['signal.h']): 49 self.addDefine('HAVE_STRUCT_SIGACTION',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 Note that since PETSc source code uses _Complex we test specifically for that, not complex''' 109 includes = '#include <complex.h>\n' 110 body = 'double _Complex x;\n x = I;\n' 111 if not self.checkCompile(includes, body): return # checkLink can succeed even if checkCompile fails 112 if self.checkLink(includes, body): 113 self.addDefine('HAVE_C99_COMPLEX', 1) 114 self.c99_complex = 1 115 return 116 117 def checkCxxComplex(self): 118 '''Check for complex numbers in namespace std''' 119 self.pushLanguage('C++') 120 includes = '#include <complex>\n' 121 body = 'std::complex<double> x;\n' 122 if self.checkLink(includes, body): 123 self.addDefine('HAVE_CXX_COMPLEX', 1) 124 self.cxx_complex = 1 125 self.popLanguage() 126 return 127 128 def checkFortranStar(self): 129 '''Checks whether integer*4, etc. is handled in Fortran, and if not defines MISSING_FORTRANSTAR''' 130 self.pushLanguage('FC') 131 body = ' integer*4 i\n real*8 d\n' 132 if not self.checkCompile('', body): 133 self.addDefine('MISSING_FORTRANSTAR', 1) 134 self.popLanguage() 135 return 136 137# reverse of the above - but more standard thing to do for F90 compilers 138 def checkFortranKind(self): 139 '''Checks whether selected_int_kind etc work USE_FORTRANKIND''' 140 self.pushLanguage('FC') 141 body = ''' 142 integer(kind=selected_int_kind(10)) i 143 real(kind=selected_real_kind(10)) d 144''' 145 if self.checkCompile('', body): 146 self.addDefine('USE_FORTRANKIND', 1) 147 self.popLanguage() 148 return 149 150 def checkConst(self): 151 '''Checks for working const, and if not found defines it to empty string''' 152 body = ''' 153 /* Ultrix mips cc rejects this. */ 154 typedef int charset[2]; const charset x; 155 /* SunOS 4.1.1 cc rejects this. */ 156 char const *const *ccp; 157 char **p; 158 /* NEC SVR4.0.2 mips cc rejects this. */ 159 struct point {int x, y;}; 160 static struct point const zero = {0,0}; 161 /* AIX XL C 1.02.0.0 rejects this. 162 It does not let you subtract one const X* pointer from another in an arm 163 of an if-expression whose if-part is not a constant expression */ 164 const char *g = "string"; 165 ccp = &g + (g ? g-g : 0); 166 /* HPUX 7.0 cc rejects these. */ 167 ++ccp; 168 p = (char**) ccp; 169 ccp = (char const *const *) p; 170 /* This section avoids unused variable warnings */ 171 if (zero.x); 172 if (x[0]); 173 { /* SCO 3.2v4 cc rejects this. */ 174 char *t; 175 char const *s = 0 ? (char *) 0 : (char const *) 0; 176 177 *t++ = 0; 178 if (*s); 179 } 180 { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ 181 int x[] = {25, 17}; 182 const int *foo = &x[0]; 183 ++foo; 184 } 185 { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ 186 typedef const int *iptr; 187 iptr p = 0; 188 ++p; 189 } 190 { /* AIX XL C 1.02.0.0 rejects this saying 191 "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ 192 struct s { int j; const int *ap[3]; }; 193 struct s *b; b->j = 5; 194 } 195 { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ 196 const int foo = 10; 197 198 /* Get rid of unused variable warning */ 199 if (foo); 200 } 201 ''' 202 if not self.checkCompile('', body): 203 self.addDefine('const', '') 204 return 205 206 def checkSizeof(self, typeName, typeSizes, otherInclude = None, lang='C', save=True, codeBegin=''): 207 '''Determines the size of type "typeName", and defines SIZEOF_"typeName" to be the size''' 208 self.log.write('Checking for size of type: ' + typeName + '\n') 209 typename = typeName.replace(' ', '-').replace('*', 'p') 210 argname = 'known-sizeof-' + typename 211 if argname in self.argDB: 212 size = int(self.argDB[argname]) 213 else: 214 includes = ''' 215#include <sys/types.h> 216#if STDC_HEADERS 217#include <stdlib.h> 218#include <stdio.h> 219#include <stddef.h> 220#endif\n''' 221 mpiFix = ''' 222#define MPICH_IGNORE_CXX_SEEK 223#define MPICH_SKIP_MPICXX 1 224#define OMPI_SKIP_MPICXX 1\n''' 225 if otherInclude: 226 if otherInclude == 'mpi.h': 227 includes += mpiFix 228 includes += '#include <' + otherInclude + '>\n' 229 with self.Language(lang): 230 for size in typeSizes: 231 body = 'char assert_sizeof[(sizeof({})=={})*2-1];'.format(typeName, size) 232 if self.checkCompile(includes, body, codeBegin=codeBegin, codeEnd='\n'): 233 break 234 if size is None: 235 raise RuntimeError('Size of type {} not found in sizes {}; specify --known-sizeof-{}'.format(typeName, typeSizes, typename)) 236 if save: 237 self.sizes[argname] = size 238 self.addDefine('SIZEOF_'+typename.replace('-', '_').upper(), str(size)) 239 return size 240 241 def checkBitsPerByte(self): 242 '''Determine the nubmer of bits per byte and define BITS_PER_BYTE''' 243 filename = 'conftestval' 244 includes = ''' 245#if STDC_HEADERS 246#include <stdlib.h> 247#include <stdio.h> 248#endif\n''' 249 body = 'FILE *f = fopen("'+filename+'", "w");\n'+''' 250 char val[2]; 251 int i = 0; 252 253 if (!f) exit(1); 254 val[0]=\'\\1\'; 255 val[1]=\'\\0\'; 256 while(val[0]) {val[0] <<= 1; i++;} 257 fprintf(f, "%d\\n", i);\n 258 ''' 259 if 'known-bits-per-byte' in self.argDB: 260 bits = self.argDB['known-bits-per-byte'] 261 elif not self.argDB['with-batch']: 262 if self.checkRun(includes, body) and os.path.exists(filename): 263 f = open(filename) 264 bits = int(f.read()) 265 f.close() 266 os.remove(filename) 267 else: 268 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' 269 raise RuntimeError(msg) 270 else: 271 self.framework.addBatchBody(['{', 272 ' int i = 0;', 273 ' char val[2];', 274 ' val[0]=\'\\1\';', 275 ' val[1]=\'\\0\';', 276 ' while(val[0]) {val[0] <<= 1; i++;}', 277 ' fprintf(output, " \'--known-bits-per-byte=%d\',\\n", i);', 278 '}']) 279 # dummy value 280 bits = 8 281 282 self.bits_per_byte = int(bits) 283 self.addDefine('BITS_PER_BYTE', bits) 284 return 285 286 287 def checkVisibility(self): 288 if not self.argDB['with-shared-libraries']: 289 self.argDB['with-visibility'] = 0 290 self.log.write('Disabled visibility attributes due to static build') 291 elif self.argDB['with-visibility']: 292 self.pushLanguage('C') 293 if self.checkCompile('','__attribute__((visibility ("default"))) int foo(void);'): 294 self.addDefine('USE_VISIBILITY_C',1) 295 else: 296 self.log.write('Cannot use visibility attributes with C') 297 self.argDB['with-visibility'] = 0 298 self.popLanguage() 299 if hasattr(self.compilers, 'CXX'): 300 self.pushLanguage('C++') 301 if self.checkCompile('','__attribute__((visibility ("default"))) int foo(void);'): 302 self.addDefine('USE_VISIBILITY_CXX',1) 303 else: 304 self.log.write('Cannot use visibility attributes with C++') 305 self.popLanguage() 306 else: 307 self.log.write('User turned off visibility attributes') 308 309 310 def configure(self): 311 self.executeTest(self.check_struct_sigaction) 312 self.executeTest(self.check__int64) 313 self.executeTest(self.checkSizeTypes) 314 self.executeTest(self.checkFileTypes) 315 self.executeTest(self.checkIntegerTypes) 316 self.executeTest(self.checkPID) 317 self.executeTest(self.checkUID) 318 self.executeTest(self.checkSignal) 319 self.executeTest(self.checkC99Complex) 320 if hasattr(self.compilers, 'CXX'): 321 self.executeTest(self.checkCxxComplex) 322 if hasattr(self.compilers, 'FC'): 323 #self.executeTest(self.checkFortranStar) 324 self.executeTest(self.checkFortranKind) 325 self.executeTest(self.checkConst) 326 for t, sizes in {'void *': (8, 4), 327 'short': (2, 4, 8), 328 'int': (4, 8, 2), 329 'long': (8, 4), 330 'long long': (8,), 331 'size_t': (8, 4)}.items(): 332 self.executeTest(self.checkSizeof, args=[t, sizes]) 333 self.executeTest(self.checkBitsPerByte) 334 self.executeTest(self.checkVisibility) 335 return 336