Динамическое связывание библиотеки - успешно при сборке исполняемого файла, такая же настройка завершается неудачно при создании другого .so - PullRequest
1 голос
/ 28 июля 2010

Я пишу числовой код, в котором я хотел бы использовать стороннюю написанную общую библиотеку. Я работаю над архитектурой x86_64 k8 под CentOS. Желаемой целью, которую я хотел бы построить, был бы модуль расширения Python или Matlab, которые, как я понимаю, представляют собой динамически связанные библиотеки, созданные с помощью gcc, с дополнительными встроенными скаффолдами Matlab / Python. Я сосредоточусь здесь, на Python, возникает та же проблема, и она, вероятно, более знакома сообществу.

Разработчик библиотеки изначально предоставил мне динамическую библиотеку и некоторый тестовый код, написанный на C ++. Вот как он собирался распространять свою библиотеку. Я должен отметить, что я стараюсь обременить первоначального разработчика как можно меньше, поскольку библиотека, вероятно, была для него сторонним проектом некоторое время назад, и его тестовый код в итоге работает нормально. Поэтому я пытаюсь решить проблемы с моей стороны в максимально возможной степени с моей стороны. Мне удалось встроить его примеры в исполняемые файлы, только с помощью gcc 4.5.0. Обычная версия gcc, которую я использую, 4.1.2, выдает четыре «неопределенных ссылки на» ошибки во время компоновки (с g ++), в частности, _M_insert<long>(long), _M_widen_init(), _M_insert<double>(double) и __ostream_insert<char, std::char_traits<char> >. Все они являются частью пространства имен std. Компиляция с g ++ 4.5.0 разрешила эти неопределенные ссылки, и примеры исполняемых файлов работают правильно. В комментарии Е.Р. readelf -x.comment libmaxent_k8.so указано, что исходные библиотеки были собраны с помощью gcc 4.4.1.

Чтобы проверить, работает ли связь с расширением Python, я построил небольшую функцию расширения Python в C ++, которая просто добавляет два числа. В частности, он не использует ничего из библиотеки, которую я хотел бы использовать. Интерфейс был сгенерирован SWIG 2.0, скомпилирован с g ++ 4.50. и код отлично работает в Python 2.4.3. Однако, когда я пытаюсь связаться с исходной библиотекой, не ссылаясь ни на какие символы из нее, код снова связывается нормально, но затем во время выполнения, при импорте расширения, я получаю ImportError: libmaxent_k8.so: undefined symbol: _ZNSo9_M_insertIlEERSoT_, который, по c++filt, равен _M_insert(long), который является одним из оригинальных, которые не были определены, когда код C ++ был связан с использованием g ++ 4.1.2.

Я подозреваю, что проблема связана с несовпадающими версиями libstdc ++ во время компоновки и работы Python, но я не знаю, как решить эту проблему. Лучший сценарий для меня позволил бы мне как-то обойтись без gcc 4.5.0 при связывании расширений, возможно, я забегал вперед при решении исходной проблемы с 4 отсутствующими ссылками. Может ли проблема быть решена путем статического связывания bing с статической связью с libstdc ++ 6.0.14 (которая является частью gcc 4.5.0), при этом сохраняя их характер как динамически связанных библиотек? Хотя у Python нет проблем с взаимодействием с gcc 4.5.0, Matlab делает, и их поддержка требует надежности только до gcc 4.2.0. По этой причине я хотел бы как можно меньше избегать компиляции с 4.5.0. Мой gcc поставляется с 6.0.8 версией libstdc ++.

Вот несколько отчетов по рассматриваемой библиотеке. Помните, что, несмотря на все эти ссылки, код работал при компиляции непосредственно в исполняемый файл.

$ readelf -aD /home/mbudisic/lib64/libmaxent_k8.so | grep NEEDED
0x0000000000000001 (NEEDED)             Shared library: [libgcc_s.so.1]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]

$ ldd -d libmaxent_k8.so 
undefined symbol: _ZSt4cerr (./libmaxent_k8.so)
undefined symbol: _ZNSt8ios_base4InitD1Ev   (./libmaxent_k8.so)
undefined symbol: _ZSt4cout (./libmaxent_k8.so)
undefined symbol: __gxx_personality_v0  (./libmaxent_k8.so)
    libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002b92457f3000)
    libc.so.6 => /lib64/libc.so.6 (0x00002b9245a01000)
    /lib64/ld-linux-x86-64.so.2 (0x000000366e200000)

Запуск nm -uC libmaxent_k8.so приводит к 35 символам, помеченным буквой «U», и двум символам, помеченным буквой «w», из библиотек libm и libstdc ++, что гораздо больше, чем указано как неопределенное при компоновке / запуске.

Ответы [ 2 ]

2 голосов
/ 29 июля 2010

В общем, glibc и libstdc ++ пытаются обеспечить обратную совместимость - двоичный файл, созданный на более старой системе (или с более старой GCC), продолжает работать на более новой системе.

И наоборот: запуск двоичного файла, связанного с glibc-2.10 в системе glibc-2.5, или запуск двоичного файла, созданного с помощью GCC-4.4, с libstdc ++, поставляемой с GCC-4.2, не является целью.

Следовательно, вы должны либо запросить двоичные файлы, созданные с использованием самого старого GCC, который вы хотите поддерживать (4.2 в вашем случае), либо договориться об использовании нового libstdc ++ (изменив LD_LIBRARY_PATH или используя LD_PRELOAD) для Matlab и Python.

Обратная совместимость glibc очень хорошая, но libstdc ++ имеет более точную запись; поэтому утверждение Матлаба о том, что только libstdc ++. so.6.0.8 стабильна и поддерживается, вполне может быть верным. Вам просто нужно попробовать, так как (если вы не построите libmaxent_k8.so с GCC-4.2), у вас нет других вариантов (которые я могу придумать).

1 голос
/ 28 июля 2010

Вот очень хорошая статья о том, почему статическое связывание libstc ++ может быть не очень хорошей идеей:

http://www.trilithium.com/johan/2005/06/static-libstdc/

...