diff options
-rw-r--r-- | mesonbuild/compilers.py | 77 | ||||
-rw-r--r-- | mesonbuild/interpreter.py | 50 | ||||
-rw-r--r-- | test cases/linuxlike/9 compiler checks with dependencies/meson.build | 31 |
3 files changed, 118 insertions, 40 deletions
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 8772803..c5b932c 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -588,15 +588,15 @@ class CCompiler(Compiler): code = 'int main(int argc, char **argv) { int class=0; return class; }\n' return self.sanity_check_impl(work_dir, environment, 'sanitycheckc.c', code) - def has_header(self, hname, env, extra_args=None): + def has_header(self, hname, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] templ = '''#include<%s> int someSymbolHereJustForFun; ''' - return self.compiles(templ % hname, env, extra_args) + return self.compiles(templ % hname, env, extra_args, dependencies) - def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None): + def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] templ = '''{2} @@ -604,7 +604,7 @@ int someSymbolHereJustForFun; int main () {{ {1}; }}''' # Pass -O0 to ensure that the symbol isn't optimized away args = extra_args + self.get_no_optimization_args() - return self.compiles(templ.format(hname, symbol, prefix), env, args) + return self.compiles(templ.format(hname, symbol, prefix), env, args, dependencies) def compile(self, code, srcname, extra_args=None): if extra_args is None: @@ -624,18 +624,23 @@ int main () {{ {1}; }}''' os.remove(srcname) return p - def compiles(self, code, env, extra_args=None): + def compiles(self, code, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] if isinstance(extra_args, str): extra_args = [extra_args] + if dependencies is None: + dependencies = [] + elif not isinstance(dependencies, list): + dependencies = [dependencies] suflen = len(self.default_suffix) (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix) os.close(fd) with open(srcname, 'w') as ofile: ofile.write(code) + cargs = [a for d in dependencies for a in d.get_compile_args()] # Convert flags to the native type of the selected compiler - args = self.unix_link_flags_to_native(extra_args) + args = self.unix_link_flags_to_native(cargs + extra_args) # Read c_args/cpp_args/etc from the cross-info file (if needed) args += self.get_cross_extra_flags(env, compile=True, link=False) # We only want to compile; not link @@ -652,19 +657,25 @@ int main () {{ {1}; }}''' pass return p.returncode == 0 - def links(self, code, env, extra_args=None): + def links(self, code, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] elif isinstance(extra_args, str): extra_args = [extra_args] + if dependencies is None: + dependencies = [] + elif not isinstance(dependencies, list): + dependencies = [dependencies] (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix) os.close(fd) (fd, dstname) = tempfile.mkstemp() os.close(fd) with open(srcname, 'w') as ofile: ofile.write(code) + cargs = [a for d in dependencies for a in d.get_compile_args()] + link_args = [a for d in dependencies for a in d.get_link_args()] # Convert flags to the native type of the selected compiler - args = self.unix_link_flags_to_native(extra_args) + args = self.unix_link_flags_to_native(cargs + link_args + extra_args) # Select a CRT if needed since we're linking args += self.get_linker_debug_crt_args() # Read c_args/c_link_args/cpp_args/cpp_link_args/etc from the cross-info file (if needed) @@ -678,17 +689,23 @@ int main () {{ {1}; }}''' pass return p.returncode == 0 - def run(self, code, env, extra_args=None): + def run(self, code, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] + if dependencies is None: + dependencies = [] + elif not isinstance(dependencies, list): + dependencies = [dependencies] if self.is_cross and self.exe_wrapper is None: raise CrossNoRunException('Can not run test applications in this cross environment.') (fd, srcname) = tempfile.mkstemp(suffix='.'+self.default_suffix) os.close(fd) with open(srcname, 'w') as ofile: ofile.write(code) + cargs = [a for d in dependencies for a in d.get_compile_args()] + link_args = [a for d in dependencies for a in d.get_link_args()] # Convert flags to the native type of the selected compiler - args = self.unix_link_flags_to_native(extra_args) + args = self.unix_link_flags_to_native(cargs + link_args + extra_args) # Select a CRT if needed since we're linking args += self.get_linker_debug_crt_args() # Read c_link_args/cpp_link_args/etc from the cross-info file @@ -737,7 +754,7 @@ int main () {{ {1}; }}''' pass return RunResult(True, pe.returncode, so, se) - def cross_sizeof(self, element, prefix, env, extra_args=None): + def cross_sizeof(self, element, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] element_exists_templ = '''#include <stdio.h> @@ -751,11 +768,11 @@ int main(int argc, char **argv) {{ int temparray[%d-sizeof(%s)]; ''' args = extra_args + self.get_no_optimization_args() - if not self.compiles(element_exists_templ.format(prefix, element), env, args): + if not self.compiles(element_exists_templ.format(prefix, element), env, args, dependencies): return -1 for i in range(1, 1024): code = templ % (prefix, i, element) - if self.compiles(code, env, args): + if self.compiles(code, env, 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 @@ -763,11 +780,11 @@ int temparray[%d-sizeof(%s)]; return i raise EnvironmentException('Cross checking sizeof overflowed.') - def sizeof(self, element, prefix, env, extra_args=None): + def sizeof(self, element, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] if self.is_cross: - return self.cross_sizeof(element, prefix, env, extra_args) + return self.cross_sizeof(element, prefix, env, extra_args, dependencies) templ = '''#include<stdio.h> %s @@ -776,14 +793,14 @@ int main(int argc, char **argv) { return 0; }; ''' - res = self.run(templ % (prefix, element), env, extra_args) + res = self.run(templ % (prefix, element), env, extra_args, dependencies) if not res.compiled: return -1 if res.returncode != 0: raise EnvironmentException('Could not run sizeof test binary.') return int(res.stdout) - def cross_alignment(self, typename, env, extra_args=None): + def cross_alignment(self, typename, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] type_exists_templ = '''#include <stdio.h> @@ -800,11 +817,11 @@ struct tmp { int testarray[%d-offsetof(struct tmp, target)]; ''' args = extra_args + self.get_no_optimization_args() - if not self.compiles(type_exists_templ.format(typename), env, args): + if not self.compiles(type_exists_templ.format(typename), env, args, dependencies): return -1 for i in range(1, 1024): code = templ % (typename, i) - if self.compiles(code, env, args): + if self.compiles(code, env, 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 @@ -812,11 +829,11 @@ int testarray[%d-offsetof(struct tmp, target)]; return i raise EnvironmentException('Cross checking offsetof overflowed.') - def alignment(self, typename, env, extra_args=None): + def alignment(self, typename, 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) + return self.cross_alignment(typename, env, extra_args, dependencies) templ = '''#include<stdio.h> #include<stddef.h> @@ -830,7 +847,7 @@ int main(int argc, char **argv) { return 0; } ''' - res = self.run(templ % typename, env, extra_args) + res = self.run(templ % typename, env, extra_args, dependencies) if not res.compiled: raise EnvironmentException('Could not compile alignment test.') if res.returncode != 0: @@ -840,7 +857,7 @@ int main(int argc, char **argv) { raise EnvironmentException('Could not determine alignment of %s. Sorry. You might want to file a bug.' % typename) return align - def has_function(self, funcname, prefix, env, extra_args=None): + def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None): """ First, this function looks for the symbol in the default libraries provided by the compiler (stdlib + a few others usually). If that @@ -897,7 +914,7 @@ int main(int argc, char **argv) { if isinstance(val, bool): return val raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname)) - if self.links(templ.format(prefix, funcname), env, extra_args): + if self.links(templ.format(prefix, funcname), env, extra_args, dependencies): return True # Add -O0 to ensure that the symbol isn't optimized away by the compiler args = extra_args + self.get_no_optimization_args() @@ -906,15 +923,15 @@ int main(int argc, char **argv) { # still detect the function. We still want to fail if __stub_foo or # _stub_foo are defined, of course. header_templ = '#include <limits.h>\n{0}\n' + stubs_fail + '\nint main() {{ {1}; }}' - if self.links(header_templ.format(prefix, funcname), env, args): + if self.links(header_templ.format(prefix, funcname), env, args, dependencies): return True # Some functions like alloca() are defined as compiler built-ins which # are inlined by the compiler, so test for that instead. Built-ins are # special functions that ignore all includes and defines, so we just # directly try to link via main(). - return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), env, args) + return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), env, args, dependencies) - def has_members(self, typename, membernames, prefix, env, extra_args=None): + def has_members(self, typename, membernames, prefix, env, extra_args=None, dependencies=None): if extra_args is None: extra_args = [] templ = '''{0} @@ -928,15 +945,15 @@ void bar() {{ for m in membernames: members += 'foo.{};\n'.format(m) code = templ.format(prefix, typename, 'foo', members) - return self.compiles(code, env, extra_args) + return self.compiles(code, env, extra_args, dependencies) - def has_type(self, typename, prefix, env, extra_args): + def has_type(self, typename, prefix, env, extra_args, dependencies=None): templ = '''%s void bar() { sizeof(%s); }; ''' - return self.compiles(templ % (prefix, typename), env, extra_args) + return self.compiles(templ % (prefix, typename), env, extra_args, dependencies) def find_library(self, libname, env, extra_dirs): # First try if we can just add the library as -l. diff --git a/mesonbuild/interpreter.py b/mesonbuild/interpreter.py index 4a76c94..385e07a 100644 --- a/mesonbuild/interpreter.py +++ b/mesonbuild/interpreter.py @@ -666,6 +666,25 @@ class CompilerHolder(InterpreterObject): args += mesonlib.stringlistify(kwargs.get('args', [])) return args + def determine_dependencies(self, kwargs, allowed_dep_types=None): + deps = kwargs.get('dependencies', None) + if allowed_dep_types is None: + allowed_dep_types = (dependencies.Dependency, dependencies.ExternalLibrary) + if deps is not None: + if not isinstance(deps, list): + deps = [deps] + final_deps = [] + for d in deps: + try: + d = d.held_object + except Exception: + pass + if not isinstance(d, allowed_dep_types): + raise InterpreterException('Dependencies must be external deps') + final_deps.append(d) + deps = final_deps + return deps + def alignment_method(self, args, kwargs): if len(args) != 1: raise InterpreterException('Alignment method takes exactly one positional argument.') @@ -685,7 +704,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') extra_args = self.determine_args(kwargs) - result = self.compiler.run(code, self.environment, extra_args) + deps = self.determine_dependencies(kwargs) + result = self.compiler.run(code, self.environment, extra_args, deps) if len(testname) > 0: if not result.compiled: h = mlog.red('DID NOT COMPILE') @@ -715,8 +735,9 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_member must be a string.') extra_args = self.determine_args(kwargs) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) had = self.compiler.has_members(typename, [membername], prefix, - self.environment, extra_args) + self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: @@ -733,8 +754,9 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_members must be a string.') extra_args = self.determine_args(kwargs) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) had = self.compiler.has_members(typename, membernames, prefix, - self.environment, extra_args) + self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: @@ -753,7 +775,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_function must be a string.') extra_args = self.determine_args(kwargs) - had = self.compiler.has_function(funcname, prefix, self.environment, extra_args) + deps = self.determine_dependencies(kwargs) + had = self.compiler.has_function(funcname, prefix, self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: @@ -770,7 +793,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_type must be a string.') extra_args = self.determine_args(kwargs) - had = self.compiler.has_type(typename, prefix, self.environment, extra_args) + deps = self.determine_dependencies(kwargs) + had = self.compiler.has_type(typename, prefix, self.environment, extra_args, deps) if had: hadtxt = mlog.green('YES') else: @@ -787,7 +811,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of sizeof must be a string.') extra_args = self.determine_args(kwargs) - esize = self.compiler.sizeof(element, prefix, self.environment, extra_args) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) + esize = self.compiler.sizeof(element, prefix, self.environment, extra_args, deps) mlog.log('Checking for size of "%s": %d' % (element, esize)) return esize @@ -800,7 +825,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') extra_args = self.determine_args(kwargs) - result = self.compiler.compiles(code, self.environment, extra_args) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) + result = self.compiler.compiles(code, self.environment, extra_args, deps) if len(testname) > 0: if result: h = mlog.green('YES') @@ -818,7 +844,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(testname, str): raise InterpreterException('Testname argument must be a string.') extra_args = self.determine_args(kwargs) - result = self.compiler.links(code, self.environment, extra_args) + deps = self.determine_dependencies(kwargs) + result = self.compiler.links(code, self.environment, extra_args, deps) if len(testname) > 0: if result: h = mlog.green('YES') @@ -833,7 +860,8 @@ class CompilerHolder(InterpreterObject): check_stringlist(args) string = args[0] extra_args = self.determine_args(kwargs) - haz = self.compiler.has_header(string, self.environment, extra_args) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) + haz = self.compiler.has_header(string, self.environment, extra_args, deps) if haz: h = mlog.green('YES') else: @@ -851,7 +879,8 @@ class CompilerHolder(InterpreterObject): if not isinstance(prefix, str): raise InterpreterException('Prefix argument of has_function must be a string.') extra_args = self.determine_args(kwargs) - haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, extra_args) + deps = self.determine_dependencies(kwargs, allowed_dep_types=(dependencies.Dependency,)) + haz = self.compiler.has_header_symbol(hname, symbol, prefix, self.environment, extra_args, deps) if haz: h = mlog.green('YES') else: @@ -860,6 +889,7 @@ class CompilerHolder(InterpreterObject): return haz def find_library_method(self, args, kwargs): + # TODO add dependencies support? if len(args) != 1: raise InterpreterException('find_library method takes one argument.') libname = args[0] diff --git a/test cases/linuxlike/9 compiler checks with dependencies/meson.build b/test cases/linuxlike/9 compiler checks with dependencies/meson.build new file mode 100644 index 0000000..2aa9015 --- /dev/null +++ b/test cases/linuxlike/9 compiler checks with dependencies/meson.build @@ -0,0 +1,31 @@ +project('compiler checks with dependencies', 'c') + +cc = meson.get_compiler('c') + +glib = dependency ('glib-2.0') +if glib.found() + assert (cc.has_header('glib.h', dependencies : glib), 'glib.h not found') + assert (cc.has_type('gint32', prefix : '#include <glib.h>', dependencies : glib), 'gint32 not found') + assert (cc.has_function('g_print', dependencies : glib), 'g_print not found') + assert (cc.has_member('GError', 'message', prefix : '#include <glib.h>', dependencies : glib), 'GError::message not found') + assert (cc.has_header_symbol('glib.h', 'gint32', dependencies : glib), 'gint32 symbol not found') + linkcode = '''#include <glib.h> +int main (int argc, char *argv[]) { + GError *error = g_error_new_literal (0, 0, NULL); + return error == NULL; +} + ''' + assert (cc.links(linkcode, dependencies : glib, name : 'Test link against glib'), 'Linking test against glib failed') +endif + +zlib = cc.find_library ('z') +if zlib.found() + linkcode = '''#include<zlib.h> +int main(int argc, char *argv[]) { + void *ptr = (void*)(deflate); + return ptr == 0; +} +''' + assert (cc.has_function('deflate', prefix : '#include<zlib.h>', dependencies : zlib, name : 'Test for function in zlib'), 'has_function test failed.') + assert (cc.links(linkcode, dependencies : zlib, name : 'Test link against zlib'), 'Linking test failed against zlib.') +endif |