gol*_*cks 56
GNU/Linux 系统通常使用 glibc(Fedora/Redhat 系列,Arch)或其近亲 eglibc(Debian/Ubuntu 系列);由于 eglibc 现在被合并回 glibc(参见“新闻”下创建的 EGLIBC 2.19 分支),在不久的将来它们都将再次成为 glibc。
检查确切版本的最简单方法是 ask ldd
,它随 C 库一起提供。
在 Fedora 20 上:
> ldd --version
ldd (GNU libc) 2.18
Run Code Online (Sandbox Code Playgroud)
那是 glibc 2.18。
在 Raspbian(ARMv6 Broadcom SoC 的 Debian 7 端口)上:
> ldd --version
ldd (Debian EGLIBC 2.13-38+rpi2) 2.13
Run Code Online (Sandbox Code Playgroud)
那是 eglibc 2.13。
如果由于某种原因您混合和匹配了某些部分或不确定ldd
,您可以直接查询 C 库。
> whereis libc.so
libc: /usr/lib64/libc.a /usr/lib64/libc.so /usr/share/man/man7/libc.7.gz
Run Code Online (Sandbox Code Playgroud)
这些都不是可执行的,但它们提供了有关在哪里可以找到的线索。
> $(find /usr/lib64/ -executable -name "*libc.so*") --version
GNU C Library (GNU libc) stable release version 2.18, by Roland McGrath et al.
Run Code Online (Sandbox Code Playgroud)
然而,这并不一定那么容易,因为 C 库并不一定要驻留在某处whereis
才能找到它。
> whereis libc.so
libc: /usr/share/man/man7/libc.7.gz
Run Code Online (Sandbox Code Playgroud)
不幸的是,手册页没有提供版本号。 ldd
仍然派上用场,因为系统上任何有效的、动态链接的可执行文件(例如, 中的几乎所有内容/usr/bin
)都将链接到 C 库。
> ldd /usr/bin/touch
/usr/lib/arm-linux-gnueabihf/libcofi_rpi.so (0xb6eed000)
librt.so.1 => /lib/arm-linux-gnueabihf/librt.so.1 (0xb6ed0000)
libc.so.6 => /lib/arm-linux-gnueabihf/libc.so.6 (0xb6da1000)
/lib/ld-linux-armhf.so.3 (0xb6efb000)
libpthread.so.0 => /lib/arm-linux-gnueabihf/libpthread.so.0 (0xb6d82000)
Run Code Online (Sandbox Code Playgroud)
libc.so.6
在第三行。
> /lib/arm-linux-gnueabihf/libc.so.6 --version
GNU C Library (Debian EGLIBC 2.13-38+rpi2) stable release version 2.13, by Roland McGrath et al.
Run Code Online (Sandbox Code Playgroud)
der*_*ert 15
一个系统实际上并不限于一个 C 库。但是,大多数主要只使用一种,这也将是默认编译器使用的一种。由于您要下载源代码进行编译,这就是您所关心的问题。
从一个简单的程序开始:
#include <stdio.h>
int main() {
printf("Hello, world\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
使用您将用于源代码的编译器编译它,然后使用ldd
它找出 C 库的位置:
$ ldd ./libc-test
linux-vdso.so.1 (0x00007fff2e5fe000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8c8ad98000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8c8b171000)
Run Code Online (Sandbox Code Playgroud)
您现在拥有了 C 库的路径。您可以在包管理器中查找该包以找到该包(例如,dpkg -S /lib/x86_64-linux-gnu/libc.so.6
或rpm -q -f /lib/x86_64-linux-gnu/libc.so.6
)。
至少在 eglibc/glibc 的情况下,你可以运行它:
$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Debian EGLIBC 2.18-4) stable release version 2.18, by Roland McGrath et al.
Copyright (C) 2013 Free Software Foundation, Inc.
?
Run Code Online (Sandbox Code Playgroud)
最后,您可以objdump -p /lib/x86_64-linux-gnu/libc.so.6
通过查看版本定义部分来查看是否可以从 中获得线索:
$ ldd ./libc-test
linux-vdso.so.1 (0x00007fff2e5fe000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f8c8ad98000)
/lib64/ld-linux-x86-64.so.2 (0x00007f8c8b171000)
Run Code Online (Sandbox Code Playgroud)
请注意 GLIBC_2.18 符号如何在列出的符号中具有最新的版本号,并且库版本确实是 2.18。不过,它是 eglibc(它旨在与 glibc 2.18 二进制兼容,因此它使用相同的符号版本)。
您也可以尝试使用strings
来了解它。您需要指定更长的最小长度 ( -n
),或使用 grep 搜索某些内容:
$ strings /lib/x86_64-linux-gnu/libc.so.6 | grep 'version [0-9]'
$ strings /lib/x86_64-linux-gnu/libc.so.6 | grep -iC1 'copyright'
Run Code Online (Sandbox Code Playgroud)
两者都适用于这个 eglibc。
注意:Debian 软件包实用程序在幕后dpkg-shlibdeps
使用objdump
以及 Debian 库软件包中存储的符号信息来确定二进制 Debian 软件包在构建时所需的最低依赖版本。基本上,它查看二进制 Debian 包导出的符号,然后找到包含这些符号的库的最低版本。
mr.*_*tic 10
显而易见的答案,虽然不是最全面的,是检查你的包管理器,例如
rpm -qi glibc
dpkg -l libc6
Run Code Online (Sandbox Code Playgroud)
(遗憾的是,glibc 没有 pkconfig.pc
文件,所以pkgconfig --modversion glibc
没有运行程序。)另请参阅 @Gnouc 的极好getconf
建议。
最简单的情况是 gcc+glibc,我最常使用的就是 execute libc.so
,如这里的其他一些答案中所述。不需要传递任何参数,它默认输出它的版本。这适用于 glibc-2.1(glibc-2.0 seg-faults,尽管那时您可以检查(现已停用)glibcbug
脚本以确认版本)。此方法也适用于最近 (>0.9.15) 版本的musl-libc(今天,3 月 20 日刚刚发布 1.0)。它不适用于 uClibc,它会出现段错误。
一种简单的方法来准确地告诉你gcc
要做什么是编译:
#include <gnu/libc-version.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
printf("%s %s\n",gnu_get_libc_version(),gnu_get_libc_release());
printf("glibc v%i %i.%i\n",__GNU_LIBRARY__,__GLIBC__,__GLIBC_MINOR__);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
(使用 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的(13759的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
,如下所示:
$ /lib/x86_64-linux-gnu/libc.so.6
GNU C Library (Debian EGLIBC 2.18-4) stable release version 2.18, by Roland McGrath et al.
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 4.8.2.
Compiled on a Linux 3.12.6 system on 2014-03-02.
Available extensions:
crypt add-on version 2.1 by Michael Glad and others
GNU Libidn by Simon Josefsson
Native POSIX Threads Library by Ulrich Drepper et al
BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.
Run Code Online (Sandbox Code Playgroud)
但是当然所在的目录libc.so.6
不在 中$PATH
,因此您必须知道在哪里寻找它。它可能在/lib
、/lib64
、/usr/lib
或更古怪的地方(如本例中)。方便,ldd
会告诉你:
$ ldd /bin/sh | grep libc
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5660b93000)
Run Code Online (Sandbox Code Playgroud)
当然,要使其工作,您必须知道动态链接的二进制可执行文件的完整路径名。该sh
可执行文件是保证在/bin
(因为这么多的#!
脚本,希望它是),而自身不能是一个#!
脚本。它可以是静态链接的,但我已经很多年没有遇到过这样做的系统了。
如果您使用 uClibc 或 musl 或更奇特的东西运行,我不知道您会做什么。