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