Merge pull request #1456 from ieei/compute_int

Add compute_int, fixes #435
pull/1486/head
Jussi Pakkanen 8 years ago committed by GitHub
commit df1480fe11
  1. 91
      mesonbuild/compilers.py
  2. 30
      mesonbuild/interpreter.py
  3. 2
      test cases/common/139 compute int/config.h.in
  4. 6
      test cases/common/139 compute int/foobar.h
  5. 35
      test cases/common/139 compute int/meson.build
  6. 16
      test cases/common/139 compute int/prog.c.in

@ -1001,44 +1001,75 @@ class CCompiler(Compiler):
mlog.debug(se)
return RunResult(True, pe.returncode, so, se)
def _bisect_compiles(self, t, fargs, env, extra_args, dependencies):
# FIXME: Does not actually do bisection right now
for i in range(1, 1024):
fargs['size'] = i
if self.compiles(t.format(**fargs), env, extra_args, dependencies):
if self.id == 'msvc':
# MSVC refuses to construct an array of zero size, so
# the test only succeeds when i is sizeof(element) + 1
return i - 1
return i
def _compile_int(self, expression, prefix, env, extra_args, dependencies):
fargs = {'prefix': prefix, 'expression': expression}
t = '''#include <stdio.h>
{prefix}
int main() {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}'''
return self.compiles(t.format(**fargs), env, extra_args, dependencies)
def cross_compute_int(self, expression, l, h, guess, prefix, env, extra_args, dependencies):
if isinstance(guess, int):
if self._compile_int('%s == %d' % (expression, guess), prefix, env, extra_args, dependencies):
return guess
cur = l
while l < h:
cur = int((l + h) / 2)
if cur == l:
break
if self._compile_int('%s >= %d' % (expression, cur), prefix, env, extra_args, dependencies):
l = cur
else:
h = cur
if self._compile_int('%s == %d' % (expression, cur), prefix, env, extra_args, dependencies):
return cur
raise EnvironmentException('Cross-compile check overflowed')
def cross_sizeof(self, element, prefix, env, extra_args=None, dependencies=None):
def compute_int(self, expression, l, h, guess, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
if self.is_cross:
return self.cross_compute_int(expression, l, h, guess, prefix, env, extra_args, dependencies)
fargs = {'prefix': prefix, 'expression': expression}
t = '''#include<stdio.h>
{prefix}
int main(int argc, char **argv) {{
printf("%ld\\n", (long)({expression}));
return 0;
}};'''
res = self.run(t.format(**fargs), env, extra_args, dependencies)
if not res.compiled:
return -1
if res.returncode != 0:
raise EnvironmentException('Could not run compute_int test binary.')
return int(res.stdout)
def cross_sizeof(self, typename, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
fargs = {'prefix': prefix, 'name': element}
fargs = {'prefix': prefix, 'type': typename}
t = '''#include <stdio.h>
{prefix}
int main(int argc, char **argv) {{
{name} something;
{type} something;
}}'''
if not self.compiles(t.format(**fargs), env, extra_args, dependencies):
return -1
t = '''#include <stdio.h>
{prefix}
int temparray[{size}-sizeof({name})];'''
return self._bisect_compiles(t, fargs, env, extra_args, dependencies)
return self.cross_compute_int('sizeof(%s)' % typename, 1, 128, None, prefix, env, extra_args, dependencies)
def sizeof(self, element, prefix, env, extra_args=None, dependencies=None):
def sizeof(self, typename, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
fargs = {'prefix': prefix, 'name': element}
fargs = {'prefix': prefix, 'type': typename}
if self.is_cross:
return self.cross_sizeof(element, prefix, env, extra_args, dependencies)
return self.cross_sizeof(typename, prefix, env, extra_args, dependencies)
t = '''#include<stdio.h>
{prefix}
int main(int argc, char **argv) {{
printf("%ld\\n", (long)(sizeof({name})));
printf("%ld\\n", (long)(sizeof({type})));
return 0;
}};'''
res = self.run(t.format(**fargs), env, extra_args, dependencies)
@ -1048,32 +1079,34 @@ class CCompiler(Compiler):
raise EnvironmentException('Could not run sizeof test binary.')
return int(res.stdout)
def cross_alignment(self, typename, env, extra_args=None, dependencies=None):
def cross_alignment(self, typename, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
fargs = {'type': typename}
fargs = {'prefix': prefix, 'type': typename}
t = '''#include <stdio.h>
{prefix}
int main(int argc, char **argv) {{
{type} something;
}}'''
if not self.compiles(t.format(**fargs), env, extra_args, dependencies):
return -1
t = '''#include <stddef.h>
{prefix}
struct tmp {{
char c;
{type} target;
}};
int testarray[{size}-offsetof(struct tmp, target)];'''
return self._bisect_compiles(t, fargs, env, extra_args, dependencies)
}};'''
return self.cross_compute_int('offsetof(struct tmp, target)', 1, 1024, None, t.format(**fargs), env, extra_args, dependencies)
def alignment(self, typename, env, extra_args=None, dependencies=None):
def alignment(self, typename, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
if self.is_cross:
return self.cross_alignment(typename, env, extra_args, dependencies)
fargs = {'type': typename}
return self.cross_alignment(typename, prefix, env, extra_args, dependencies)
fargs = {'prefix': prefix, 'type': typename}
t = '''#include <stdio.h>
#include <stddef.h>
{prefix}
struct tmp {{
char c;
{type} target;

@ -632,6 +632,7 @@ class CompilerHolder(InterpreterObject):
self.methods.update({'compiles': self.compiles_method,
'links': self.links_method,
'get_id': self.get_id_method,
'compute_int': self.compute_int_method,
'sizeof': self.sizeof_method,
'has_header': self.has_header_method,
'has_header_symbol': self.has_header_symbol_method,
@ -700,8 +701,12 @@ class CompilerHolder(InterpreterObject):
raise InterpreterException('Alignment method takes exactly one positional argument.')
check_stringlist(args)
typename = args[0]
prefix = kwargs.get('prefix', '')
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of sizeof must be a string.')
extra_args = mesonlib.stringlistify(kwargs.get('args', []))
result = self.compiler.alignment(typename, self.environment, extra_args)
deps = self.determine_dependencies(kwargs)
result = self.compiler.alignment(typename, prefix, self.environment, extra_args, deps)
mlog.log('Checking for alignment of "', mlog.bold(typename), '": ', result, sep='')
return result
@ -823,6 +828,29 @@ class CompilerHolder(InterpreterObject):
mlog.log('Checking for type "', mlog.bold(typename), '": ', hadtxt, sep='')
return had
def compute_int_method(self, args, kwargs):
if len(args) != 1:
raise InterpreterException('Compute_int takes exactly one argument.')
check_stringlist(args)
expression = args[0]
prefix = kwargs.get('prefix', '')
l = kwargs.get('low', -1024)
h = kwargs.get('high', 1024)
guess = kwargs.get('guess', None)
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of compute_int must be a string.')
if not isinstance(l, int):
raise InterpreterException('Low argument of compute_int must be an int.')
if not isinstance(h, int):
raise InterpreterException('High argument of compute_int must be an int.')
if guess is not None and not isinstance(guess, int):
raise InterpreterException('Guess argument of compute_int must be an int.')
extra_args = self.determine_args(kwargs)
deps = self.determine_dependencies(kwargs)
res = self.compiler.compute_int(expression, l, h, guess, prefix, self.environment, extra_args, deps)
mlog.log('Computing int of "%s": %d' % (expression, res))
return res
def sizeof_method(self, args, kwargs):
if len(args) != 1:
raise InterpreterException('Sizeof takes exactly one argument.')

@ -0,0 +1,2 @@
#define INTSIZE @INTSIZE@
#define FOOBAR_IN_CONFIG_H @FOOBAR@

@ -0,0 +1,6 @@
#ifndef __FOOBAR_H__
#define __FOOBAR_H__
#define FOOBAR_IN_FOOBAR_H 10
#endif /*__FOOBAR_H__*/

@ -0,0 +1,35 @@
project('compute int', 'c', 'cpp')
inc = include_directories('.')
# Test with C
cc = meson.get_compiler('c')
intsize = cc.compute_int('sizeof(int)', low : 1, high : 16, guess : 4)
foobar = cc.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc)
cd = configuration_data()
cd.set('INTSIZE', intsize)
cd.set('FOOBAR', foobar)
cd.set('CONFIG', 'config.h')
configure_file(input : 'config.h.in', output : 'config.h', configuration : cd)
s = configure_file(input : 'prog.c.in', output : 'prog.c', configuration : cd)
e = executable('prog', s)
test('compute int test', e)
# Test with C++
cpp = meson.get_compiler('cpp')
intsize = cpp.compute_int('sizeof(int)')
foobar = cpp.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc)
cdpp = configuration_data()
cdpp.set('INTSIZE', intsize)
cdpp.set('FOOBAR', foobar)
cdpp.set('CONFIG', 'config.hpp')
configure_file(input : 'config.h.in', output : 'config.hpp', configuration : cdpp)
spp = configure_file(input : 'prog.c.in', output : 'prog.cc', configuration : cdpp)
epp = executable('progpp', spp)
test('compute int test c++', epp)

@ -0,0 +1,16 @@
#include "@CONFIG@"
#include <stdio.h>
#include <wchar.h>
#include "foobar.h"
int main(int argc, char **argv) {
if(INTSIZE != sizeof(int)) {
fprintf(stderr, "Mismatch: computed int size %d, actual size %d.\n", INTSIZE, (int)sizeof(int));
return 1;
}
if(FOOBAR_IN_CONFIG_H != FOOBAR_IN_FOOBAR_H) {
fprintf(stderr, "Mismatch: computed int %d, should be %d.\n", FOOBAR_IN_CONFIG_H, FOOBAR_IN_FOOBAR_H);
return 1;
}
return 0;
}
Loading…
Cancel
Save