aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaakon Sporsheim <haakon.sporsheim@gmail.com>2017-03-10 11:40:48 +0100
committerHaakon Sporsheim <haakon.sporsheim@gmail.com>2017-03-10 12:33:21 +0100
commit1e2c914b3c508e1749890be85867e1f51336ece1 (patch)
treed72f22fa572950c28a8aa3495491550e4898886a
parent52f23f8c34bd9f6eacd31e8dff70066ca2aeb4e1 (diff)
downloadmeson-1e2c914b3c508e1749890be85867e1f51336ece1.zip
meson-1e2c914b3c508e1749890be85867e1f51336ece1.tar.gz
meson-1e2c914b3c508e1749890be85867e1f51336ece1.tar.bz2
compiler: Fix compute_int and sizeof for cross compilation.
sizeof now uses compute_int which again binary searches for correct value.
-rw-r--r--mesonbuild/compilers.py60
-rw-r--r--mesonbuild/interpreter.py15
-rw-r--r--test cases/common/139 compute int/meson.build2
3 files changed, 44 insertions, 33 deletions
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index d1a564b..403dda1 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -998,37 +998,43 @@ 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
- 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}
+ def _compile_int(self, expression, prefix, env, extra_args, dependencies):
+ fargs = {'prefix': prefix, 'expression': expression}
t = '''#include <stdio.h>
{prefix}
- int temparray[{size}-({fragment})];'''
- return self._bisect_compiles(t, fargs, env, extra_args, dependencies)
+ 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
- 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:
extra_args = []
- fargs = {'prefix': prefix, 'fragment': fragment}
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>
{prefix}
int main(int argc, char **argv) {{
- printf("%ld\\n", (long)({fragment}));
+ printf("%ld\\n", (long)({expression}));
return 0;
}};'''
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):
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)' % element, 1, 128, None, prefix, env, extra_args, dependencies)
def sizeof(self, element, prefix, env, extra_args=None, dependencies=None):
if extra_args is None:
@@ -1087,9 +1090,8 @@ class CCompiler(Compiler):
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):
if extra_args is None:
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index dca7934..bd818bb 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -827,14 +827,23 @@ class CompilerHolder(InterpreterObject):
if len(args) != 1:
raise InterpreterException('Compute_int takes exactly one argument.')
check_stringlist(args)
- fragment = args[0]
+ 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(fragment, prefix, self.environment, extra_args, deps)
- mlog.log('Computing int of "%s": %d' % (fragment, res))
+ 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):
diff --git a/test cases/common/139 compute int/meson.build b/test cases/common/139 compute int/meson.build
index 6f813c5..43553fe 100644
--- a/test cases/common/139 compute int/meson.build
+++ b/test cases/common/139 compute int/meson.build
@@ -5,7 +5,7 @@ inc = include_directories('.')
# Test with 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)
cd = configuration_data()