From f6dfd362393fb1e999bcc0dbc7ef65c48d8b204f Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 8 Nov 2016 15:01:52 +0530 Subject: [PATCH 1/8] has_header_symbol: Make it work with C++ compilers Need to pass -fpermissive to force C++ compilers to only warn about our non-conformant code that tests for a symbol being defined. Also do a simple #ifdef check first in has_header_symbol to allow arbitrary macros to be detected which would not have been detected earlier. This follows what AC_CHECK_DECL does. Closes #958 --- mesonbuild/compilers.py | 37 +++++++++++++++---- .../common/111 has header symbol/meson.build | 23 +++++++----- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 94e8a543c..ce137cb11 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -512,6 +512,13 @@ class CCompiler(Compiler): def get_no_optimization_args(self): return ['-O0'] + def get_compiler_check_args(self): + ''' + Get arguments useful for compiler checks such as being permissive in + the code quality and not doing any optimization. + ''' + return self.get_no_optimization_args() + def get_output_args(self, target): return ['-o', target] @@ -643,9 +650,14 @@ int someSymbolHereJustForFun; extra_args = [] templ = '''{2} #include <{0}> -int main () {{ {1}; }}''' - # Pass -O0 to ensure that the symbol isn't optimized away - args = extra_args + self.get_no_optimization_args() +int main () {{ + /* If it's not defined as a macro, try to use as a symbol */ + #ifndef {1} + {1}; + #endif + return 0; +}}''' + args = extra_args + self.get_compiler_check_args() return self.compiles(templ.format(hname, symbol, prefix), env, args, dependencies) @contextlib.contextmanager @@ -784,7 +796,7 @@ int main(int argc, char **argv) {{ %s int temparray[%d-sizeof(%s)]; ''' - args = extra_args + self.get_no_optimization_args() + args = extra_args + self.get_compiler_check_args() if not self.compiles(element_exists_templ.format(prefix, element), env, args, dependencies): return -1 for i in range(1, 1024): @@ -833,7 +845,7 @@ struct tmp { int testarray[%d-offsetof(struct tmp, target)]; ''' - args = extra_args + self.get_no_optimization_args() + args = extra_args + self.get_compiler_check_args() if not self.compiles(type_exists_templ.format(typename), env, args, dependencies): return -1 for i in range(1, 1024): @@ -967,8 +979,7 @@ int main(int argc, char **argv) { head, main = self._no_prototype_templ() templ = head + stubs_fail + main - # Add -O0 to ensure that the symbol isn't optimized away by the compiler - args = extra_args + self.get_no_optimization_args() + args = extra_args + self.get_compiler_check_args() if self.links(templ.format(prefix, funcname), env, extra_args, dependencies): return True # Some functions like alloca() are defined as compiler built-ins which @@ -2035,6 +2046,12 @@ class GnuCPPCompiler(GnuCompiler, CPPCompiler): return options['cpp_winlibs'].value return [] + def get_compiler_check_args(self): + # -fpermissive allows non-conforming code to compile which is necessary + # for many C++ checks. Particularly, the has_header_symbol check is + # too strict without this and always fails. + return self.get_no_optimization_args() + ['-fpermissive'] + class GnuObjCCompiler(GnuCompiler,ObjCCompiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None, defines=None): @@ -2057,6 +2074,12 @@ class GnuObjCPPCompiler(GnuCompiler, ObjCPPCompiler): '2': ['-Wall', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor'], '3' : ['-Wall', '-Wpedantic', '-Wextra', '-Winvalid-pch', '-Wnon-virtual-dtor']} + def get_compiler_check_args(self): + # -fpermissive allows non-conforming code to compile which is necessary + # for many ObjC++ checks. Particularly, the has_header_symbol check is + # too strict without this and always fails. + return self.get_no_optimization_args() + ['-fpermissive'] + class ClangCompiler(): def __init__(self, clang_type): self.id = 'clang' diff --git a/test cases/common/111 has header symbol/meson.build b/test cases/common/111 has header symbol/meson.build index e0afb4212..c62e7c044 100644 --- a/test cases/common/111 has header symbol/meson.build +++ b/test cases/common/111 has header symbol/meson.build @@ -1,18 +1,23 @@ -project('has header symbol', 'c') +project('has header symbol', 'c', 'cpp') cc = meson.get_compiler('c') +cpp = meson.get_compiler('cpp') -assert (cc.has_header_symbol('stdio.h', 'int'), 'base types should always be available') -assert (cc.has_header_symbol('stdio.h', 'printf'), 'printf function not found') -assert (cc.has_header_symbol('stdio.h', 'FILE'), 'FILE structure not found') -assert (cc.has_header_symbol('limits.h', 'INT_MAX'), 'INT_MAX define not found') -assert (not cc.has_header_symbol('limits.h', 'guint64'), 'guint64 is not defined in limits.h') -assert (not cc.has_header_symbol('stdlib.h', 'FILE'), 'FILE structure is defined in stdio.h, not stdlib.h') -assert (not cc.has_header_symbol('stdlol.h', 'printf'), 'stdlol.h shouldn\'t exist') -assert (not cc.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header') +foreach comp : [cc, cpp] + assert (comp.has_header_symbol('stdio.h', 'int'), 'base types should always be available') + assert (comp.has_header_symbol('stdio.h', 'printf'), 'printf function not found') + assert (comp.has_header_symbol('stdio.h', 'FILE'), 'FILE structure not found') + assert (comp.has_header_symbol('limits.h', 'INT_MAX'), 'INT_MAX define not found') + assert (not comp.has_header_symbol('limits.h', 'guint64'), 'guint64 is not defined in limits.h') + assert (not comp.has_header_symbol('stdlib.h', 'FILE'), 'FILE structure is defined in stdio.h, not stdlib.h') + assert (not comp.has_header_symbol('stdlol.h', 'printf'), 'stdlol.h shouldn\'t exist') + assert (not comp.has_header_symbol('stdlol.h', 'int'), 'shouldn\'t be able to find "int" with invalid header') +endforeach # This is likely only available on Glibc, so just test for it if cc.has_function('ppoll') assert (not cc.has_header_symbol('poll.h', 'ppoll'), 'ppoll should not be accessible without _GNU_SOURCE') assert (cc.has_header_symbol('poll.h', 'ppoll', prefix : '#define _GNU_SOURCE'), 'ppoll should be accessible with _GNU_SOURCE') endif + + From 4d84241ccf515446b49ddbe19683184b5a4e5a13 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 8 Nov 2016 15:04:19 +0530 Subject: [PATCH 2/8] has_header_symbol: Also detect C++ classes and templates With the `using` keyword we can try to use the specified class or template which will tell us if it exists. --- mesonbuild/compilers.py | 14 ++++++++++++++ .../common/111 has header symbol/meson.build | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index ce137cb11..31cafa659 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -1059,6 +1059,20 @@ class CPPCompiler(CCompiler): code = 'class breakCCompiler;int main(int argc, char **argv) { return 0; }\n' return self.sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code) + def has_header_symbol(self, hname, symbol, prefix, env, extra_args=None, dependencies=None): + # Check if it's a C-like symbol + if super().has_header_symbol(hname, symbol, prefix, env, extra_args, dependencies): + return True + # Check if it's a class or a template + if extra_args is None: + extra_args = [] + templ = '''{2} +#include <{0}> +using {1}; +int main () {{ return 0; }}''' + args = extra_args + self.get_compiler_check_args() + return self.compiles(templ.format(hname, symbol, prefix), env, args, dependencies) + class ObjCCompiler(CCompiler): def __init__(self, exelist, version, is_cross, exe_wrap): self.language = 'objc' diff --git a/test cases/common/111 has header symbol/meson.build b/test cases/common/111 has header symbol/meson.build index c62e7c044..b5c865f1d 100644 --- a/test cases/common/111 has header symbol/meson.build +++ b/test cases/common/111 has header symbol/meson.build @@ -20,4 +20,13 @@ if cc.has_function('ppoll') assert (cc.has_header_symbol('poll.h', 'ppoll', prefix : '#define _GNU_SOURCE'), 'ppoll should be accessible with _GNU_SOURCE') endif +assert (cpp.has_header_symbol('iostream', 'std::iostream'), 'iostream not found in iostream.h') +assert (cpp.has_header_symbol('vector', 'std::vector'), 'vector not found in vector.h') +assert (not cpp.has_header_symbol('limits.h', 'std::iostream'), 'iostream should not be defined in limits.h') +boost = dependency('boost', required : false) +if boost.found() + assert (cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion not found') +else + assert (not cpp.has_header_symbol('boost/math/quaternion.hpp', 'boost::math::quaternion', dependencies : boost), 'quaternion found?!') +endif From 7400284e3233d7974beb53761db97885e26d1547 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 8 Nov 2016 15:35:37 +0530 Subject: [PATCH 3/8] has_function: Fix trivial typo This was breaking has_function on C++ --- mesonbuild/compilers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 31cafa659..9b6ad8ca2 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -980,7 +980,7 @@ int main(int argc, char **argv) { templ = head + stubs_fail + main args = extra_args + self.get_compiler_check_args() - if self.links(templ.format(prefix, funcname), env, extra_args, dependencies): + if self.links(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 From ae5a3629509fdd8f17fbfcecbfeb6798d2be6630 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 8 Nov 2016 15:34:44 +0530 Subject: [PATCH 4/8] tests/common: Run compiler checks for both C & C++ Without this we're just hoping that the C++ compiler behaves the same way as the C compiler, which is not always true as demonstrated by https://github.com/mesonbuild/meson/issues/958 --- test cases/common/33 try compile/meson.build | 29 +++---- test cases/common/35 sizeof/meson.build | 24 +++++- .../common/35 sizeof/{prog.c => prog.c.in} | 6 +- test cases/common/37 has header/meson.build | 18 ++--- test cases/common/39 tryrun/meson.build | 80 ++++++++++--------- test cases/common/43 has function/meson.build | 72 +++++++++-------- test cases/common/44 has member/meson.build | 30 +++---- test cases/common/45 alignment/meson.build | 48 +++++------ test cases/common/83 has type/meson.build | 18 +++-- 9 files changed, 178 insertions(+), 147 deletions(-) rename test cases/common/35 sizeof/{prog.c => prog.c.in} (87%) diff --git a/test cases/common/33 try compile/meson.build b/test cases/common/33 try compile/meson.build index bca82ce45..09ca395be 100644 --- a/test cases/common/33 try compile/meson.build +++ b/test cases/common/33 try compile/meson.build @@ -1,4 +1,4 @@ -project('try compile', 'c') +project('try compile', 'c', 'cpp') code = '''#include void func() { printf("Something.\n"); } @@ -8,19 +8,20 @@ breakcode = '''#include void func() { printf("This won't work.\n"); } ''' -compiler = meson.get_compiler('c') -if compiler.compiles(code, name : 'should succeed') == false - error('Compiler is fail.') -endif +foreach compiler : [meson.get_compiler('c'), meson.get_compiler('cpp')] + if compiler.compiles(code, name : 'should succeed') == false + error('Compiler ' + compiler.get_id() + ' is fail.') + endif -if compiler.compiles(files('valid.c'), name : 'should succeed') == false - error('Compiler is fail.') -endif + if compiler.compiles(files('valid.c'), name : 'should succeed') == false + error('Compiler ' + compiler.get_id() + ' is fail.') + endif -if compiler.compiles(breakcode, name : 'should fail') - error('Compiler returned true on broken code.') -endif + if compiler.compiles(breakcode, name : 'should fail') + error('Compiler ' + compiler.get_id() + ' returned true on broken code.') + endif -if compiler.compiles(files('invalid.c'), name : 'should fail') - error('Compiler returned true on broken code.') -endif + if compiler.compiles(files('invalid.c'), name : 'should fail') + error('Compiler ' + compiler.get_id() + ' returned true on broken code.') + endif +endforeach diff --git a/test cases/common/35 sizeof/meson.build b/test cases/common/35 sizeof/meson.build index 4a0398ba2..9de5b7816 100644 --- a/test cases/common/35 sizeof/meson.build +++ b/test cases/common/35 sizeof/meson.build @@ -1,13 +1,33 @@ -project('sizeof', 'c') +project('sizeof', 'c', 'cpp') +# Test with C cc = meson.get_compiler('c') + intsize = cc.sizeof('int') wcharsize = cc.sizeof('wchar_t', prefix : '#include') cd = configuration_data() cd.set('INTSIZE', intsize) cd.set('WCHARSIZE', wcharsize) +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', 'prog.c') +e = executable('prog', s) test('sizeof test', e) + +# Test with C++ +cpp = meson.get_compiler('cpp') + +intsize = cpp.sizeof('int') +wcharsize = cpp.sizeof('wchar_t', prefix : '#include') + +cdpp = configuration_data() +cdpp.set('INTSIZE', intsize) +cdpp.set('WCHARSIZE', wcharsize) +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('sizeof test c++', epp) diff --git a/test cases/common/35 sizeof/prog.c b/test cases/common/35 sizeof/prog.c.in similarity index 87% rename from test cases/common/35 sizeof/prog.c rename to test cases/common/35 sizeof/prog.c.in index 9164c18b0..85b12299c 100644 --- a/test cases/common/35 sizeof/prog.c +++ b/test cases/common/35 sizeof/prog.c.in @@ -1,6 +1,6 @@ -#include"config.h" -#include -#include +#include "@CONFIG@" +#include +#include int main(int argc, char **argv) { if(INTSIZE != sizeof(int)) { diff --git a/test cases/common/37 has header/meson.build b/test cases/common/37 has header/meson.build index bbfce6dc6..ce6e71a38 100644 --- a/test cases/common/37 has header/meson.build +++ b/test cases/common/37 has header/meson.build @@ -1,11 +1,11 @@ -project('has header', 'c') +project('has header', 'c', 'cpp') -cc = meson.get_compiler('c') +foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')] + if comp.has_header('stdio.h') == false + error('Stdio missing.') + endif -if cc.has_header('stdio.h') == false - error('Stdio missing.') -endif - -if cc.has_header('ouagadougou.h') - error('Found non-existant header.') -endif + if comp.has_header('ouagadougou.h') + error('Found non-existant header.') + endif +endforeach diff --git a/test cases/common/39 tryrun/meson.build b/test cases/common/39 tryrun/meson.build index f5d07ab97..c64446ff0 100644 --- a/test cases/common/39 tryrun/meson.build +++ b/test cases/common/39 tryrun/meson.build @@ -1,14 +1,14 @@ -project('tryrun', 'c') +project('tryrun', 'c', 'cpp') # Complex to exercise all code paths. if meson.is_cross_build() if meson.has_exe_wrapper() - cc = meson.get_compiler('c', native : false) + compilers = [meson.get_compiler('c', native : false), meson.get_compiler('cpp', native : false)] else - cc = meson.get_compiler('c', native : true) + compilers = [meson.get_compiler('c', native : true), meson.get_compiler('cpp', native : true)] endif else - cc = meson.get_compiler('c') + compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] endif ok_code = '''#include @@ -32,45 +32,47 @@ INPUTS = [ ['File', files('ok.c'), files('error.c'), files('no_compile.c')], ] -foreach input : INPUTS - type = input[0] - ok = cc.run(input[1], name : type + ' should succeed') - err = cc.run(input[2], name : type + ' should fail') - noc = cc.run(input[3], name : type + ' does not compile') +foreach cc : compilers + foreach input : INPUTS + type = input[0] + ok = cc.run(input[1], name : type + ' should succeed') + err = cc.run(input[2], name : type + ' should fail') + noc = cc.run(input[3], name : type + ' does not compile') - if noc.compiled() - error(type + ' compilation fail test failed.') - else - message(type + ' fail detected properly.') - endif + if noc.compiled() + error(type + ' compilation fail test failed.') + else + message(type + ' fail detected properly.') + endif - if ok.compiled() - message(type + ' compilation worked.') - else - error(type + ' compilation did not work.') - endif + if ok.compiled() + message(type + ' compilation worked.') + else + error(type + ' compilation did not work.') + endif - if ok.returncode() == 0 - message(type + ' return code ok.') - else - error(type + ' return code fail') - endif + if ok.returncode() == 0 + message(type + ' return code ok.') + else + error(type + ' return code fail') + endif - if err.returncode() == 1 - message(type + ' bad return code ok.') - else - error(type + ' bad return code fail.') - endif + if err.returncode() == 1 + message(type + ' bad return code ok.') + else + error(type + ' bad return code fail.') + endif - if ok.stdout().strip() == 'stdout' - message(type + ' stdout ok.') - else - message(type + ' bad stdout.') - endif + if ok.stdout().strip() == 'stdout' + message(type + ' stdout ok.') + else + message(type + ' bad stdout.') + endif - if ok.stderr().strip() == 'stderr' - message(type + ' stderr ok.') - else - message(type + ' bad stderr.') - endif + if ok.stderr().strip() == 'stderr' + message(type + ' stderr ok.') + else + message(type + ' bad stderr.') + endif + endforeach endforeach diff --git a/test cases/common/43 has function/meson.build b/test cases/common/43 has function/meson.build index 00ca640dd..61f96e11e 100644 --- a/test cases/common/43 has function/meson.build +++ b/test cases/common/43 has function/meson.build @@ -1,41 +1,43 @@ -project('has function', 'c') +project('has function', 'c', 'cpp') -cc = meson.get_compiler('c') +compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] -if not cc.has_function('printf', prefix : '#include') - error('"printf" function not found (should always exist).') -endif +foreach cc : compilers + if not cc.has_function('printf', prefix : '#include') + error('"printf" function not found (should always exist).') + endif -# Should also be able to detect it without specifying the header -# We check for a different function here to make sure the result is -# not taken from a cache (ie. the check above) -# On MSVC fprintf is defined as an inline function in the header, so it cannot -# be found without the include. -if cc.get_id() != 'msvc' - assert(cc.has_function('fprintf'), '"fprintf" function not found without include (on !msvc).') -else - assert(cc.has_function('fprintf', prefix : '#include '), '"fprintf" function not found with include (on msvc).') -endif + # Should also be able to detect it without specifying the header + # We check for a different function here to make sure the result is + # not taken from a cache (ie. the check above) + # On MSVC fprintf is defined as an inline function in the header, so it cannot + # be found without the include. + if cc.get_id() != 'msvc' + assert(cc.has_function('fprintf'), '"fprintf" function not found without include (on !msvc).') + else + assert(cc.has_function('fprintf', prefix : '#include '), '"fprintf" function not found with include (on msvc).') + endif -if cc.has_function('hfkerhisadf', prefix : '#include') - error('Found non-existent function "hfkerhisadf".') -endif + if cc.has_function('hfkerhisadf', prefix : '#include') + error('Found non-existent function "hfkerhisadf".') + endif -# With glibc on Linux lchmod is a stub that will always return an error, -# we want to detect that and declare that the function is not available. -# We can't check for the C library used here of course, but if it's not -# implemented in glibc it's probably not implemented in any other 'slimmer' -# C library variants either, so the check should be safe either way hopefully. -if host_machine.system() == 'linux' and cc.get_id() == 'gcc' - assert (cc.has_function('poll', prefix : '#include '), 'couldn\'t detect "poll" when defined by a header') - assert (not cc.has_function('lchmod', prefix : '''#include - #include '''), '"lchmod" check should have failed') -endif + # With glibc on Linux lchmod is a stub that will always return an error, + # we want to detect that and declare that the function is not available. + # We can't check for the C library used here of course, but if it's not + # implemented in glibc it's probably not implemented in any other 'slimmer' + # C library variants either, so the check should be safe either way hopefully. + if host_machine.system() == 'linux' and cc.get_id() == 'gcc' + assert (cc.has_function('poll', prefix : '#include '), 'couldn\'t detect "poll" when defined by a header') + assert (not cc.has_function('lchmod', prefix : '''#include + #include '''), '"lchmod" check should have failed') + endif -# For some functions one needs to define _GNU_SOURCE before including the -# right headers to get them picked up. Make sure we can detect these functions -# as well without any prefix -if cc.has_header_symbol('sys/socket.h', 'recvmmsg', prefix : '#define _GNU_SOURCE') - # We assume that if recvmmsg exists sendmmsg does too - assert (cc.has_function('sendmmsg'), 'Failed to detect function "sendmmsg" (should always exist).') -endif + # For some functions one needs to define _GNU_SOURCE before including the + # right headers to get them picked up. Make sure we can detect these functions + # as well without any prefix + if cc.has_header_symbol('sys/socket.h', 'recvmmsg', prefix : '#define _GNU_SOURCE') + # We assume that if recvmmsg exists sendmmsg does too + assert (cc.has_function('sendmmsg'), 'Failed to detect function "sendmmsg" (should always exist).') + endif +endforeach diff --git a/test cases/common/44 has member/meson.build b/test cases/common/44 has member/meson.build index e60aeb365..4e61956d9 100644 --- a/test cases/common/44 has member/meson.build +++ b/test cases/common/44 has member/meson.build @@ -1,19 +1,21 @@ -project('has member', 'c') +project('has member', 'c', 'cpp') -cc = meson.get_compiler('c') +compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] -if not cc.has_member('struct tm', 'tm_sec', prefix : '#include') - error('Did not detect member of "struct tm" that exists: "tm_sec"') -endif +foreach cc : compilers + if not cc.has_member('struct tm', 'tm_sec', prefix : '#include') + error('Did not detect member of "struct tm" that exists: "tm_sec"') + endif -if cc.has_member('struct tm', 'tm_nonexistent', prefix : '#include') - error('Not existing member "tm_nonexistent" found.') -endif + if cc.has_member('struct tm', 'tm_nonexistent', prefix : '#include') + error('Not existing member "tm_nonexistent" found.') + endif -if not cc.has_members('struct tm', 'tm_sec', 'tm_min', prefix : '#include') - error('Did not detect members of "struct tm" that exist: "tm_sec" "tm_min"') -endif + if not cc.has_members('struct tm', 'tm_sec', 'tm_min', prefix : '#include') + error('Did not detect members of "struct tm" that exist: "tm_sec" "tm_min"') + endif -if cc.has_members('struct tm', 'tm_sec', 'tm_nonexistent2', prefix : '#include') - error('Not existing member "tm_nonexistent2" found.') -endif + if cc.has_members('struct tm', 'tm_sec', 'tm_nonexistent2', prefix : '#include') + error('Not existing member "tm_nonexistent2" found.') + endif +endforeach diff --git a/test cases/common/45 alignment/meson.build b/test cases/common/45 alignment/meson.build index 2ec3f898a..a9bd65b73 100644 --- a/test cases/common/45 alignment/meson.build +++ b/test cases/common/45 alignment/meson.build @@ -1,29 +1,31 @@ -project('alignment', 'c') +project('alignment', 'c', 'cpp') -cc = meson.get_compiler('c') +compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] -# These tests should return the same value on all -# platforms. If (and when) they don't, fix 'em up. -if cc.alignment('char') != 1 - error('Alignment of char misdetected.') -endif +foreach cc : compilers + # These tests should return the same value on all + # platforms. If (and when) they don't, fix 'em up. + if cc.alignment('char') != 1 + error('Alignment of char misdetected.') + endif -ptr_size = cc.sizeof('void*') -dbl_alignment = cc.alignment('double') + ptr_size = cc.sizeof('void*') + dbl_alignment = cc.alignment('double') -# These tests are not thorough. Doing this properly -# would take a lot of work because it is strongly -# platform and compiler dependent. So just check -# that they produce something fairly sane. + # These tests are not thorough. Doing this properly + # would take a lot of work because it is strongly + # platform and compiler dependent. So just check + # that they produce something fairly sane. -if ptr_size == 8 or ptr_size == 4 - message('Size of ptr ok.') -else - error('Size of ptr misdetected.') -endif + if ptr_size == 8 or ptr_size == 4 + message('Size of ptr ok.') + else + error('Size of ptr misdetected.') + endif -if dbl_alignment == 8 or dbl_alignment == 4 - message('Alignment of double ok.') -else - error('Alignment of double misdetected.') -endif + if dbl_alignment == 8 or dbl_alignment == 4 + message('Alignment of double ok.') + else + error('Alignment of double misdetected.') + endif +endforeach diff --git a/test cases/common/83 has type/meson.build b/test cases/common/83 has type/meson.build index 002f1505a..de8dbc834 100644 --- a/test cases/common/83 has type/meson.build +++ b/test cases/common/83 has type/meson.build @@ -1,11 +1,13 @@ -project('has type', 'c') +project('has type', 'c', 'cpp') -cc = meson.get_compiler('c') +compilers = [meson.get_compiler('c'), meson.get_compiler('cpp')] -if not cc.has_type('time_t', prefix : '#include') - error('Did not detect type that exists.') -endif +foreach cc : compilers + if not cc.has_type('time_t', prefix : '#include') + error('Did not detect type that exists.') + endif -if cc.has_type('no_time_t', prefix : '#include') - error('Not existing type found.') -endif + if cc.has_type('no_time_t', prefix : '#include') + error('Not existing type found.') + endif +endforeach From d41b903f07dde2b8330f2fea6b4e7b279e099f4c Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 8 Nov 2016 16:08:50 +0530 Subject: [PATCH 5/8] travis.yml: Don't test for GCC on OS X GCC on OS X is just a wrapper around Clang, so the test results will always be identical. --- .travis.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.travis.yml b/.travis.yml index bc52ffa0b..964c15790 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,6 +18,12 @@ language: services: - docker +matrix: + exclude: + # On OS X gcc is just a wrapper around clang, so don't waste time testing that + - os: osx + compiler: gcc + before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ninja python3; fi From 1e1abc675e703ab82c51da63457b63fbbdfbce70 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 8 Nov 2016 16:19:28 +0530 Subject: [PATCH 6/8] travis.yml: Export CC and CXX inside the docker instance docker does not inherit the parent environment and loses the CC/CXX settings for testing against clang and gcc. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 964c15790..86485728a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,5 +36,5 @@ script: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo FROM jpakkane/mesonci:yakkety > Dockerfile; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo ADD . /root >> Dockerfile; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker build -t withgit .; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true ./run_tests.py -- $MESON_ARGS"; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run withgit /bin/sh -c "cd /root && TRAVIS=true CC=$CC CXX=$CXX ./run_tests.py -- $MESON_ARGS"; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then SDKROOT=$(xcodebuild -version -sdk macosx Path) ./run_tests.py --backend=ninja -- $MESON_ARGS ; fi From f144e50f5ca65ba67c23ff262a79c35a2c444006 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 8 Nov 2016 16:22:40 +0530 Subject: [PATCH 7/8] has_function: Cast to void* instead of int Clang++ doesn't allow that, but void* will always be allowed because lots of projects depend on that. error: cast from pointer to smaller type 'int' loses information --- mesonbuild/compilers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 9b6ad8ca2..53d298aee 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -930,7 +930,7 @@ int main(int argc, char **argv) { head = '#include \n{0}\n' # We don't know what the function takes or returns, so try to use it as # a function pointer - main = '\nint main() {{ int a = (int) &{1}; }}' + main = '\nint main() {{ void *a = (void*) &{1}; }}' return head, main def has_function(self, funcname, prefix, env, extra_args=None, dependencies=None): From 30392a3a8a2f14ee1b3b7e3f66be9728b6a6b52e Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 8 Nov 2016 16:56:36 +0530 Subject: [PATCH 8/8] Inherit VisualStudioCPPCompiler from CPPCompiler Without this our custom C++ has_header_symbol implementation is not used with the Visual Studio C++ compiler. --- mesonbuild/compilers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 53d298aee..5953d043e 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -1883,9 +1883,10 @@ class VisualStudioCCompiler(CCompiler): pdbarr += ['pdb'] return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] -class VisualStudioCPPCompiler(VisualStudioCCompiler): +class VisualStudioCPPCompiler(VisualStudioCCompiler, CPPCompiler): def __init__(self, exelist, version, is_cross, exe_wrap): self.language = 'cpp' + CPPCompiler.__init__(self, exelist, version, is_cross, exe_wrap) VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap) self.base_options = ['b_pch'] # FIXME add lto, pgo and the like