LINUX.ORG.RU

Слинкованная со статическими и динамическими библиотеками прога странно себя ведет


0

0

Есть некая проприетарная программа, которую нужно раздавать в виде бинарников. 95% ее пользователей работают под Ubuntu и Fedora, там проблем нет. Оставшиеся работают на чем угодно: от Pardus до Gentoo. Предполагается, что они получат статически слинкованную версию.

Однако здесь появляются проблемы. После выяснения того факта, что glibc не нужно включать в статический бинарник, было решено собрать нечто вроде полу-статика, то есть включить в состав бинарника статические версии большинства прикладных библиотек. Аналогичным образом собирается skype. В качестве платформы для сборки был выбран Debian-5 (i386), там большинство необходимых библиотек имеется как в .so, так и в .a.

Полученный бинарник был перенесен под Ubuntu-9.10 (i386) чисто с экспериментальными целями. Дальше начались фокусы. Если запустить программу просто так, она падает, выдав сообщение

Gtk-Message: Failed to load module "canberra-gtk-module": libcanberra-gtk-module.so: cannot open shared object file: No such file or directory
Segmentation fault
При этом никаких упоминаний о канберре я в бинарнике не вижу. И библиотека эта в системе есть. Далее, при попытке запустить этот бинарник под отладчиком:
Gtk-Message: Failed to load module "canberra-gtk-module": libcanberra-gtk-module.so: cannot open shared object file: No such file or directory

Program received signal SIGSEGV, Segmentation fault.
0x00535645 in xcb_writev () from /usr/lib/libxcb.so.1
Интересно, что libxcb была включена при линковке как статическая. Значит, при запуске происходит то же, что и с glibc - то есть, статическая glibc внутри бинарника не получает управления, вместо этого всё равно вызывается имеющаяся в системе динамическая glibc. Разумеется, мне стало интересно, кто же вызвал динамическую libxcb. Однако тут меня ждал сюрприз. Программа запускается и нормально работает, будучи вызвана из-под ltrace или strace! Причем в их диагностике нет ни слова о канберре и libxcb — похоже, на этот раз вызвался статик.

Собственно, вопросы. Расскажите, вдруг кто-нибудь знает о таком эффекте — почему он происходит (характер «подземного стука» вроде описал). Ну и как бороться, собственно...

«Gtk-Message: » как бэ говорит нам, что оно пытается загрузить библиотеку через dlopen, на всякий случай.

А что пишет ldd?

anonymous
()

Да, если что-то загружалось через dlopen, то и зависимости будут подтянуты, отсюда libxcb.so может и появится.

anonymous
()

> статическая glibc внутри бинарника

glibc вообще-то не из одной библиотеки состоит - их там минимум пара десятков

Разумеется, мне стало интересно, кто же вызвал динамическую libxcb


команда ldd вам поможет

ahonimous
()
Ответ на: комментарий от anonymous

Вроде всё нормально с ldd (это уже на неродной системе):

        linux-gate.so.1 =>  (0xb76ef000)
        libdl.so.2 => /lib/tls/i686/cmov/libdl.so.2 (0xb76d7000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xb75e8000)
        libm.so.6 => /lib/tls/i686/cmov/libm.so.6 (0xb75c1000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0xb75b2000)
        libc.so.6 => /lib/tls/i686/cmov/libc.so.6 (0xb744f000)
        /lib/ld-linux.so.2 (0xb76f0000)

sweeper
() автор топика
Ответ на: комментарий от ahonimous

GTK версии 2.12.12-1 (родная для Deb-5) собиралась статически со следующими параметрами:

#!/bin/sh

./configure \
    --prefix=/opt/gnome \
    --enable-static=yes \
    --enable-shared=no \
    --disable-gtk-doc \
    --disable-modules \
    --with-x --with-included-loaders=png,jpeg,tiff,xpm
Собиралась, да не собралась... Хотя libgtk-x11-2.0.a и .la и появились в /opt/gnome/lib, они отличаются от тех, что были в gtk/.libs. Но это, наверное, нормально. хуже другое. Вот строчка из .la:
dependency_libs=' /opt/gnome/lib/libgdk-x11-2.0.la -lfontconfig -lXext -lXrender -lXinerama -lXrandr -lXcursor /opt/gnome/lib/libgdk_pixbuf-2.0.la /usr/lib/libpangocairo-1.0.la /usr/lib/libpango-1.0.la -lX11 -lXcomposite -lXdamage -lXfixes /usr/lib/libatk-1.0.la /usr/lib/libgobject-2.0.la /usr/lib/libgmodule-2.0.la -ldl /usr/lib/libglib-2.0.la /usr/lib/libcairo.la /usr/lib/libtiff.
la -ljpeg -lz -lc /usr/lib/libjpeg.la -lpng12 -lm'

Что-то мне подсказывает, что всё, что начинается с '-l', будет динамиком... Нет?

sweeper
() автор топика
Ответ на: комментарий от sweeper

[quote]Что-то мне подсказывает, что всё, что начинается с '-l', будет динамиком...[/quote] Нет, если это статические библиотеки. Однако если вдруг найдутся два варианта в разных директориях - статический и динамический, то я не знаю, что выберет компилятор.

master1312
()
Ответ на: комментарий от master1312

>Однако если вдруг найдутся два варианта в разных директориях - статический и динамический, то я не знаю, что выберет компилятор.

Выберет динамический скорее всего, у него приоритет намного выше.

Lucky1 ★★★
()
Ответ на: комментарий от sweeper

Что-то мне подсказывает, что всё, что начинается с '-l', будет динамиком... Нет?

Если бы это было так, ldd показал бы зависимости.

anonymous
()

Я в похожей ситуации (проприетарная прога, распространяемая в виде бинарников, с гуём на gtk/gtkmm) линковал так: статически - все плюсовые библиотеки (включая libstdc++) (ибо у них менее стабильный ABI и всякие -mm обёртки далеко не во всех дистрибутивах ставятся по дефолту), а также gcc-спцифичные библиотеки (gcc_eh, gcc). Всё остальное, включая сам gtk и его зависимости линковал динамически. Проблема в том, что gtk много чего грузит в рантайме через dlopen, соответственно, полностью слинковать статически с gtk невозможно без суровой обработки его напильником. Но у gtk очень хорошая обратная бинарная совместимость, поэтому динамическая линковка с ним налагает только дополнительное требование на наличие в системе gtk весии не менее X.

Частичная статическая линковка делается так:

gcc -Laaa -Lbbb -Wl,-Bstatic -lstatic1 -lstatic2... -Wl,-Bdynamic -ldynamic1 -ldynamic2 ...

Библиотеки после -Wl,-Bstatic и до -Wl,-Bdynamic будут прилинкованы статически, остальные - динамически. Этот способ лучше чем явное указание a/la файлов (la, тем более, не во всех дистрибутивах сейчас устанавливаются), т. к. его легче интегрировать в систему сборки и использовать pkg_config для определения флагов линковки.

Полезно анализировать результат линковки с помощью ldd.

Альтернативный подход - сложить все нужные библиотеки в отдельный каталог и с помощью переменных окружения (LD_LIBRARY_PATH плюс переменные окружения, определяющие путь к gtk-шным модулям) заставить грузить их оттуда а не из системы.

slav ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.