1

I'm trying to link against a 3rd party library that uses Boost. I've linked against the correct boost library (libboost_program_options.a), but still not finding it.

The error msg (formatted a bit for clarity):

undefined reference to `boost::program_options::validate(boost::any&, 
                              std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > > const&, 
                              std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, 
                              int)'

nm --demangle libboost_program_options.a | grep validate

boost::program_options::validate(boost::any&,                                   std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > const&, 
                                  bool*, 
                                  int)
 boost::program_options::validate(boost::any&, 
                                  std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > const&, 
                                  std::string*, 
                                  int)
 boost::program_options::validate(boost::any&, 
                                  std::vector<std::string, std::allocator<std::string> > const&, 
                                  bool*, 
                                  int)
 boost::program_options::validate(boost::any&, 
                                  std::vector<std::string, std::allocator<std::string> > const&, 
                                  std::string*, 
                                  int)

The second record looks similar, but apparently not close enough. Any idea how I can compile Boost to get a signature that matches what's in the library? I have a request out to the library owner to see what version of Boost they're using and such, but haven't heard back yet.

This is on a CentOS 7 box, which uses g++ version 4.8.5. But the library I'm tryng to link against uses C++11 heavily and was compiled with g++ v 6.1, so I installed devtoolset-6 which gives me a g++ 6 environment (g++ version 6.3.1)

I downloaded and built Boost from scratch (v1.65.1) so that it's built with the same compiler, rather then the system version.

Edit... I think John Zwinck is on the right track, but I can't get the boost library to compile to the new ABI.

The validate() functions are found in value_semantic.cpp

Stripping the build down to the basics, and adding the flags discussed:

g++ -std=c++11 -D_GLIBCXX_USE_CXX11_ABI -c -o test.o libs/program_options/src/value_semantic.cpp

nm --demangle test.o | grep validate
00000000000008b6 T boost::program_options::validate(boost::any&, std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > const&, bool*, int)
0000000000000c02 T boost::program_options::validate(boost::any&, std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > > const&, std::string*, int)
00000000000005f2 T boost::program_options::validate(boost::any&, std::vector<std::string, std::allocator<std::string> > const&, bool*, int)
0000000000000b9a T boost::program_options::validate(boost::any&, std::vector<std::string, std::allocator<std::string> > const&, std::string*, int)

Does the _GLIBCXX_USE_CXX11_ABI macro only work with gcc 5.1?

CoAstroGeek
  • 277
  • 1
  • 13
  • 1
    Have you tried using `g++ -std=c++11` for your build of boost? – burlyearly Nov 10 '17 at 22:44
  • No - as far as I know, c++11 is the default for g++ v6. I was thinking about that though - have to see how to get that into the Boost build system. – CoAstroGeek Nov 10 '17 at 22:53
  • 1
    Just looked c++14 is the default for gcc v6 https://gcc.gnu.org/projects/cxx-status.html#cxx11 – CoAstroGeek Nov 10 '17 at 22:55
  • Show us the full command you use for linking (i.e. the command that fails). – John Zwinck Nov 11 '17 at 02:31
  • @CoAstroGeek: First, _GLIBCXX_USE_CXX11_ABI is supposed to be defined to 0 if you want it to have some effect. Second, it only has effect with GCC 5 or later. It is effectively always 0 in GCC 4.x. – John Zwinck Nov 15 '17 at 08:08
  • Yea, I tried setting it, setting it to 0, 1, etc. No change to the signature. I'm using gcc 6.3.1 – CoAstroGeek Nov 15 '17 at 15:58

3 Answers3

3

It appears you have run afoul of the GCC Dual ABI for std::string in C++11: https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html

Your program is trying to link against an API using

std::__cxx11::basic_string<char>* 

But your Boost library has

std::basic_string<char>*

This implies that your Boost library was built with GCC older than 5.1, or with the new ABI turned off. In either case, you can compile your own code with the new ABI turned off by adding this compiler flag:

-D_GLIBCXX_USE_CXX11_ABI=0

By compiling your program with that, it will be possible to use the system-provided (old ABI) Boost libraries. But then the question will be which C++ ABI your vendor compiled their code with (ask them, or look for __cxx11 in their library).

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
  • I think this is on the right track, but I still can't get my build to match the 3rd party library ABI - see edit above. Thanks! – CoAstroGeek Nov 15 '17 at 06:32
1

As explained at https://stackoverflow.com/a/52611576/981959 you can't use the new cxx11 ABI in the devtoolset version of GCC (because the whole point of the devtoolset GCC is to remain compatible with the system libstdc++'s ABI).

Your options are to either:

  • get a new version of the third-party library that uses the gcc4-compatible ABI, so you can link to it using the devtoolset compiler; or
  • build and install a newer GCC yourself, use that instead of the devtoolset GCC, and ensure that the new libstdc++.so gets used at runtime.
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
0

Ok, I think I've figured out why I can't get g++ to generate the cxx11 signature (new ABI).

If I run g++ with the -v option:

g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/opt/rh/devtoolset-6/root/usr/libexec/gcc/x86_64-redhat-linux/6.3.1/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,fortran,lto --prefix=/opt/rh/devtoolset-6/root/usr --mandir=/opt/rh/devtoolset-6/root/usr/share/man --infodir=/opt/rh/devtoolset-6/root/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --enable-plugin --with-linker-hash-style=gnu --enable-initfini-array --disable-libgcj --with-default-libstdcxx-abi=gcc4-compatible --with-isl=/builddir/build/BUILD/gcc-6.3.1-20170216/obj-x86_64-redhat-linux/isl-install --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 6.3.1 20170216 (Red Hat 6.3.1-3) (GCC)

Note the following under the "configured with" field

--with-default-libstdcxx-abi=gcc4-compatible

What I believe this means is that the devtoolset-6 version of g++ is built with the old style ABI "baked in", and it therefore doesn't respond to the _GLIBCXX_USE_CXX11_ABI macro.

According to this link: https://gcc.gnu.org/onlinedocs/libstdc++/manual/configure.html

--with-default-libstdcxx-abi=OPTION Set the default value for the _GLIBCXX_USE_CXX11_ABI macro (see Macros). The default is OPTION=new which sets the macro to 1, use OPTION=gcc4-compatible to set it to 0. This option does not change the library ABI.

It would seem to only change the default value of _GLIBCXX_USE_CXX11_ABI, but in my attempts setting _GLIBCXX_USE_CXX11_ABI doesn't have any effect.

Not positive of this, but it's my working theory for now. Any additional insight is appreciated.

CoAstroGeek
  • 277
  • 1
  • 13
  • 1
    As the name suggests, `--with-default-libstdcxx-abi=gcc4-compatible` only affects the _default_ ABI, it doesn't prevent you changing it with the `_GLIBCXX_USE_CXX11_ABI` macro. So that configure option isn't the problem, the problem is that [in devtoolset changing the ABI via the macro is not supported](https://stackoverflow.com/a/50459937/981959) – Jonathan Wakely Oct 02 '18 at 16:01