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