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
pull/1006/head
Nirbheek Chauhan 8 years ago
parent 87f07cdf3d
commit f6dfd36239
  1. 37
      mesonbuild/compilers.py
  2. 23
      test cases/common/111 has header symbol/meson.build

@ -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'

@ -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

Loading…
Cancel
Save