LINUX.ORG.RU

Статическая линковка


0

0

Добрый день... помогите пожалуйста разобраться со статической линковкой....

прочел в форуме кучу топиков но окончательного ответа не получил... отдельно спасибо тому кто написал про "программу работающую на любых дистрибутивах"..

спасибо кто отвечал в предидущих моих постах.

Опять же программа написана на С. используется ncurses. Собираю проект в SlickEdit 11

Собрал glibc с ключем --enable-nss.

получил статические(*.a) файлы libc, libncurses, llibnss_files и т.д. чтобы получилось слинковать с ключем

-static -lc -lnss_files -lnss_dns -lresolv

все получил.. замечательно.. размер бинарника выорос до 2.8 мб с 300 кб при динамической линковке.

При запуске на другой линуксовой машине получаю Kernel too old.

но получаю Segmentation fault. ну вот ты тресни:(((

в буквах запутался....

При запуске на другой линуксовой машине уже не получаю Kernel too old, а получаю Segmentation fault. ну вот ты тресни:(((

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

>может лучше библиотеки libc и др. поставлять в одной папке с программой, а не вкомпиливать в неё?

т.е. положить статически собранные библиотеки? а они с собой ничего другого тянуть не будут?

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

> получаю Segmentation fault

Для начала - strace.

Если ничего путного не будет, собираешь программу с -g и запускаешь gdb.

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

оки.. этоя завтр сделаю.... но меня мучает вопрос:

почему один и тот же код ведет себя абсолютно по разному наразличных дистрибутивах?

на девелоперсокй машине эта программа работает отлично.. без всяких нареканий...

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

попытка собрать обьектники, чтобы линковать на тестовой машине сваливает в тот же самый Segmentation fault.

ak_mish
() автор топика

Между версией ядра и версией glibc существует достаточно тесная связь. Если glibc прилинковать статически, то неизбежно появятся системы, на которых программа работать не будет, причем они м.б. как более новые, так и более старые, чем та, на которой выполнялась сборка. Полученный результат кажется вполне закономерным следствием статической линковки glibc.

По поводу человека, советовавшего все линковать статически для повышения портабельности, я ничего плохого сказать не могу, а вот сама идея абсолютно вредоносная. Почитай лучше вот это http://www.usenix.org/publications/library/proceedings/als00/2000papers/paper...

Тут недавно выступал гражданин с "советом" все линковать статически, которого дружно, справедливо и довольно аргументировано осмеяли. Посмейся и ты http://www.linux.org.ru/jump-message.jsp?msgid=1543485

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

>Между версией ядра и версией glibc существует достаточно тесная >связь. Если glibc прилинковать статически, то неизбежно появятся >системы, на которых программа работать не будет, причем они м.б. как >более новые, так и более старые, чем та, на которой выполнялась >сборка. Полученный результат кажется вполне закономерным следствием >статической линковки glibc

Сама идея линковать все статически мне и самому кажется жуткой.. но просто я не вижу другого способа обеспечивать переносимость программы.. Пока получается несколько способов, только не понятно какие из них работают, а какие нет..

1. Четко определить версии kernel + glibc собрать для них динамический проект и отдавать пользователям+разработчикам.

2. статически полностью собрать проект как сейчас пытаюсь сделать.. но версии kernel + glibc приедется определить точно также как в прошлом пункте..

3. получить с мест версии kernel + glibc и собрать им проект у себя на машине..

4. ездить на места и собрать на их системах выполняемый модуль.. но не совсем понятно как быть с версионостью т.к. у нас достаточно часто выпускаются версии ПО.

а как выходят из этих сложностей другие разработчики?

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

А можно узнать какой у тебя версии gcc? Потому что если те системы собраны gcc3.4 а у тебя новее то в этом может быть проблема. Попробуй собрать gcc3.4 и линковать все статически а glibc динамически. Тогда должно пахать на всех машинах где есть libc.6 Можешь собрать две версии для libc.5 и libc.6

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

Публикуют сорцы + делают пакет для конкретного дистрибутива. Сим закрываются все перечисленные проблемы. Но нужно много знать и много работать, ежели целевых систем много.

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

> как выходят из этих сложностей другие разработчики?

Зависит от ситуации.

В определенных обстоятельствах есть смысл паковать дистрибутив в rpm. Создаются кое-какие новые проблемы, но уже имеющиеся предстают в ином свете и решаются легче: пользователю сразу говорят, чего именно в его системе не хватает, и, при удаче, сразу ставят недостающий пакет. linux way, так сказать.

rpm боятся не нужно - он освящен LSB, а дебианисты с ним замечательно справляются с помощью alien.

Если у тебя есть возможность получить список версий glibc, интересных твоим клиентам, то делай build систему на основе самой старой. Новые библиотеки либо совместимы со старыми (но, естественно, не наоборот), либо есть библиотеки совместимости: запустить бинарник, собранный на FC5, на RHEL 3 будет гораздо сложнее, чем наоборот.

Статическая линковка м.б. полезна для определенных библиотек, но я считаю, что glibc в этот список не входит.

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

> Между версией ядра и версией glibc существует достаточно тесная связь.

Это справедливо для Соляры (в смысле, там статическая линковка чревата). Для Линукса это не так, вернее, не совсем так.

"Правильно" слинкованная программа пойдет на всех системах, если не возникнет конфликта с ядерными вызовами и идиотизма с грубой проверкой версии ядра библиотекой. Вообще говоря, до недавнего времени на обратную совместимость обращали внимание, а ядерные разработчики -- даже особое внимание.

> Если glibc прилинковать статически, то неизбежно появятся системы, на которых программа работать не будет, причем они м.б. как более новые, так и более старые, чем та, на которой выполнялась сборка.

В таких случаях любое иное решение не пойдет заведомо.

Die-Hard ★★★★★
()
Ответ на: комментарий от ak_mish

> почему один и тот же код ведет себя абсолютно по разному наразличных дистрибутивах?

Скорее всего, дело в багах.

Уже несколько лет на статические версии некоторых вещей внимания практически не обращают. Там полно неотлавливаемых багов.

Можно сделать так:

Поставить "старый" gcc, с его помощью откомпилить "старую" glibc и потом статически все слинковать. Скорее всего, все заведется.

У меня пока получается :)

gcc 3.2

glibc-2.2.5 compiled with --enable-static-nss

P.S.

Без --enable-static-nss, скорее всего, дело в подгружаемых модулях nss, задаваемых в файле /etc/nsswitch.conf. Они всегда глючат при статической сборке...

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

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

Баги тут могут быть не при чем.

Как вариант, можно собрать glibc с --enable-kernel=2.4.0 И старые include'ы ядра подсунуть. Тогда, теоретически, должно работать где угодно (возможно, надо забыть о nptl).

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

> Баги тут могут быть не при чем.

Конечно, могут.

А есть еще и "багофичи"!

> Как вариант, можно собрать glibc с --enable-kernel=2.4.0

Кстати, да, про это я забыл!

> И старые include'ы ядра подсунуть.

Да, и про это я тоже забыл :)

Но так, скорее всего, не соберется. У меня так компилятор на что-то в инклудах ругался, а старый компилятор ругался на что-то в исходниках glibc. Мне пришлось именно старым компилером собирать старую glibc.

> возможно, надо забыть о nptl

Про nptl, конечно, забыть придется...

Die-Hard ★★★★★
()
Ответ на: комментарий от ak_mish

согласен с пп 1 и 3. если покупателей большое количество, то просто необходимо ограничить число поддерживаемых систем. если софт банковский, то скорее всего, у клиентов стоят коммерческие линуксы с оплаченнной поддержкой: => RHEL ES4, RHEL AS3, SuSE, ну пусть еще Debian(для экстремалов) => можно поддерживать две версии соляриса(или что там у них из ком.Юниксов) => ну винда win2003server(если кросс-платформа)

итого: оставить три-четыре платформы. остальные поддерживать за отдельные деньги. ничего плохого в этом нет. лучше выкатить три рабочих сборки, чем десяток сомнительного качества.

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

>> Если glibc прилинковать статически, то неизбежно появятся системы, на которых программа работать не будет, причем они м.б. как более новые, так и более старые, чем та, на которой выполнялась сборка.

>В таких случаях любое иное решение не пойдет заведомо.

Почему? Ведь у glibc все в порядке с версионированием, и для старого бинарника будет вызываться любимая им старая функция, т.е. функция со старым поведением, но адаптированная к новому ядру/окружению. Если программа совсем старая, то для нее найдется библиотека совместимости. Где проблема? И чем статическая линковка лучше? На первый взгляд, это тот самый silver bullet, и мой скромный опыт указывает на очень хорошую переносимость между разными Linux'ами, появившимися на свет в течение трех последних лет. Правда, экспериментов со статической линковкой я не проводил - очень возможно, что и в это случае все было бы хорошо.

Вопрос нисколько не риторический, и я буду очень признателен за объяснения и/или примеры. Дилемма static/dynamic меня интересует именно в контексте переносимости; эти аргументы http://people.redhat.com/drepper/no_static_linking.html вероятно, в дополнительных комментариях не нуждаются.

Еще раз подчеркиваю, что я говорю о glibc и только о glibc.

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

в пользу статической линковки: ABI ядра линукса самое стабильное abi среди всех линуксовых abi.

Die-Hard наверное ещё помнит наш тред о stdio где неоднообразность поведения приложения на разных платформах оказалась в том что в один прекрасный день glibc тихонечко стала соответствовать стандарту XOpen вместо SysV

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

мн6оготредовые и есчо какието приложения впринципе нельзя собрать полностью статическими: всёравно придётся тягать за собою небольшую часть glibc

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

cvv:

> Die-Hard наверное ещё помнит наш тред о stdio

:-)

Там не один трэд был...

Die-Hard ★★★★★
()
Ответ на: комментарий от anonymous

anonymous (*) (29.08.2006 9:41:10):

>>В таких случаях любое иное решение не пойдет заведомо.

>Почему? Ведь у glibc все в порядке с версионированием, и для старого бинарника будет вызываться любимая им старая функция, т.е. функция со старым поведением, но адаптированная к новому ядру/окружению. Если программа совсем старая, то для нее найдется библиотека совместимости. Где проблема? И чем статическая линковка лучше?

Не понял предлагаемой идеи...

Если libc хоть на единицу отличается в мажорной версии, то динамическая линковка однозначно не проканает.

Из-за багов даже минорные различия в версиях glibc обычно приводят к несовместимости по возрастающей, а бывало и к обратной несовместимости.

Еще -- обычно не единой glibc жива программа. Особенно плюсатая. Тогда вообще мрак...

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

>Не понял предлагаемой идеи...

Я уже давал здесь эту ссылку http://www.usenix.org/publications/library/proceedings/als00/2000papers/paper... да ты, вероятно, и без меня в курсе. Насколько я понимаю, glibc в современных дистрибутивах действительно содержат несколько реализаций одних и тех же функций с разными версиями, что вселяет некоторую надежду.

>Если libc хоть на единицу отличается в мажорной версии, то динамическая линковка однозначно не проканает.

Проканает динамическая линковка с библиотекой совместимости.

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

На это мне возразить нечего из-за отсутствия соответствующего практического опыта. Не сталкивался. Упомянутый пример про stdio я поищу, хотя искать слово "stdio" в этом форуме будет весьма забавно.

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

А можно посмотреть вывод команды:

file ваш_бинарник

И на каких (как Вы говорите "старых") ядрах происходит "Kernel too old" и "Segmentation fault"?

Тема заинтересовала - со старыми ядрами я не игрался - попробуйте скомпилировать что-то вроде:

void main (void) { for ( ; ; ) ; }

с флагами -static и -nostdlibs (так кажется) - те без каких-либо библиотек и посмотреть на проблемной машине - будут ли проблемы.

Если да - то это libc кочевряжится, если нет - ядро (полагаю связано с BFD - load_elf_binary() или что-то в этом духе - он может послать SIGSEGV в принципе если ему что-то не понравится (см. код) :-)

Путь который проделывает прога (по исследованию некоего К.Болдышева): shell() -> execve() -> sys_execve() -> (прибытие в ядро) -> do_execve() -> search_binary_handler() -> load_elf_binary() -> start_thread()

Пока не проверял - времени нет - но если кто-бы денег заплатил - я бы кернел дебуггером прошёлся бы...

aka Mr.Nobody

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

anonymous (*) (30.08.2006 8:59:54):

> Упомянутый пример про stdio я поищу, хотя искать слово "stdio" в этом форуме будет весьма забавно.

Зачем искать? Я ссылки на ТАКОЕ храню,

http://www.linux.org.ru/view-message.jsp?msgid=1152778

Но это, хотя и интересно, немного не про то...

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