New compiler method: check_header

This checks not only for existence, but also for usability of the
header, which means it does a full compilation and not just
pre-processing or __has_include.

Fixes https://github.com/mesonbuild/meson/issues/2246
pull/3643/head
Nirbheek Chauhan 7 years ago
parent c87c42b736
commit ff07314a86
  1. 6
      mesonbuild/compilers/c.py
  2. 3
      mesonbuild/compilers/compilers.py
  3. 26
      mesonbuild/interpreter.py
  4. 48
      test cases/common/200 check header/meson.build
  5. 1
      test cases/common/200 check header/ouagadougou.h

@ -266,6 +266,12 @@ 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 check_header(self, hname, prefix, env, extra_args=None, dependencies=None):
fargs = {'prefix': prefix, 'header': hname}
code = '''{prefix}
#include <{header}>'''
return self.compiles(code.format(**fargs), env, extra_args, dependencies)
def has_header(self, hname, prefix, env, extra_args=None, dependencies=None):
fargs = {'prefix': prefix, 'header': hname}
code = '''{prefix}

@ -710,6 +710,9 @@ class Compiler:
def get_option_link_args(self, options):
return []
def check_header(self, *args, **kwargs):
raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())
def has_header(self, *args, **kwargs):
raise EnvironmentException('Language %s does not support header checks.' % self.get_display_language())

@ -843,6 +843,7 @@ class CompilerHolder(InterpreterObject):
'compute_int': self.compute_int_method,
'sizeof': self.sizeof_method,
'get_define': self.get_define_method,
'check_header': self.check_header_method,
'has_header': self.has_header_method,
'has_header_symbol': self.has_header_symbol_method,
'run': self.run_method,
@ -1229,6 +1230,31 @@ class CompilerHolder(InterpreterObject):
mlog.log('Checking if "', mlog.bold(testname), '" links: ', h, sep='')
return result
@permittedKwargs({
'prefix',
'no_builtin_args',
'include_directories',
'args',
'dependencies',
})
def check_header_method(self, args, kwargs):
if len(args) != 1:
raise InterpreterException('check_header method takes exactly one argument.')
check_stringlist(args)
hname = args[0]
prefix = kwargs.get('prefix', '')
if not isinstance(prefix, str):
raise InterpreterException('Prefix argument of has_header must be a string.')
extra_args = self.determine_args(kwargs)
deps = self.determine_dependencies(kwargs)
haz = self.compiler.check_header(hname, prefix, self.environment, extra_args, deps)
if haz:
h = mlog.green('YES')
else:
h = mlog.red('NO')
mlog.log('Check usable header "%s":' % hname, h)
return haz
@permittedKwargs({
'prefix',
'no_builtin_args',

@ -0,0 +1,48 @@
project('check header', 'c', 'cpp')
host_system = host_machine.system()
non_existant_header = 'ouagadougou.h'
# Copy it into the builddir to ensure that it isn't found even if it's there
configure_file(input : non_existant_header,
output : non_existant_header,
copy: true)
fallback = ''
foreach comp : [meson.get_compiler('c'), meson.get_compiler('cpp')]
assert(comp.check_header('stdio.h', prefix : fallback), 'Stdio missing.')
# stdio.h doesn't actually need stdlib.h, but just test that setting the
# prefix does not result in an error.
assert(comp.check_header('stdio.h', prefix : '#include <stdlib.h>' + fallback),
'Stdio missing.')
# Test that check_header behaves differently than has_header. The second
# check without windows.h will fail with check_header.
# We only do this check on MSVC because MinGW often defines its own wrappers
# that pre-include windows.h
if comp.get_id() == 'msvc'
assert(comp.check_header('XInput.h', prefix : '#include <windows.h>' + fallback),
'XInput.h should not be missing on Windows')
assert(not comp.check_header('XInput.h'), 'XInput.h needs windows.h')
endif
# Test that the following GCC bug doesn't happen:
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80005
# https://github.com/mesonbuild/meson/issues/1458
if host_system == 'linux'
assert(comp.check_header('linux/if.h', prefix : fallback),
'Could not find <linux/if.h>')
if comp.has_header('intrin.h', prefix : fallback)
assert(not comp.check_header('intrin.h'),
'intrin.h should not be usable on linux')
endif
endif
# This header exists in the source and the builddir, but we still must not
# find it since we are looking in the system directories.
assert(not comp.check_header(non_existant_header, prefix : fallback),
'Found non-existant header.')
endforeach

@ -0,0 +1 @@
#define OMG_THIS_SHOULDNT_BE_FOUND
Loading…
Cancel
Save