How do I check for an unmangled C++ symbol when building a PHP extension?
-
18-09-2019 - |
Question
I have a PHP module written in C++, which relies on a C++ library (Boost Date_Time) being installed.
Currently, in my config.m4 file I'm checking for the library as follows:
LIBNAME=boost_date_time
LIBSYMBOL=_ZN5boost9gregorian9bad_monthD0Ev
PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,,
[
AC_MSG_ERROR([lib $LIBNAME not found. Try: sudo apt-get install libboost-dev])
],[
-lstdc++ -ldl
])
Now, this works in my current environment, but I'm painfully aware this will probably break on a different version of the library or compiler.
How can I get automake to understand the non-mangled C++ symbol?
Edit:
I realise that checking on the mangled name is horrible, but is there not some way of checking for the symbol name as returned by "nm -C" (eg boost::gregorian::bad_month etc).
I found some refence to the automake command AC_LANG_CPLUSPLUS(), but I'm not sure how to use it and whether it's applicable here.
Solution
You can check AC_TRY_COMPILE
with something like that:
LIBNAME=boost_date_time
AC_MSG_CHECKING([for BOOST])
AC_TRY_COMPILE(
[
#include "boost/date_time/gregorian/greg_month.hpp"
],
[
boost::gregorian::bad_month* bm = new boost::gregorian::bad_month;
],
[
AC_MSG_RESULT(yes)
],
[
AC_MSG_ERROR([lib $LIBNAME not found. Try: sudo apt-get install libboost-dev])
])
This avoid the use of unmangled symbol.
OTHER TIPS
Outside of the environment of a particular C++ compiler, there is no "non-mangled C++ symbol" - the mangling is done precisely to provide a unique name to external tools, such as linkers and librarians.
This is a terrible idea -- to have mangled symbols out in the open. Why'd you need this in the first place?
Having seen your update, I'd have to ask, why not use a custom rule to invoke nm
and get this information and make this rule to be passed as a requirement? I would be very surprised if autoconf
was to provide a direct command to check object files for symbols.
You need to provide a set of C++ wrappers for the Boost api functions that you wish to invoke. These wrappers need to be declared with extern "C"
, as in:
extern "C"
void foo(int bar)
{
...
}
Your PHP code should use these wrappers, rather than trying to directly call C++ methods.
EDIT: Since you're assuming the availability of automake
, you're probably planning to compile the Boost library as part of the install. This gives you the option of probing the result of the name mangling. Try creating a test C++ program along these lines. Note that this only needs to compile; it doesn't need to produce a valid result.
#include "boost/date_time/gregorian/greg_month.hpp"
int main( int argc, const char* argv[] )
{
boost::gregorian::bad_month* xxxjunk = new boost::gregorian::bad_month;
return 0;
}
In your automake, you'd want to compile this, then run the output through
nm -C | grep "boost::gregorian::bad_month"
Depending on your needs and pickiness, you might want to further refine the grep
command to look for the string "typeinfo for boost::gregorian::bad_month
" (note that this further increases your dependency on the specific compiler implementation.)