xref: /petsc/config/BuildSystem/config/types.py (revision f560b561fafa46db89e20ff01ea2940b99fcf228)
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      self.addDefine('HAVE_C99_COMPLEX', 1)
89      self.c99_complex = 1
90    return
91
92  def checkCxxComplex(self):
93    '''Check for complex numbers in namespace std'''
94    self.pushLanguage('C++')
95    includes = '#include <complex>\n'
96    body     = 'std::complex<double> x;\n'
97    if self.checkLink(includes, body):
98      self.addDefine('HAVE_CXX_COMPLEX', 1)
99      self.cxx_complex = 1
100    self.popLanguage()
101    return
102
103  def checkConst(self):
104    '''Checks for working const, and if not found defines it to empty string'''
105    body = '''
106    /* Ultrix mips cc rejects this.  */
107    typedef int charset[2]; const charset x;
108    /* SunOS 4.1.1 cc rejects this.  */
109    char const *const *ccp;
110    char **p;
111    /* NEC SVR4.0.2 mips cc rejects this.  */
112    struct point {int x, y;};
113    static struct point const zero = {0,0};
114    /* AIX XL C 1.02.0.0 rejects this.
115    It does not let you subtract one const X* pointer from another in an arm
116    of an if-expression whose if-part is not a constant expression */
117    const char *g = "string";
118    ccp = &g + (g ? g-g : 0);
119    /* HPUX 7.0 cc rejects these. */
120    ++ccp;
121    p = (char**) ccp;
122    ccp = (char const *const *) p;
123    /* This section avoids unused variable warnings */
124    if (zero.x);
125    if (x[0]);
126    { /* SCO 3.2v4 cc rejects this.  */
127      char *t;
128      char const *s = 0 ? (char *) 0 : (char const *) 0;
129
130      *t++ = 0;
131      if (*s);
132    }
133    { /* Someone thinks the Sun supposedly-ANSI compiler will reject this.  */
134      int x[] = {25, 17};
135      const int *foo = &x[0];
136      ++foo;
137    }
138    { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */
139      typedef const int *iptr;
140      iptr p = 0;
141      ++p;
142    }
143    { /* AIX XL C 1.02.0.0 rejects this saying
144      "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */
145      struct s { int j; const int *ap[3]; };
146      struct s *b; b->j = 5;
147    }
148    { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */
149      const int foo = 10;
150
151      /* Get rid of unused variable warning */
152      if (foo);
153    }
154    '''
155    if not self.checkCompile('', body):
156      self.addDefine('const', '')
157    return
158
159  def checkSizeof(self, typeName, typeSizes, otherInclude = None, lang='C', save=True, codeBegin=''):
160    '''Determines the size of type "typeName", and defines SIZEOF_"typeName" to be the size'''
161    self.log.write('Checking for size of type: ' + typeName + '\n')
162    typename = typeName.replace(' ', '-').replace('*', 'p')
163    includes = '''
164#include <sys/types.h>
165#include <stdlib.h>
166#include <stdio.h>
167#include <stddef.h>'''
168    mpiFix = '''
169#define MPICH_IGNORE_CXX_SEEK
170#define MPICH_SKIP_MPICXX 1
171#define OMPI_SKIP_MPICXX 1\n'''
172    if otherInclude:
173      if otherInclude == 'mpi.h':
174        includes += mpiFix
175      includes += '#include <' + otherInclude + '>\n'
176    size = None
177    checkName = typeName
178    if typeName == 'enum':
179      checkName = 'enum{ENUM_DUMMY}'
180    with self.Language(lang):
181      for s in typeSizes:
182        body = 'char assert_sizeof[(sizeof({0})=={1})*2-1];'.format(checkName, s)
183        if self.checkCompile(includes, body, codeBegin=codeBegin, codeEnd='\n'):
184          size = s
185          break
186    if size is None:
187      raise RuntimeError('Unable to determine size of {0} not found'.format(typeName))
188    if save:
189      self.sizes[typename] = size
190      self.addDefine('SIZEOF_'+typename.replace('-', '_').upper(), str(size))
191    return size
192
193  def checkVisibility(self):
194    if not self.argDB['with-shared-libraries']:
195      self.argDB['with-visibility'] = 0
196      self.log.write('Disabled visibility attributes due to static build')
197    elif self.argDB['with-visibility']:
198      self.pushLanguage('C')
199      if self.checkCompile('','__attribute__((visibility ("default"))) int foo(void);'):
200        self.addDefine('USE_VISIBILITY_C',1)
201      else:
202        self.log.write('Cannot use visibility attributes with C')
203        self.argDB['with-visibility'] = 0
204      self.popLanguage()
205      if hasattr(self.compilers, 'CXX'):
206        self.pushLanguage('C++')
207        if self.checkCompile('','__attribute__((visibility ("default"))) int foo(void);'):
208          self.addDefine('USE_VISIBILITY_CXX',1)
209        else:
210          self.log.write('Cannot use visibility attributes with C++')
211        self.popLanguage()
212    else:
213      self.log.write('User turned off visibility attributes')
214
215  def checkMaxPathLen(self):
216    import re
217    HASHLINESPACE = ' *(?:\n#.*\n *)*'
218    self.log.write('Determining PETSC_MAX_PATH_LEN\n')
219    include = ''
220    if self.headers.haveHeader('sys/param.h'):
221      include = (include + '\n#include <sys/param.h>')
222    if self.headers.haveHeader('sys/types.h'):
223      include = (include + '\n#include <sys/types.h>')
224    length = include + '''
225#if defined(MAXPATHLEN)
226#  define PETSC_MAX_PATH_LEN MAXPATHLEN
227#elif defined(MAX_PATH)
228#  define PETSC_MAX_PATH_LEN MAX_PATH
229#elif defined(_MAX_PATH)
230#  define PETSC_MAX_PATH_LEN _MAX_PATH
231#else
232#  define PETSC_MAX_PATH_LEN 4096
233#endif
234#define xstr(s) str(s)
235#define str(s) #s
236char petsc_max_path_len[] = xstr(PETSC_MAX_PATH_LEN);
237'''
238    MaxPathLength = 'unknown'
239    if self.checkCompile(length):
240      buf = self.outputPreprocess(length)
241      try:
242        MaxPathLength = re.compile('\nchar petsc_max_path_len\s?\[\s?\] = '+HASHLINESPACE+'\"([0-9]+)\"'+HASHLINESPACE+';').search(buf).group(1)
243      except:
244        raise RuntimeError('Unable to determine PETSC_MAX_PATH_LEN')
245    if MaxPathLength == 'unknown' or not MaxPathLength.isdigit():
246      raise RuntimeError('Unable to determine PETSC_MAX_PATH_LEN')
247    else:
248      self.addDefine('MAX_PATH_LEN',MaxPathLength)
249
250
251  def configure(self):
252    self.executeTest(self.check_struct_sigaction)
253    self.executeTest(self.check__int64)
254    self.executeTest(self.checkSizeTypes)
255    self.executeTest(self.checkFileTypes)
256    self.executeTest(self.checkIntegerTypes)
257    self.executeTest(self.checkPID)
258    self.executeTest(self.checkUID)
259    self.executeTest(self.checkC99Complex)
260    if hasattr(self.compilers, 'CXX'):
261      self.executeTest(self.checkCxxComplex)
262    self.executeTest(self.checkConst)
263    for t, sizes in {'void *': (8, 4),
264                     'short': (2, 4, 8),
265                     'int': (4, 8, 2),
266                     'long': (8, 4),
267                     'long long': (8,),
268                     'enum': (4, 8),
269                     'size_t': (8, 4)}.items():
270      self.executeTest(self.checkSizeof, args=[t, sizes])
271    if self.sizes['void-p'] == 8:
272      self.addDefine('USING_64BIT_PTR',1)
273    self.executeTest(self.checkVisibility)
274    self.executeTest(self.checkMaxPathLen)
275    return
276