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

@ -632,6 +632,7 @@ class CompilerHolder(InterpreterObject):
self.methods.update({'compiles': self.compiles_method, self.methods.update({'compiles': self.compiles_method,
'links': self.links_method, 'links': self.links_method,
'get_id': self.get_id_method, 'get_id': self.get_id_method,
'compute_int': self.compute_int_method,
'sizeof': self.sizeof_method, 'sizeof': self.sizeof_method,
'has_header': self.has_header_method, 'has_header': self.has_header_method,
'has_header_symbol': self.has_header_symbol_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.') raise InterpreterException('Alignment method takes exactly one positional argument.')
check_stringlist(args) check_stringlist(args)
typename = args[0] 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', [])) 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='') mlog.log('Checking for alignment of "', mlog.bold(typename), '": ', result, sep='')
return result return result
@ -823,6 +828,29 @@ class CompilerHolder(InterpreterObject):
mlog.log('Checking for type "', mlog.bold(typename), '": ', hadtxt, sep='') mlog.log('Checking for type "', mlog.bold(typename), '": ', hadtxt, sep='')
return had 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): def sizeof_method(self, args, kwargs):
if len(args) != 1: if len(args) != 1:
raise InterpreterException('Sizeof takes exactly one argument.') 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