Question

Why am I getting the following linker error when using clang with libc++:

$ clang++ -stdlib=libc++  po.cxx -lpoppler
/tmp/po-QqlXGY.o: In function `main':
po.cxx:(.text+0x33): undefined reference to `Dict::lookup(char*, Object*, std::__1::set<int, std::__1::less<int>, std::__1::allocator<int> >*)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Where:

$ nm -D /usr/lib/x86_64-linux-gnu/libpoppler.so | grep lookup | c++filt| grep \ Dict::lookup\(
00000000000c1870 T Dict::lookup(char*, Object*, std::set<int, std::less<int>, std::allocator<int> >*)

Code is simply:

#include <poppler/PDFDoc.h>

int main()
{
  Dict *infoDict;
  Object obj;
  infoDict->lookup((char*)"key", &obj);
  return 0;
}
Was it helpful?

Solution

According you error, it should be like you're trying to link a libc++ with stdlibc++, the libc++ and stdlibc++ is different, stdlibc++ is gcc's c++ standard library, it will not compatible with each other.

For your issue, it's like your libpoppler.so is using stdlibc++, but in your clang command line, you're trying use libc++ as standard lib, they have different name in linking stage, see link at the end of this answer for detail why.

So, maybe your solution is just change the compile command to

    clang++ -stdlib=libstdc++  po.cxx -lpoppler

Please see this question for detail why std:__1::set and std::set.

Why can't clang with libc++ in c++0x mode link this boost::program_options example?

OTHER TIPS

Because libpoppler.so is linked against GNU stdlibc++. All parts of a single executable have to be linked against the same standard C and the same standard C++ libraries.

The easiest option is to just go with the default standard library. Both are now mostly C++11-complete.

Alternatively you can build version of libpoppler.so against libc++, but you'd have to give it different name so the dynamic linker finds the right one.

In the link error you can see that libpoppler.so refers to std::set and std::less etc., but your objects want to refer to std::__1::set and std::__1::less etc. That is because GNU stdlibc++ and Clang libc++ approach versioning differently.

Because libc++ uses a different namespace from the GNU C++ standard library. This linker error is a good thing because the layout of the two libraries' types are certainly going to be different for some types.

So what this means is that your 'poppler' library built against the GNU C++ std library, which has one set of names -- whereas and the compiler used the declarations in libc++ for the function calls in your program's translation. Thus, the linker looks for symbols in the objects (e.g. the poppler library) which have the libc++ naming for std library declarations, but it does not find them because they were not emitted with the same name -- they probably exist in the poppler library with the GNU names.

Of course, you probably just care how this can be fixed: build both your program and the poppler library using the same standard library. If you cannot build the poppler library, you will have to wait for them to push out a binary which is built against libc++.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top