From 2300c022c24d12f1bf2f41171dc97ea9b318a9ce Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 4 May 2016 00:15:37 +0530 Subject: [PATCH 1/2] has_function: Also detect function implementations inside headers This also detects when the header has re-defined the symbol to something else that is then provided by libc, which is also a case we want to support. --- mesonbuild/compilers.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index a320e7d30..d0950ef34 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -680,6 +680,13 @@ int main(int argc, char **argv) { return align def has_function(self, funcname, prefix, env, extra_args=[]): + """ + First, this function looks for the symbol in the default libraries + provided by the compiler (stdlib + a few others usually). If that + fails, it checks if any of the headers specified in the prefix provide + an implementation of the function, and if that fails, it checks if it's + implemented as a compiler-builtin. + """ # Define the symbol to something else in case it is defined by the # includes or defines listed by the user `{0}` or by the compiler. # Then, undef the symbol to get rid of it completely. @@ -725,12 +732,17 @@ int main(int argc, char **argv) { raise EnvironmentException('Cross variable {0} is not a boolean.'.format(varname)) if self.links(templ.format(prefix, funcname), extra_args): return True + # Add -O0 to ensure that the symbol isn't optimized away by the compiler + extra_args += self.get_no_optimization_args() + # Sometimes the implementation is provided by the header, or the header + # redefines the symbol to be something else. In that case, we want to + # still detect the function. + if self.links('{0}\nint main() {{ {1}; }}'.format(prefix, funcname), extra_args): + 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(). - # Add -O0 to ensure that the symbol isn't optimized away by the compiler - extra_args += self.get_no_optimization_args() return self.links('int main() {{ {0}; }}'.format('__builtin_' + funcname), extra_args) def has_member(self, typename, membername, prefix, extra_args=[]): From 0ac33b885727180b071fa091c34ef56d00b80ceb Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 4 May 2016 00:16:53 +0530 Subject: [PATCH 2/2] tests/common/43: Better, more descriptive error messages --- test cases/common/43 has function/meson.build | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test cases/common/43 has function/meson.build b/test cases/common/43 has function/meson.build index 3736a3db6..c7fe35333 100644 --- a/test cases/common/43 has function/meson.build +++ b/test cases/common/43 has function/meson.build @@ -3,16 +3,16 @@ project('has function', 'c') cc = meson.get_compiler('c') if not cc.has_function('printf', prefix : '#include') - error('Existing function not found.') + 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) -assert(cc.has_function('fprintf'), 'Existing function not found without include') +assert(cc.has_function('fprintf'), '"fprintf" function not found without include (should always exist).') if cc.has_function('hfkerhisadf', prefix : '#include') - error('Found non-existant function.') + error('Found non-existent function "hfkerhisadf".') endif # With glibc on Linux lchmod is a stub that will always return an error, @@ -21,9 +21,9 @@ endif # 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 (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') + #include '''), '"lchmod" check should have failed') endif # For some functions one needs to define _GNU_SOURCE before including the @@ -31,5 +31,5 @@ endif # 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 existing function') + assert (cc.has_function('sendmmsg'), 'Failed to detect function "sendmmsg" (should always exist).') endif