clang++ -stdlib=libc++ приводит к неопределенной ссылке

Почему я получаю следующую ошибку компоновщика при использовании clang с 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)

Где:

$ 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> >*)

Код просто:

#include <poppler/PDFDoc.h>

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

person malat    schedule 27.08.2013    source источник


Ответы (3)


Согласно вашей ошибке, это должно быть похоже на то, что вы пытаетесь связать libС++ с stdlibС++, libС++ и stdlibС++ разные, stdlibС++ - это стандартная библиотека gcc С++, она не будет совместима друг с другом.

Для вашей проблемы это похоже на то, что ваш libpoppler.so использует stdlibc++, но в вашей командной строке clang вы пытаетесь использовать libc++ в качестве стандартной библиотеки, у них другое имя на этапе связывания, см. ссылку в конце этого ответа, чтобы узнать, почему .

Итак, возможно, ваше решение - просто изменить команду компиляции на

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

Подробнее см. в этом вопросе, почему std:__1::set и std::set.

Почему нельзя лязгнуть с libc++ в режиме c++0x связывает этот пример boost::program_options?

person Jiejing Zhang    schedule 27.08.2013

Поскольку libpoppler.so связан с GNU stdlibc++. Все части одного исполняемого файла должны быть связаны с одним и тем же стандартным C и одними и теми же стандартными библиотеками C++.

Самый простой вариант — просто использовать стандартную библиотеку по умолчанию. Оба теперь в основном C++11-complete.

В качестве альтернативы вы можете создать версию libpoppler.so против libc++, но вам нужно будет дать ей другое имя, чтобы динамический компоновщик нашел правильное.

В ошибке ссылки вы можете видеть, что libpoppler.so относится к std::set и std::less и т. д., но ваши объекты хотят ссылаться на std::__1::set и std::__1::less и т. д. Это потому, что GNU stdlibc++ и Clang libc++ по-разному подходят к управлению версиями.

person Jan Hudec    schedule 27.08.2013

Потому что libc++ использует пространство имен, отличное от стандартной библиотеки GNU C++. Эта ошибка компоновщика является хорошей вещью, потому что расположение типов двух библиотек, безусловно, будет отличаться для некоторых типов.

Итак, это означает, что ваша библиотека poppler построена на основе стандартной библиотеки GNU C++, которая имеет один набор имен, тогда как компилятор использовал объявления в libc++ для вызовов функций в переводе вашей программы. Таким образом, компоновщик ищет символы в объектах (например, в библиотеке poppler), которые имеют имена libc++ для объявлений стандартной библиотеки, но не находит их, потому что они не были выпущены с тем же именем — они, вероятно, существуют в библиотеке poppler. с именами GNU.

Конечно, вы, вероятно, просто заботитесь о том, как это можно исправить: соберите и свою программу, и библиотеку poppler, используя одну и ту же стандартную библиотеку. Если вы не можете собрать библиотеку poppler, вам придется подождать, пока они выпустят бинарный файл, созданный для libc++.

person justin    schedule 27.08.2013