compiler: Fix compute_int and sizeof for cross compilation.

sizeof now uses compute_int which again binary searches for correct value.
pull/1456/head
Haakon Sporsheim 8 years ago
parent 52f23f8c34
commit 1e2c914b3c
  1. 60
      mesonbuild/compilers.py
  2. 15
      mesonbuild/interpreter.py
  3. 2
      test cases/common/139 compute int/meson.build

@ -998,37 +998,43 @@ 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):
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
raise EnvironmentException('Cross-compile check overflowed')
def cross_compute_int(self, fragment, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
extra_args = []
fargs = {'prefix': prefix, 'fragment': fragment}
t = '''#include <stdio.h> t = '''#include <stdio.h>
{prefix} {prefix}
int temparray[{size}-({fragment})];''' int main() {{ static int a[1-2*!({expression})]; a[0]=0; return 0; }}'''
return self._bisect_compiles(t, fargs, env, extra_args, dependencies) 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
def compute_int(self, fragment, prefix, env, extra_args=None, dependencies=None): 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 compute_int(self, expression, l, h, guess, prefix, env, extra_args=None, dependencies=None):
if extra_args is None: if extra_args is None:
extra_args = [] extra_args = []
fargs = {'prefix': prefix, 'fragment': fragment}
if self.is_cross: if self.is_cross:
return self.cross_compute_int(fragment, prefix, env, extra_args, dependencies) return self.cross_compute_int(expression, l, h, guess, prefix, env, extra_args, dependencies)
fargs = {'prefix': prefix, 'expression': expression}
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)({fragment})); printf("%ld\\n", (long)({expression}));
return 0; return 0;
}};''' }};'''
res = self.run(t.format(**fargs), env, extra_args, dependencies) res = self.run(t.format(**fargs), env, extra_args, dependencies)
@ -1049,10 +1055,7 @@ class CCompiler(Compiler):
}}''' }}'''
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)' % element, 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, element, prefix, env, extra_args=None, dependencies=None):
if extra_args is None: if extra_args is None:
@ -1087,9 +1090,8 @@ class CCompiler(Compiler):
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, env, extra_args=None, dependencies=None):
if extra_args is None: if extra_args is None:

@ -827,14 +827,23 @@ class CompilerHolder(InterpreterObject):
if len(args) != 1: if len(args) != 1:
raise InterpreterException('Compute_int takes exactly one argument.') raise InterpreterException('Compute_int takes exactly one argument.')
check_stringlist(args) check_stringlist(args)
fragment = args[0] expression = args[0]
prefix = kwargs.get('prefix', '') prefix = kwargs.get('prefix', '')
l = kwargs.get('low', -1024)
h = kwargs.get('high', 1024)
guess = kwargs.get('guess', None)
if not isinstance(prefix, str): if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of compute_int must be a string.') 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) extra_args = self.determine_args(kwargs)
deps = self.determine_dependencies(kwargs) deps = self.determine_dependencies(kwargs)
res = self.compiler.compute_int(fragment, prefix, self.environment, extra_args, deps) res = self.compiler.compute_int(expression, l, h, guess, prefix, self.environment, extra_args, deps)
mlog.log('Computing int of "%s": %d' % (fragment, res)) mlog.log('Computing int of "%s": %d' % (expression, res))
return res return res
def sizeof_method(self, args, kwargs): def sizeof_method(self, args, kwargs):

@ -5,7 +5,7 @@ inc = include_directories('.')
# Test with C # Test with C
cc = meson.get_compiler('c') cc = meson.get_compiler('c')
intsize = cc.compute_int('sizeof(int)') 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) foobar = cc.compute_int('FOOBAR_IN_FOOBAR_H', prefix : '#include "foobar.h"', include_directories : inc)
cd = configuration_data() cd = configuration_data()

Loading…
Cancel
Save