Как я могу точно сказать, какую пользовательскую библиотеку C использует моя система? Возможные причины, по которым эта информация нужна:
Есть гигантский пакет с исходным кодом, который я собираюсь загрузить, и я уверен, что он сделает правильные проверки и перечислит версию библиотеки mininum, но я бы предпочел избавить себя от потенциальных хлопот, проверив сначала, будет ли он работать.
Меня беспокоит совместимость ABI с некоторыми сторонними двоичными файлами, которые я хочу попробовать установить за пределами системы управления пакетами системы.
У меня есть пакет с исходным кодом, в документации которого упоминается необходимость в минимальной версии библиотеки моей системы, но процесс сборки не выполняет никаких проверок.
Я создаю кросс-компилятор для конкретной системы и не хочу рисковать проблемами с совместимостью .
источник
ldd
. Я не уверен, чтоotool --version
можно рассматривать как предоставление той же информации.Ответы:
Системы GNU / Linux обычно используют либо glibc (семейство Fedora / Redhat, Arch), либо его близкий родственник, eglibc (семейство Debian / Ubuntu); поскольку eglibc теперь объединяется с glibc ( см. ветку EGLIBC 2.19, созданную в разделе «Новости» ), в ближайшем будущем все они снова будут glibc.
Самый простой способ проверить точную версию - спросить
ldd
, которая поставляется с библиотекой C.На Fedora 20:
Это glibc 2.18.
На Raspbian (порт Debian 7 для ARMv6 Broadcom SoC):
Это, например, 2.13.
Если по какой-либо причине вы смешали и сопоставили некоторые части или по-другому не уверены
ldd
, вы можете запросить библиотеку C напрямую.Ни один из них не является исполняемым, но он дает представление о том, где его найти.
Тем не менее, это не обязательно так просто, потому что библиотека C не обязательно должна находиться где-то, чтобы
whereis
найти ее.К сожалению, страница руководства не предоставляет номер версии.
ldd
все еще пригодится, поскольку любой работающий, динамически связанный исполняемый файл в системе (например, почти все внутри/usr/bin
) будет связываться с библиотекой C.libc.so.6
находится на третьей строке.источник
/lib/`uname -m`*
путь. Так переносимый способ будет:find /lib/`uname -m`* /usr/lib* -executable -name "*libc.so*" | xargs --version
. Спасибо за приятное объяснение.Система на самом деле не ограничена одной библиотекой Си. Большинство, тем не менее, в основном используют только один, который также будет использоваться компилятором по умолчанию. А поскольку вы загружаете исходный код для компиляции, это то, что вас беспокоит.
Начните с тривиальной программы:
скомпилируйте его, используя компилятор, который вы собираетесь использовать для исходного кода, а затем используйте,
ldd
чтобы узнать, где находится библиотека C:Теперь у вас есть путь к библиотеке C. Вы можете найти это в вашем менеджере пакетов, чтобы найти пакет (например,
dpkg -S /lib/x86_64-linux-gnu/libc.so.6
илиrpm -q -f /lib/x86_64-linux-gnu/libc.so.6
).По крайней мере, в случае eglibc / glibc, вы можете запустить его:
Наконец, вы можете увидеть, можете ли вы получить подсказки
objdump -p /lib/x86_64-linux-gnu/libc.so.6
, посмотрев в разделе определений версий :Обратите внимание, что символ GLIBC_2.18 имеет самый последний номер версии среди перечисленных символов, и версия библиотеки действительно равна 2.18. Это eglibc, хотя (он предназначен для двоичной совместимости с glibc 2.18, поэтому он использует те же версии символов).
Вы также можете попытаться использовать,
strings
чтобы узнать что-то об этом. Вы захотите указать более длинную минимальную длину (-n
) или использовать grep для поиска чего-либо:оба работают для этого eglibc.
ПРИМЕЧАНИЕ. Утилита пакетов Debian
dpkg-shlibdeps
используетobjdump
скрытую информацию вместе с хранимой информацией о символах в пакетах библиотек Debian для определения минимальных версий зависимостей, требуемых бинарными пакетами Debian во время сборки. По сути, он просматривает символы, экспортируемые двоичным пакетом Debian, а затем находит минимальные версии библиотек, которые содержат эти символы.источник
Очевидный ответ, хотя и не самый полный, состоит в том, чтобы проверить ваш менеджер пакетов, например
(К сожалению, у glibc нет
.pc
файла pkconfig , поэтому он не участвуетpkgconfig --modversion glibc
.) Смотрите также превосходноеgetconf
предложение @ Gnouc .Простейший случай с gcc + glibc и тот, который я в основном использую первым, - просто выполнить
libc.so
, как описано в некоторых других ответах здесь. Нет необходимости передавать аргументы, по умолчанию выводится его версия. Это работает вплоть до glibc-2.1 (ошибки сегмента glibc-2.0, хотя еще тогда вы могли проверить (теперь уже удаленный)glibcbug
скрипт для подтверждения версии). Этот метод также работает с последними (> 0.9.15) версиями musl-libc (которая вышла 1.0 сегодня, 20 марта). Это не работает с uClibc, это segfaults.Один простой способ точно сказать, что вы
gcc
собираетесь делать - это скомпилировать:(с glibc,
<stdio.h>
включает в себя ,<features.h>
которая определяет соответствующие GLIBC макросы, вам необходимо<gnu/libc-version.h>
для объявления функций.)Это позволяет отследить более сложные случаи (несколько libc и / или несколько компиляторов), если, конечно, вы используете правильный компилятор (и флаги). (Я подозреваю, что он не будет различать между eglibc и glibc).
Если вы уверены, что используете glibc (или eglibc), то(извините, это неверно).ld
также подтвердите версиюЕсли
__GNU_LIBRARY__
не определено, вы получите ошибки, то пришло время для плана B.gcc -dumpmachine
может помочь, например, для uclibc он имеет-uclibc
суффикс, как можетgcc -dumpspecs | grep dynamic-linker
. Это также может подразумевать ABI.gcc -print-file-name=libc.so
скажет вам, какой файл компилятор будет использовать для "-lc
", это почти наверняка компоновщик-скрипт в вашей установке gcc, который вы можете прочитать как обычный текст. Это покажет точный путь кlibc.so
. Это также будет работать, если вы передаете флаги типа-m32
или-m64
.В случае , если вы используете uclibc (как используются OpenWRT и более), оно определяет
__UCLIBC_MAJOR__
,__UCLIBC_MINOR__
и__UCLIBC_SUBLEVEL__
так же , как__UCLIBC__
в<features.h>
, так что это легко обнаруживается с помощью изменения незначительного по вышеуказанному C фрагменте кода. В интересах совместимости, uClibc может также определять макросы GNU / GLIBC, как использовано выше, в настоящее время он претендует на то, чтобы быть glibc-2.2. Она в настоящее время не выполнятьgnu_get_libc_X()
функции, но это осуществить ,getconf
который также может ввести в заблуждение (я подозреваю , что он возвращает пустой ответ наgetconf GNU_LIBC_VERSION
мой билд окр дуется сегодня , поэтому я не могу подтвердить.)В маловероятном случае, если вы используете dietlibc , при запуске
diet -v
будет отображаться версия.(FWIW, в течение нескольких лет с программным обеспечением, использующим autoconf, у меня было больше проблем с непроверенными требованиями
gcc
иg++
требованиями, чем с проверенными функциями glibc.)источник
GNU libc (то, что большинство дистрибутивов Linux используют в той или иной форме) идет на все, чтобы сохранить строгую обратную совместимость. Таким образом, вы должны столкнуться с проблемами только в том случае, если вы попытаетесь запустить слишком новый двоичный файл в старой версии (или в «корпоративном» дистрибутиве, они обычно замораживают версии, особенно базовые, такие как библиотека C, возвращают исправления, сохраняя строгую двоичную совместимость) , Я считаю, что у вас гораздо больше шансов столкнуться с проблемами с другими библиотеками (в C ++ было несколько изменений API / ABI в недавней памяти, некоторые другие библиотеки просто не заботятся о обратной совместимости).
К сожалению, единственный способ узнать наверняка - попробовать.
источник
(По сути, это то же самое, что и ответ Златовласки, но с дополнительным объяснением того, что происходит под капотом.)
Базовая разделяемая библиотека для GNU libc
libc.so.6
(в Linux; у Hurd другое SONAME) обладает необычным свойством (для разделяемых библиотек), которое вы можете вызывать как исполняемый файл. Если вы это сделаете, то выдает то, что утилиты GNU обычно печатают при запуске--version
, например:Но, разумеется, каталог, в котором
libc.so.6
живет, отсутствует$PATH
, поэтому вы должны знать, где его искать. Это может быть/lib
,/lib64
,/usr/lib
или что - то еще wackier (как в данном случае). Удобно,ldd
скажу вам:Конечно, чтобы это работало, вы должны знать полный путь к динамически связанному двоичному исполняемому файлу.
sh
Исполняемый гарантированно будет в/bin
(потому что многие#!
сценариях ожидать , что это будет), а сам не может быть#!
сценарием. Это может быть статически связано, но я не сталкивался с системой, которая делала это много лет.Я не знаю, что вы делаете, если вы используете uClibc или musl или что-то более экзотическое.
источник
$ ldd $(which sh) | grep libc
. : DЕще один способ получить это:
источник