diff --git a/demos/c++/wscript b/demos/c++/wscript index 5115c000..b440e0ad 100644 --- a/demos/c++/wscript +++ b/demos/c++/wscript @@ -16,6 +16,7 @@ def options(opt): def configure(conf): conf.load('compiler_cxx') conf.check(header_name='stdio.h', features='cxx cxxprogram', mandatory=False) + conf.check_cxx_decl('memcpy(void *, const void *, size_t)', header_name='string.h') conf.check_cxx_func('memcpy') def build(bld): diff --git a/demos/c/wscript b/demos/c/wscript index d0fa6fdf..fe67fe05 100644 --- a/demos/c/wscript +++ b/demos/c/wscript @@ -41,6 +41,7 @@ def configure(conf): conf.check(lib='m', cflags='-Wall', defines=['var=foo', 'x=y'], uselib_store='M', mandatory=False) conf.check_large_file(mandatory=False) conf.check_inline() + conf.check_c_decl('memcpy(void *, const void *, size_t)', header_name='string.h') conf.check_c_func('memcpy') endianness = conf.check_endianness() diff --git a/docs/sphinx/confmap.rst b/docs/sphinx/confmap.rst index b34d2c98..0a58577f 100644 --- a/docs/sphinx/confmap.rst +++ b/docs/sphinx/confmap.rst @@ -33,6 +33,10 @@ Configuration methods * check_ +.. _check_c_decl: tools/c_config.html#waflib.Tools.c_config.check_c_decl + +* check_c_decl_ + .. _check_c_func: tools/c_config.html#waflib.Tools.c_config.check_c_func * check_c_func_ @@ -49,6 +53,10 @@ Configuration methods * check_cxx_ +.. _check_cxx_decl: tools/c_config.html#waflib.Tools.c_config.check_cxx_decl + +* check_cxx_decl_ + .. _check_cxx_func: tools/c_config.html#waflib.Tools.c_config.check_cxx_func * check_cxx_func_ diff --git a/waflib/Tools/c_config.py b/waflib/Tools/c_config.py index 9f0a49e4..7e9e4cce 100644 --- a/waflib/Tools/c_config.py +++ b/waflib/Tools/c_config.py @@ -732,6 +732,74 @@ def check_cc(self, *k, **kw): kw['compiler'] = 'c' return self.check(*k, **kw) +def check_decl(symbol_name, **kw): + name = re.sub(r' *\(.*', '', symbol_name) + call = re.sub(r',', ')0, (', symbol_name.replace('(', '((').replace(')', ')0)')) + header = '' + if 'header_name' in kw: + header += to_header(Utils.to_list(kw['header_name'])) + '\n' + kw['define_name'] = 'HAVE_DECL_' + name.upper() + kw['fragment'] = header + \ + 'int main(int argc, char **argv) {\n' + \ + ' (void)argc; (void)argv;\n' + \ + '#ifndef ' + name + '\n' + \ + '#ifdef __cplusplus\n' + \ + ' (void)' + call + ';\n' + \ + '#else\n' + \ + ' (void)' + name + ';\n' + \ + '#endif\n' + \ + '#endif\n' + \ + ' return 0;\n' + \ + '}\n' + kw['msg'] = 'Checking whether ' + name + ' is declared' + return kw; + +@conf +def check_cxx_decl(self, symbol_name, *k, **kw): + """ + Checks whether ``symbol_name`` is declared. Optionally, use the + ``header_name`` parameter to specify one or more header files providing + the declaration. This check is similar to the Autoconf + AC_CHECK_DECLS() macro. Compiles a test program to check whether + ``symbol_name`` is defined as a macro or can be used as an rvalue using + the C++ compiler. Optionally, you can specify function parameter types + to account for overloaded function declarations. The function + parameter types must allow an initialization with zero (0), e.g. + ``memcpy(void *, const void *, size_t)``. Defines + ``HAVE_DECL_SYMBOL_NAME`` to 1 in the configuration header if the check + was successful, otherwise it is not defined. This function sets the + ``compiler``, ``define_name``, ``features``, ``fragment``, and ``msg`` + parameters and then calls :py:func:`waflib.Tools.c_config.check` to + carry out the check. + + :param symbol_name: the name of the symbol to check + :type symbol_name: string + """ + kw = check_decl(symbol_name, **kw) + kw['features'] = 'cxx' + return self.check_cxx(*k, **kw) + +@conf +def check_c_decl(self, symbol_name, *k, **kw): + """ + Checks whether ``symbol_name`` is declared. Optionally, use the + ``header_name`` parameter to specify one or more header files providing + the declaration. This check is similar to the Autoconf + AC_CHECK_DECLS() macro. Compiles a test program to check whether + ``symbol_name`` is defined as a macro or can be used as an rvalue using + the C compiler. Defines ``HAVE_DECL_SYMBOL_NAME`` to 1 in the + configuration header if the check was successful, otherwise it is not + defined. This function sets the ``compiler``, ``define_name``, + ``features``, ``fragment``, and ``msg`` parameters and then calls + :py:func:`waflib.Tools.c_config.check` to carry out the check. + + :param symbol_name: the name of the symbol to check + :type symbol_name: string + """ + kw = check_decl(symbol_name, **kw) + kw['features'] = 'c' + return self.check_cc(*k, **kw) + def check_func(function_name, **kw): kw['define_name'] = 'HAVE_' + function_name.upper() kw['fragment'] = CHECK_FUNC_FRAGMENT.replace('func', function_name)