aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2017-03-23 16:02:40 -0400
committerGitHub <noreply@github.com>2017-03-23 16:02:40 -0400
commitdf1480fe11e5d4f20b7305abc2129d3c6494d1b5 (patch)
treee5166265aa96aba3972d5c3d111d31474536b454
parent1efab9b5a9e9cd361658226ede35ff455f954a44 (diff)
parent2f11e2e4630a7770eddbce7efdd7ce9b63de5ba1 (diff)
downloadmeson-df1480fe11e5d4f20b7305abc2129d3c6494d1b5.zip
meson-df1480fe11e5d4f20b7305abc2129d3c6494d1b5.tar.gz
meson-df1480fe11e5d4f20b7305abc2129d3c6494d1b5.tar.bz2
Merge pull request #1456 from ieei/compute_int
Add compute_int, fixes #435
-rw-r--r--mesonbuild/compilers.py91
-rw-r--r--mesonbuild/interpreter.py30
-rw-r--r--test cases/common/139 compute int/config.h.in2
-rw-r--r--test cases/common/139 compute int/foobar.h6
-rw-r--r--test cases/common/139 compute int/meson.build35
-rw-r--r--test cases/common/139 compute int/prog.c.in16
6 files changed, 150 insertions, 30 deletions
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
index f8c3f6b..519a7d5 100644
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -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;
diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py
index c16b668..79a531d 100644
--- a/mesonbuild/interpreter.py
+++ b/mesonbuild/interpreter.py
@@ -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.')
diff --git a/test cases/common/139 compute int/config.h.in b/test cases/common/139 compute int/config.h.in
new file mode 100644
index 0000000..ad8d077
--- /dev/null
+++ b/test cases/common/139 compute int/config.h.in
@@ -0,0 +1,2 @@
+#define INTSIZE @INTSIZE@
+#define FOOBAR_IN_CONFIG_H @FOOBAR@
diff --git a/test cases/common/139 compute int/foobar.h b/test cases/common/139 compute int/foobar.h
new file mode 100644
index 0000000..fd3cb5e
--- /dev/null
+++ b/test cases/common/139 compute int/foobar.h
@@ -0,0 +1,6 @@
+#ifndef __FOOBAR_H__
+#define __FOOBAR_H__
+
+#define FOOBAR_IN_FOOBAR_H 10
+
+#endif /*__FOOBAR_H__*/
diff --git a/test cases/common/139 compute int/meson.build b/test cases/common/139 compute int/meson.build
new file mode 100644
index 0000000..43553fe
--- /dev/null
+++ b/test cases/common/139 compute int/meson.build
@@ -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)
diff --git a/test cases/common/139 compute int/prog.c.in b/test cases/common/139 compute int/prog.c.in
new file mode 100644
index 0000000..3ff1463
--- /dev/null
+++ b/test cases/common/139 compute int/prog.c.in
@@ -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;
+}