1import config.base 2 3import os 4 5class Configure(config.base.Configure): 6 def __init__(self, framework): 7 config.base.Configure.__init__(self, framework) 8 self.headerPrefix = '' 9 self.substPrefix = '' 10 self.sizes = {} 11 self.c99_complex = 0 12 self.cxx_complex = 0 13 return 14 15 def setupHelp(self, help): 16 import nargs 17 help.addArgument('Visibility', '-with-visibility=<bool>', nargs.ArgBool(None, 1, 'Use compiler visibility flags to limit symbol visibility')) 18 return 19 20 def setupDependencies(self, framework): 21 config.base.Configure.setupDependencies(self, framework) 22 self.compilers = framework.require('config.compilers', self) 23 self.headers = framework.require('config.headers', self) 24 return 25 26 def check(self, typeName, defaultType = None, includes = []): 27 '''Checks that "typeName" exists, and if not defines it to "defaultType" if given''' 28 self.log.write('Checking for type: '+typeName+'\n') 29 include = ''' 30#include <sys/types.h> 31#include <stdlib.h> 32#include <stddef.h> 33%s 34 ''' % ('\n'.join(['#include<%s>' % inc for inc in includes])) 35 found = self.checkCompile(include,typeName+' a;') 36 if not found and defaultType: 37 self.addTypedef(defaultType, typeName) 38 else: 39 self.log.write(typeName+' found\n') 40 return found 41 42 def check_struct_sigaction(self): 43 '''Checks if "struct sigaction" exists in signal.h. This check is for C89 check.''' 44 if self.check('struct sigaction', includes = ['signal.h']): 45 self.addDefine('HAVE_STRUCT_SIGACTION',1) 46 return 47 48 def check__int64(self): 49 '''Checks if __int64 exists. This is primarily for windows.''' 50 if self.check('__int64'): 51 self.addDefine('HAVE___INT64',1) 52 return 53 54 def checkSizeTypes(self): 55 '''Checks for types associated with sizes, such as size_t.''' 56 self.check('size_t', 'int') 57 return 58 59 def checkIntegerTypes(self): 60 '''Checks for types associated with integers, such as int32_t.''' 61 self.check('int32_t', 'int') 62 return 63 64 def checkFileTypes(self): 65 '''Checks for types associated with files, such as mode_t, off_t, etc.''' 66 self.check('mode_t', 'int') 67 self.check('off_t', 'int') 68 return 69 70 def checkPID(self): 71 '''Checks for pid_t, and defines it if necessary''' 72 return self.check('pid_t', 'int') 73 74 def checkUID(self): 75 '''Checks for uid_t and gid_t, and defines them if necessary''' 76 if self.outputPreprocess('#include <sys/types.h>').find('uid_t') < 0: 77 self.addDefine('uid_t', 'int') 78 self.addDefine('gid_t', 'int') 79 return 80 81 def checkC99Complex(self): 82 '''Check for complex numbers in in C99 std 83 Note that since PETSc source code uses _Complex we test specifically for that, not complex''' 84 includes = '#include <complex.h>\n' 85 body = 'double _Complex x;\n x = I;\n' 86 if not self.checkCompile(includes, body): return # checkLink can succeed even if checkCompile fails 87 if self.checkLink(includes, body): 88 # recheck with _GNU_SOURCE active (Issues with crayCC on aarch64) 89 includes = '#define _GNU_SOURCE\n#include <complex.h>\n' 90 if not self.checkCompile(includes, body): return 91 self.addDefine('HAVE_C99_COMPLEX', 1) 92 self.c99_complex = 1 93 return 94 95 def checkCxxComplex(self): 96 '''Check for complex numbers in namespace std''' 97 self.pushLanguage('C++') 98 includes = '#include <complex>\n' 99 body = 'std::complex<double> x;\n' 100 if self.checkLink(includes, body): 101 self.addDefine('HAVE_CXX_COMPLEX', 1) 102 self.cxx_complex = 1 103 self.popLanguage() 104 return 105 106 def checkConst(self): 107 '''Checks for working const, and if not found defines it to empty string''' 108 body = ''' 109 /* Ultrix mips cc rejects this. */ 110 typedef int charset[2]; const charset x; 111 /* SunOS 4.1.1 cc rejects this. */ 112 char const *const *ccp; 113 char **p; 114 /* NEC SVR4.0.2 mips cc rejects this. */ 115 struct point {int x, y;}; 116 static struct point const zero = {0,0}; 117 /* AIX XL C 1.02.0.0 rejects this. 118 It does not let you subtract one const X* pointer from another in an arm 119 of an if-expression whose if-part is not a constant expression */ 120 const char *g = "string"; 121 ccp = &g + (g ? g-g : 0); 122 /* HPUX 7.0 cc rejects these. */ 123 ++ccp; 124 p = (char**) ccp; 125 ccp = (char const *const *) p; 126 /* This section avoids unused variable warnings */ 127 if (zero.x); 128 if (x[0]); 129 { /* SCO 3.2v4 cc rejects this. */ 130 char *t; 131 char const *s = 0 ? (char *) 0 : (char const *) 0; 132 133 *t++ = 0; 134 if (*s); 135 } 136 { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ 137 int x[] = {25, 17}; 138 const int *foo = &x[0]; 139 ++foo; 140 } 141 { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ 142 typedef const int *iptr; 143 iptr p = 0; 144 ++p; 145 } 146 { /* AIX XL C 1.02.0.0 rejects this saying 147 "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ 148 struct s { int j; const int *ap[3]; }; 149 struct s *b; b->j = 5; 150 } 151 { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ 152 const int foo = 10; 153 154 /* Get rid of unused variable warning */ 155 if (foo); 156 } 157 ''' 158 if not self.checkCompile('', body): 159 self.addDefine('const', '') 160 return 161 162 def checkSizeof(self, typeName, typeSizes, otherInclude = None, lang='C', save=True, codeBegin=''): 163 '''Determines the size of type "typeName", and defines SIZEOF_"typeName" to be the size''' 164 self.log.write('Checking for size of type: ' + typeName + '\n') 165 typename = typeName.replace(' ', '-').replace('*', 'p') 166 includes = ''' 167#include <sys/types.h> 168#include <stdlib.h> 169#include <stdio.h> 170#include <stddef.h>''' 171 mpiFix = ''' 172#define MPICH_IGNORE_CXX_SEEK 173#define MPICH_SKIP_MPICXX 1 174#define OMPI_SKIP_MPICXX 1\n''' 175 if otherInclude: 176 if otherInclude == 'mpi.h': 177 includes += mpiFix 178 includes += '#include <' + otherInclude + '>\n' 179 size = None 180 checkName = typeName 181 if typeName == 'enum': 182 checkName = 'enum{ENUM_DUMMY}' 183 with self.Language(lang): 184 for s in typeSizes: 185 body = 'char assert_sizeof[(sizeof({0})=={1})*2-1];'.format(checkName, s) 186 if self.checkCompile(includes, body, codeBegin=codeBegin, codeEnd='\n'): 187 size = s 188 break 189 if size is None: 190 raise RuntimeError('Unable to determine size of {0} not found'.format(typeName)) 191 if save: 192 self.sizes[typename] = size 193 self.addDefine('SIZEOF_'+typename.replace('-', '_').upper(), str(size)) 194 return size 195 196 def checkVisibility(self): 197 if not self.argDB['with-shared-libraries']: 198 self.argDB['with-visibility'] = 0 199 self.log.write('Disabled visibility attributes due to static build') 200 elif self.argDB['with-visibility']: 201 self.pushLanguage('C') 202 if self.checkCompile('','__attribute__((visibility ("default"))) int foo(void);'): 203 self.addDefine('USE_VISIBILITY_C',1) 204 else: 205 self.log.write('Cannot use visibility attributes with C') 206 self.argDB['with-visibility'] = 0 207 self.popLanguage() 208 if hasattr(self.compilers, 'CXX'): 209 self.pushLanguage('C++') 210 if self.checkCompile('','__attribute__((visibility ("default"))) int foo(void);'): 211 self.addDefine('USE_VISIBILITY_CXX',1) 212 else: 213 self.log.write('Cannot use visibility attributes with C++') 214 self.popLanguage() 215 else: 216 self.log.write('User turned off visibility attributes') 217 218 def checkMaxPathLen(self): 219 import re 220 HASHLINESPACE = ' *(?:\n#.*\n *)*' 221 self.log.write('Determining PETSC_MAX_PATH_LEN\n') 222 include = '' 223 if self.headers.haveHeader('sys/param.h'): 224 include = (include + '\n#include <sys/param.h>') 225 if self.headers.haveHeader('sys/types.h'): 226 include = (include + '\n#include <sys/types.h>') 227 length = include + ''' 228#if defined(MAXPATHLEN) 229# define PETSC_MAX_PATH_LEN MAXPATHLEN 230#elif defined(MAX_PATH) 231# define PETSC_MAX_PATH_LEN MAX_PATH 232#elif defined(_MAX_PATH) 233# define PETSC_MAX_PATH_LEN _MAX_PATH 234#else 235# define PETSC_MAX_PATH_LEN 4096 236#endif 237#define xstr(s) str(s) 238#define str(s) #s 239char petsc_max_path_len[] = xstr(PETSC_MAX_PATH_LEN); 240''' 241 MaxPathLength = 'unknown' 242 if self.checkCompile(length): 243 buf = self.outputPreprocess(length) 244 try: 245 MaxPathLength = re.compile('\nchar petsc_max_path_len\s?\[\s?\] = '+HASHLINESPACE+'\"([0-9]+)\"'+HASHLINESPACE+';').search(buf).group(1) 246 except: 247 raise RuntimeError('Unable to determine PETSC_MAX_PATH_LEN') 248 if MaxPathLength == 'unknown' or not MaxPathLength.isdigit(): 249 raise RuntimeError('Unable to determine PETSC_MAX_PATH_LEN') 250 else: 251 self.addDefine('MAX_PATH_LEN',MaxPathLength) 252 253 254 def configure(self): 255 self.executeTest(self.check_struct_sigaction) 256 self.executeTest(self.check__int64) 257 self.executeTest(self.checkSizeTypes) 258 self.executeTest(self.checkFileTypes) 259 self.executeTest(self.checkIntegerTypes) 260 self.executeTest(self.checkPID) 261 self.executeTest(self.checkUID) 262 self.executeTest(self.checkC99Complex) 263 if hasattr(self.compilers, 'CXX'): 264 self.executeTest(self.checkCxxComplex) 265 self.executeTest(self.checkConst) 266 for t, sizes in {'void *': (8, 4), 267 'short': (2, 4, 8), 268 'int': (4, 8, 2), 269 'long': (8, 4), 270 'long long': (8,), 271 'enum': (4, 8), 272 'size_t': (8, 4)}.items(): 273 self.executeTest(self.checkSizeof, args=[t, sizes]) 274 if self.sizes['void-p'] == 8: 275 self.addDefine('USING_64BIT_PTR',1) 276 self.executeTest(self.checkVisibility) 277 self.executeTest(self.checkMaxPathLen) 278 return 279