总结
- 一套系统折腾多套gcc、libc、libstdc 没必要,浪费时间。用对应版本的系统编译对应版本的二进制即可。一般软件对libc、libstdc 的要求都不会太高,系统别太老一般都能跑。
- 如果系统太老,自带的libc太旧,新软件可能会编译失败(比如用了新的libc的函数),这种情况下如果是因为libc太久,可以直接升级系统,实在可下载libc给程序特供。
- 如果因为libstdc 太旧(比如用了新的c 库函数),因为libstdc 是跟着gcc的,系统的gcc也比较旧了,可以更新gcc的版本,编译时需要执行用新的gcc,但很可能编译时还回去去找老的gcc和老的stdlibc 库,这就需要看程序的怎么编译的了,改下编译器、引用库路径等。
C 的版本管理简单粗暴,像libc这种基础库如果需要多版本,用起来非常不方便,但c/c 基础库都是向下兼容的,最好的方式就是用一套比较新的系统,带着新的libc,再安装一套和系统版本同年代的新一点的gcc编译器即可,可满足大部分的使用场景,避免一套环境上折腾多套libc、libstdc ,经验之谈:非常麻烦性价比很低!
libc.so
系统一定会自带libc.so,因为这是C的基础库,内核和所有程序都会依赖系统自带libc.so。
随便一个程序看下依赖库,都能看到Libc的影子:
代码语言:javascript复制# ldd /usr/bin/echo
...
...
libc.so.6 => /lib64/libc.so.6 (0x00007fa004df6000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fa004bf2000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa0053c5000)
注意:程序用的时候都会用/lib64/libc.so.6
的名字,而libc.so.6
会指向哭啼某个版本的libc。
查看所依赖的libc版本,可以看出当前Libc的版本是2.28。而Libc是向下兼容的,从库中定义的一些字符串常量可以知道兼容哪些版本:
- 当前是2.28
- 向下兼容到2.3
$ ll /lib64/libc.so.6
lrwxrwxrwx 1 root root 12 Nov 24 2022 /lib64/libc.so.6 -> libc-2.28.so
$ strings /lib64/libc.so.6 | grep -E '^GLIBC' | sort
GLIBC_2.10
GLIBC_2.11
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_2.18
GLIBC_2.22
GLIBC_2.23
GLIBC_2.23
GLIBC_2.24
GLIBC_2.2.5
GLIBC_2.25
GLIBC_2.25
GLIBC_2.2.6
GLIBC_2.2.6
GLIBC_2.26
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28
GLIBC_2.28
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.5
GLIBC_2.6
GLIBC_2.6
GLIBC_2.7
GLIBC_2.7
GLIBC_2.8
GLIBC_2.8
GLIBC_2.9
GLIBC_2.9
GLIBC_PRIVATE
/lib64/目录是短连接,实际位置:
代码语言:javascript复制$ ll /lib64
lrwxrwxrwx 1 root root 9 Dec 21 2021 /lib64 -> usr/lib64
$ ll /usr/lib64/ | grep libc.so
-rw-r--r-- 1 root root 253 Nov 24 2022 libc.so
lrwxrwxrwx 1 root root 12 Nov 24 2022 libc.so.6 -> libc-2.28.so
ldd的版本和libc是配套的:
代码语言:javascript复制$ ldd --version
ldd (GNU libc) 2.28
Copyright (C) 2018 Free Software Foundation, Inc.
编译器用的Libc版本:
代码语言:javascript复制$ gcc -print-file-name=libc.so
/usr/lib/gcc/x86_64-redhat-linux/8/../../../../lib64/libc.so
libstdc 与gcc
- libstdc 是c 的标准库文件,注意libstdc 是和gcc一起编译安装的。
- 自己编译安装的gcc是不会安装libc的,libc可以单独下载升级。
- linux系统内核、自带工具会依赖libc,所以libc是必须存在的;但不依赖libstdc ,所以libstdc 可以不安装。
使用g 编译的c 程序会依赖c 标准库libstdc .so.6
代码语言:javascript复制$ ldd llvm-as
...
libstdc .so.6 => /lib64/libstdc .so.6 (0x00007f4cf5ae0000)
libm.so.6 => /lib64/libm.so.6 (0x00007f4cf575e000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f4cf5546000)
libc.so.6 => /lib64/libc.so.6 (0x00007f4cf5180000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4cf68bc000)
libstdc .so.6的名字也是用短连接指向真正的库文件:
代码语言:javascript复制$ ll /lib64/libstdc .so.6
lrwxrwxrwx 1 root root 19 May 24 22:05 /lib64/libstdc .so.6 -> libstdc .so.6.0.25
$ strings /usr/lib64/libstdc .so.6 | grep LIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBCXX_3.4.20
GLIBCXX_3.4.21
GLIBCXX_3.4.22
GLIBCXX_3.4.23
GLIBCXX_3.4.24
GLIBCXX_3.4.25
GLIBCXX_DEBUG_MESSAGE_LENGTH
GA GLIBCXX_ASSERTIONS
程序需要什么版本的libc和libstdc
以llvm为例
代码语言:javascript复制$ readelf -s llvm-ar | grep -oE "GLIBCXX_.*|GLIBC_.*" | sort | uniq
GLIBCXX_3.4
GLIBCXX_3.4 (6)
GLIBCXX_3.4.11 (14)
GLIBCXX_3.4.14 (26)
GLIBCXX_3.4.15 (11)
GLIBCXX_3.4.18 (22)
GLIBCXX_3.4.19 (21)
GLIBCXX_3.4.20 (5)
GLIBCXX_3.4.21 (8)
GLIBCXX_3.4.9 (13)
GLIBC_2.14
GLIBC_2.14 (7)
GLIBC_2.15 (23)
GLIBC_2.2.5
GLIBC_2.2.5 (15)
GLIBC_2.2.5 (18)
GLIBC_2.2.5 (3)
GLIBC_2.2.5 (4)
GLIBC_2.3
GLIBC_2.3 (17)
GLIBC_2.3 (9)
GLIBC_2.6
GLIBC_2.6 (10)
可以看出llvm-ar需要:
- libc的版本为:2.15
- libcxx的版本为:3.4.21
而当前系统提供:
- libc的最新版本:2.28
- libcxx的版本:3.4.25
strings /usr/lib64/libstdc .so.6 | grep GLIBCXX
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBCXX_3.4.15
GLIBCXX_3.4.16
GLIBCXX_3.4.17
GLIBCXX_3.4.18
GLIBCXX_3.4.19
GLIBCXX_3.4.20
GLIBCXX_3.4.21
GLIBCXX_3.4.22
GLIBCXX_3.4.23
GLIBCXX_3.4.24
GLIBCXX_3.4.25
strings /lib64/libc.so.6 | grep -E '^GLIBC' | sort
GLIBC_2.10
GLIBC_2.11
GLIBC_2.11
GLIBC_2.12
GLIBC_2.13
GLIBC_2.13
GLIBC_2.14
GLIBC_2.15
GLIBC_2.16
GLIBC_2.16
GLIBC_2.17
GLIBC_2.18
GLIBC_2.18
GLIBC_2.2.5
GLIBC_2.2.6
GLIBC_2.2.6
GLIBC_2.22
GLIBC_2.23
GLIBC_2.23
GLIBC_2.24
GLIBC_2.25
GLIBC_2.25
GLIBC_2.26
GLIBC_2.26
GLIBC_2.27
GLIBC_2.28
GLIBC_2.28
GLIBC_2.3
GLIBC_2.3.2
GLIBC_2.3.3
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.5
GLIBC_2.5
GLIBC_2.6
GLIBC_2.6
GLIBC_2.7
GLIBC_2.7
GLIBC_2.8
GLIBC_2.8
GLIBC_2.9
GLIBC_2.9
可以满足要求。