多个gcc/glibc版本的共存及指定gcc版本的编译


这篇文章描述解决的方法,是针对这样的场景, 怎么使多个gcc/glib版本共存,在多个gcc/glib版本共存的情况,怎么样指定一个版本进行编译,怎么在一个与编译环境不同(gcc/glibc版本不同)的机器上运行服务

需求

服务原本的编译环境 Ubuntu + gcc 5.5.0(libstdc++) + libc.so.2.17

需要在目标编译环境 centos 6.8 + gcc 4.8(libstdc++) + libc.so.2.14

需要在环境 centos 6.8 + libc.so.2.14 运行

  • 限制:
  1. 源码必须使用gcc 5.5.0编译,所以得在目标编译环境安装对应版本的gcc和glibc
  2. 目标编译环境账号没有root权限

还有一点要注意,目标编译环境原编译环境上的连接器的版本也需要一致(或高于),连接器是隶属于 binutils包的。

这个需求中囊括了这样三个需求:怎么使多个gcc/glib版本共存在多个gcc/glib版本共存的情况,怎么样指定一个版本进行编译怎么在一个与编译环境不同(gcc/glibc版本不同)的机器上运行服务

背景知识

什么是glibc,libc,glib

  • glibc是linux的GUN C函数库,是linux系统中最底层的API,几乎其它任何运行时库都依赖于glibc。glibc除了封装linux操作系统所提供的系统服务,它本身也提供了许多其它必要功能服务的实现,例如:动态加载模块libdl、实时扩展接口librt。对应的动态库的名字libc.so

  • libc是Linux下的ANSI C函数库,被glibc包含

libc是Linux下原来的标准C库,也就是当初写hello world时包含的头文件#include < stdio.h> 定义的地方。
后来逐渐被glibc取代,也就是传说中的GNU C Library,在此之前除了有libc,还有klibc,uclibc。现在只要知道用的最多的是glibc就行了,主流的一些linux操作系统如 Debian, Ubuntu,Redhat等用的都是glibc(或者其变种,下面会说到).

  • glib是Linux下C的一些工具库,和glibc没有关系

依赖关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zzFJvF6H-1629517049109)(https://note.youdao.com/yws/api/personal/file/WEB1525e2b8f59e6aba4d5212f778140ddf?method=download&shareKey=69bafa9f7495f1a0f9ff03ffe6242795)]

构建程序,只要链接的libstdc++,glibc(libc.so,libpthread,动态连接器等系列库)版本正确,就不会出问题。在低版本的os上,安装高版本的gcc,glibc,只要可以顺利编译通过,则意味这高版本库是支持低版本OS的。

方法

查看glibc版本
  • 通过ldd
ldd --version

ldd是隶属于glibc,它的版本就是glibc的版本

  • 通过 getconf GNU_LIBC_VERSION

pthread也是一个非常重要的库,它被包含在glibc中,可以通过

getconf GNU_LIBPTHREAD_VERSION查看它的版本,是与glibc的版本是一致的

查找glibc库的位置
  • 通过ldd

linux 上几乎所有的程序都依赖于glibc,所以可以直接通过 ldd 某个程序 | grep "libc.so"的方式查看

  • 通过gcc

gcc -print-file-name=libc.so可以获得libc.so的位置,这也是该gcc依赖的libc.so的位置

查看glibc API的版本
  • strings /lib64/libc.so.6 | grep GLIBC
libstdc++

libstdc++是 gcc的标准C++库(libc++是clang的标准C++库)

查找libstdc++.so的位置
  • /sbin/ldconfig -p | grep stdc++

  • locate libstdc++.so

查看libstdc++的版本

libstdc++是被包含在gcc中的,对应为gcc的版本

gcc --version

查看系统libstdc++API的版本

strings /usr/lib/libstdc++.so.6 | grep LIBCXX

libstdc++,glibc的关系

libstdc++与gcc是捆绑在一起的,也就是说安装gcc的时候会把libstdc++装上。 那为什么glibc和gcc没有捆绑在一起呢?因为程序可以不依赖libstdc++,但是必须依赖glibc

确定程序需要的glibc/libstdc++的版本

readelf -s qt_cef_poc | grep -oP "GLIBC_[\d\.]*" | sort | uniq

解决步骤

编译安装

必须安装如下程序:

  • gcc(这里需求的是版本 5.5.0) 包含了 gcc/g++ ,libstdc++
  • binutils(这里需求的是版本2.27) 包含了 链接器(ld)
  • glibc(这里需求的是版本2.17) 包含了 libc.so , ld(动态链接器,用于在程序运行时链接动态库),libpthread

多个gcc/glibc版本共存

多个gcc/glibc共存,新安装的gcc/glibc版本需要指定安装目录。特别是glibc作为基础库,如果直接替换了系统中原有的glibc,很可能造成任何命令/程序都无法运行的情况。切记,一定要指定安装目录

指定gcc/g++,glibc的版本进行编译

在编译时需要指定gcc及库的依赖路径,包括以下几点:

  1. 指定gcc/g++的版本
export CC=gcc的路径
export CXX=g++的路径
  1. 指定连接器的版本

将连接器的路径,放在LD_LIBRARY_PATH的最前面

  1. 指定glibc的版本
  • 通过gcc 的-L参数指定glibc库(libc.so)的路径

  • 在gcc的编译参数中指定 -Wl,–dynamic-linker=glibc中动态链接器的路径,如下:

-Wl,--dynamic-linker=/动态连接器的路径/ld-linux-x86-64.so.2
  • 在gcc中链接libc.so(-lc)

  • glibc的路径,引入LD_LIBRARY_PATH

程序运行机器上的依赖

如果编译环境与运行环境不同,则需要将gcc,glibc的一些库打包到程序安装包中,并且指定库的路径

  1. 依赖的库
    libstdc++.so,libc.so库及它们的依赖库,动态连接器都需要放入程序的依赖库的目录中,基本是包含如下几个库
librt.so.1
libdl.so.2
libpthread.so.0
libstdc++.so.6
libm.so.6
libc.so.6 -> glibc库
libgcc_s.so.1
libresolv.so.2
libcrypt.so.1
ld-linux-x86-64.so.2 ->其实是个执行程序,为动态连接器
  1. 指定依赖库的路径

在编译是通过gcc的编译参数-Wl,-rpath=程序的依赖库路径

这些库最好都放在指定的,固定的目录中,在编译时通过这个编译选项指定该路径

3.将动态连接器ld-linux-x86-64.so.2的路径配置到PATH

总结

基本原理,就是千方百计的,将程序链接/运行时的依赖路径指向期望的版本,手段包括:

  • -Wl,-rpath=编译参数
  • -Wl,--dynamic-linker编译参数
  • 设置LD_LIBRARY_PATH
  • 设置PATH

吐个槽,C++的库管理太麻烦了。

### 回答1: 要查看交叉编译器使用的 glibc 版本,可以使用以下命令: ``` ${交叉编译器前缀}-gcc -print-file-name=libc.so ``` 其中,${交叉编译器前缀} 表示交叉编译器的前缀,例如 arm-linux-gnueabi-gcc 的前缀为 arm-linux-gnueabi。 执行上述命令后,输出的结果将包含 libc.so 文件的路径,例如: ``` /opt/arm-linux-gnueabi/libc.so ``` 在该路径下,使用以下命令即可查看 glibc 版本: ``` strings /opt/arm-linux-gnueabi/libc.so |grep GLIBC ``` 该命令会列出 libc.so 文件中包含的所有字符串,并筛选出包含 "GLIBC" 的字符串,这些字符串中包含了 glibc版本信息。 例如,输出可能类似于以下内容: ``` GLIBC_2.4 GLIBC_2.3.4 GLIBC_2.3.2 ``` 其中,GLIBC_2.x 表示 glibc 的主版本号为 2,次版本号为 x。因此,上述输出表示 glibc版本为 2.4、2.3.4 和 2.3.2。 ### 回答2: 要查看交叉编译器(Cross-Compiler)的glibc版本,您可以执行以下步骤: 1. 首先,使用命令行进入您的交叉编译器所在的目录。通常,交叉编译器的安装路径类似于`/opt/cross`或`/usr/local/cross`。 2. 然后,输入以下命令查看交叉编译器版本信息: ``` <交叉编译器路径>/bin/<目标平台架构标识>-<目标操作系统标识>-gcc --version ``` 其中,`<交叉编译器路径>`是您的交叉编译器所在的路径,`<目标平台架构标识>`是交叉编译器的目标平台架构(如arm、x86等),`<目标操作系统标识>`是交叉编译器的目标操作系统(如linux、android等)。 例如,如果您的交叉编译器安装在`/opt/cross`目录下,目标平台架构是arm,目标操作系统是linux,那么可以执行以下命令查看glibc版本: ``` /opt/cross/bin/arm-linux-gnueabi-gcc --version ``` 3. 上述命令执行后,您将看到交叉编译器版本信息,其中包括glibc版本。通常,glibc版本信息会在输出中的一行中显示为类似于`gcc version x.x.x (XXXXX)`的形式。 通过执行以上步骤,您可以轻松查看交叉编译器glibc版本。 ### 回答3: 要查看交叉编译器glibc版本,可以按照以下步骤进行: 1. 打开终端或命令行界面。 2. 输入命令“gcc -v”或“gcc --version”并按下回车键。 3. 终端将返回一些关于gcc编译器的信息,其中包括glibc版本glibc版本号通常以GNU C Library的缩写"glibc"开头,后面跟着版本号。 4. 可能需要滚动屏幕以查找完整的版本号。如果屏幕上没有看到完整的版本号,可以尝试使用命令“gcc -v 2>&1 | grep 'version'”来筛选和显示版本号。 5. 如果你正在进行交叉编译并可能有多个gcc版本安装在系统中,你可能需要指定交叉编译器的路径。在上述命令中,将“gcc”替换为交叉编译器的名称,例如“arm-linux-gnueabi-gcc -v”。 通过这些步骤,你应该能够找到交叉编译器glibc版本。请注意,glibc版本号通常以主版本号、次版本号和修订号的形式显示,例如2.32。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mo4776

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值