多个gcc/glibc版本的共存及指定gcc版本的编译_gcc编译指定glibc版本-程序员宅基地

技术标签: c++  C++编译系统  编译器  


这篇文章描述解决的方法,是针对这样的场景, 怎么使多个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++的库管理太麻烦了。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/mo4776/article/details/119837501

智能推荐

行转列-程序员宅基地

文章浏览阅读63次。DECLARE @sql VARCHAR(8000)SET @sql='' --初始化变量@sqlSELECT @sql=@sql+','+课程 FROM tb GROUP BY 课程 --变量多值赋值SET @sql=stuff(@sql,1,1,'')--去掉首个','SET @sql='select * from tb pivot (max(分数) for 课程 in ('+@s...

Android 屏幕保持唤醒_andrion设备关闭屏幕后仍然可以触摸唤醒-程序员宅基地

文章浏览阅读398次。一、 相关概念1. 出于节电的需要,一般应用在用户一段时间无操作的情况下屏幕变暗,然后进后休眠状态2. 用户只能在”设置->声音和显示”中设置所有应用默认的屏幕亮度和进行待机的时间3. 电源管理的实现分内核应用两部分,通过下面介绍的接口,我们可以设置应用程序的电源管理,以控制与其休眠相关的状态(是否需要进入休眠,调整c_andrion设备关闭屏幕后仍然可以触摸唤醒

java中的字符,字符串,数字之间的转换_controller字符串转数字安全-程序员宅基地

文章浏览阅读2k次。java中的字符,字符串,数字之间的转换string 和int之间的转换string转换成int :Integer.valueOf(" “)int转换成string : String.valueOf(int i )或者Integer.toString(int i)或者i+” “//i为int类型其中三者的效率为:Integer.toString(int i) >String.v..._controller字符串转数字安全

Vue-router 结合 element-ui 制作动态导航栏 + 面包屑_elementui实现动态的纵向导航栏-程序员宅基地

文章浏览阅读4.3w次,点赞11次,收藏84次。效果图如下: 主要思路: 一开始我的想法是根据左侧导航栏的点击事件动态的改变上方的面包屑,但后来发现如果直接通过 URL 访问的话导航栏和面包屑都是处于初始状态的。因此我想到通过 route 的值同时改变导航栏和面包屑。首先,我们定义 route 文件,注意将 Router 的模式设为 history,否则跳转时 URL 上会带有 # 符号,导致获取到的 route 值不正确,代码如下..._elementui实现动态的纵向导航栏

OPENSTACK Train版本安装大集合_openstack train版本下载-程序员宅基地

文章浏览阅读3.8k次。OPENSTACK Train版本安装大集合1. 服务器安装centos7 操作系统2. 配置网络-ip地址及注意事项3 centos7开启ssh服务-事倍功半的效果4. Centos7使用wget修改为阿里云镜像源5. 开始按照官网安装train 版本5.1 官网地址5.2 安装过程几个注意事项1. 服务器安装centos7 操作系统服务器的基本配置要满足要求,如cpu 内存等,一般服务器都..._openstack train版本下载

linux中文件查找locate,whereis,find介绍_linux 查找 locate源码文件 where-程序员宅基地

文章浏览阅读284次。文件查找命令find按照名字查找文件find / -name 文件(目录)名按照时间查找文件-mtime n :n 为数字,意义为在 n 天前癿『一天内』被更改过内容的档案; -mtime +n :列出在 n 天前(不含 n 天本身)被更改过内容的档案档名;-mtime -n :列出在 n 天内(含n 天本身)被更改过内容的档案档名。例如find /ho_linux 查找 locate源码文件 where

随便推点

如何屏蔽CSDN-程序员宅基地

文章浏览阅读854次。如何过滤掉csdn相关文章_屏蔽csdn

计算机电子表格的优点,信息技术《电子表格的特点及应用》的说课稿-程序员宅基地

文章浏览阅读518次。信息技术《电子表格的特点及应用》的说课稿一、 说教材(一)、地位、作用和特点本课是海南出版社的海南省中小学信息技术七年级下册第二章第一节,内容是电子表格的特点及应用,是学生学习word软件和powerpoint软件办公软件的基础上,再继续学习的电子表格软件。教材是先从日常生活中的电子表格的应用举例,到介绍电子表格处理软件,再结合word文档处理软件与excel电子表格处理软进行对比,总结出电子表格..._表格的云南人民出版社七年级9册信息技术教材特点

SpringCloud之Config 分布式配置中心-程序员宅基地

文章浏览阅读314次。分布式系统面临的—配置问题微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。SpringCloud提供了ConfigServer来解决这个问题,我们每一个微服务自己带着一个application.yml,上百个配置文件的管理…/(ㄒoㄒ)/~~...

修改mysql用户密码的方法总结_mysql修改密码时0 row affected-程序员宅基地

文章浏览阅读475次。修改mysql密码是管理web服务器经常需要做的事情。MySQL管理员帐号默认是root用户,密码为空。mysqladmin命令修改root密码如果你从没设置过MySQL的密码,使用root用户来连接MySQL服务器不需要输入密码。第一次设置root密码可以使用以下命令:mysqladmin -u root password NEWPASSWORD如_mysql修改密码时0 row affected

Spring Tools的安装配置_sprinttools-程序员宅基地

文章浏览阅读257次。Spring Tools(sts)是基于eclipse的开发环境, 用于开发Spring应用程序。下载地址:spring tool suite官网:http://spring.io/tools/stsspring tool suite官网下载:http://spring.io/tools/sts/alleclipse官网下载:http://www.eclipse.org/downloads..._sprinttools

关于vim的复制粘贴_vim复制其他文件-程序员宅基地

文章浏览阅读1.2k次。今天被vim的复制粘贴弄得很烦,它不像windows那样,每次复制会把以前的内容覆盖。所以有时粘贴出来的东西并不是你想要的。在不同终端中,用vim打开的两个文件之间的复制粘贴1. 用同一个终端,直接使用这个命令:vim file1 file2这样就可以直接用y和p复制粘贴了。但是这样比较麻烦,需要在两个文件之间切换。2. 之所以不能直接用_vim复制其他文件

推荐文章

热门文章

相关标签