【gcc】高版本gcc编译出的程序在低版本glibc机器上运行
目录
1.静态编译(多数场景不行)
2.容器发布(部分场景可以使用)
3.安装部署devtoolset
4.打包依赖的so发布(通用方案)
3.1 方式1 在编译时设置rpath和dynamic linker
3.2 方式2 直接修改二进制程序的rpath和interpreter
比如我们用gcc 9.3.0编译程序,但需要发布的机器gcc版本是4.8.5,怎么办?
你可能想到如下方法
- 静态编译
- 容器发布
- 打包依赖的so,使用本地so运行程序
1.静态编译(多数场景不行)
其中静态编译是行不通的,libstdc++是可以静态编译,但是libc没有提供这方面的功能,即使你是cpp程序,依然会大概率依赖libc.so
可以通过nm <bin> | grep GLIBC_
确定你的程序是否依赖了glibc,没有的话,你可以考虑直接静态编译libstdc++。
2.容器发布(部分场景可以使用)
使用携带gcc9.3.0环境的容器发布程序,是可以的。但是在一些没有容器且没有sudo权限的场合,依然不太友好。
3.安装部署devtoolset
从源码安装的难度不低,向了devtoolset可能是不错的选择
RedHat 推出Software Collections
的目的就是为了解决想在RedHat
系统下能使用新版本的工具,让同一个工具(如gcc)的不同版本能在系统中共存,在需要的时候切换到对应的版本中
如何安装和使用devtoolset
,可以参考官方指导文档。在看装前,我们可以先到Information for build搜索自己需要的package对应的源码版本,看devtoolset
中的安装包对应的源码版本是多少,是否满足自身的需求。
devtoolset-8-gcc-8.3.1-3.2.el7 | Build Info | CentOS Community Build Service
- 到sclo7-devtoolset-8-rh-candidate下载全部RPM包(这里偷懒下载全部包,这样就不用处理他们之间复杂的依赖关系)
- 下载完成后,在RPM包的目录中执行
yum install *.rpm
,安装全部 - 然后执行
scl enable devtoolset-8 bash
切换环境。
> stap -V # 我们可以执行这个命令进行验证,我们得到了Systemtap-3.3,支持linux kernel 2.6.28-4.18
Systemtap translator/driver (version 3.3/0.173, rpm 3.3-1.el7)
Copyright (C) 2005-2018 Red Hat, Inc. and others
This is free software; see the source for copying conditions.
tested kernel versions: 2.6.18 ... 4.18-rc0
enabled features: AVAHI BOOST_STRING_REF DYNINST LIBRPM LIBSQLITE3 NLS NSS READLINE
安装最新版 devtoolset-8 — 源代码
4.打包依赖的so发布(通用方案)
这个方法虽然听起来不是很优雅,但其实如果你对elf文件有一些了解,是不错的方式。下面说下具体的方法。
3.1 方式1 在编译时设置rpath和dynamic linker
当你有条件获得程序源码,并能够重新编译时,可以直接在编译时指定相关参数来解决。
先说编译时要增加的参数:
# 绝对路径
gcc -Wl,-rpath='/my/lib',-dynamic-linker='/my/lib/ld-linux.so.2'
gcc参数
-Wl,option
Pass option as an option to the linker.
ld参数
-rpath=dir
Add a directory to the runtime library search path. This is used when linking an ELF executable with shared objects.
--dynamic-linker=file
Set the name of the dynamic linker.
这两个参数分别设置的elf文件中的rpath和interpreter字段。
rpath
全名run-time search path
,是elf文件中一个字段,它指定了可执行文件执行时搜索so文件的第一优先位置,一般编译器默认将该字段设为空。elf文件中还有一个类似的字段runpath,其作用与rpath类似,但搜索优先级稍低。搜索优先级:
rpath > LD_LIBRARY_PATH > runpath > ldconfig缓存 > 默认的/lib,/usr/lib等
如果你需要使用相对路径指定lib文件夹,可以使用ORIGIN变量,ld会将ORIGIN理解成可执行文件所在的路径。
gcc -Wl,-rpath='$ORIGIN/../lib'
interpreter
全名elf interpreter
,用于加载elf文件。这个字段在链接时会帮你自动设置,64bit程序一般为/lib64/ld-linux-x86-64.so.2
。这也是打包so的坑之一,很多人(比如我)通过ldd找出程序依赖的so,进行打包后,在目标机器修改rpath或者LD_LIBRARY_PATH指向本地lib目录,但ldd程序,发现/lib64/ld-linux-x86-64.so.2这个so仍然指向系统so。原因就是这个字段是写死在elf文件中的,并不受LD_LIBRARY_PATH影响。
编译时带上这两个参数,下面只需要将你程序依赖的so打包一份,随程序进行发布即可。
3.2 方式2 直接修改二进制程序的rpath和interpreter
(patchelf
具体用法见:https://blog.csdn.net/bandaoyu/article/details/113181179)
当你无法编译程序时,也可以通过其他方式修改rpath和interpreter。这种情况需要使用到一个工具patchelf
,通过dnf install patchelf
即可安装。你可以通过它修改elf文件的rpath和interpreter:
patchelf --set-rpath /my/lib your_program
patchelf --set-interpreter /my/lib/ld-linux.so.2 your_program
除了绝对路径,一种比较常见的方式是在部署前,使用pwd
获取当前路径,使用相对路径指向本地lib。
patchelf --set-rpath `pwd`/../lib your_program
patchelf --set-interpreter `pwd`/../lib/ld-linux-x86-64.so.2 ./your_program
摘抄和参考:
链接:https://www.jianshu.com/p/77d7f7dc93b3
安装最新版 devtoolset-8 — 源代码
解决‘GLIBC_2.34‘ not found,并且gcc制定glibc版本编译
【日常记录】解决‘GLIBC_2.34‘ not found,并且gcc制定glibc版本编译_https://blog.csdn.net/weixin_65527369/article/details/127973141
【gcc】高版本gcc编译出的程序在低版本glibc机器上运行相关推荐
- 让vc编译出的程序减小体积
让vc编译出的程序减小体积 转自邪恶八进制 ----------------------------- 人们都说vc做出的东西可以小点,现在你打开vc编译一个Hello World出来!点属性看下,咦 ...
- 【原】解决VS2008编译的程序在某些机器上运行提示“由于应用程序配置不正确,应用程序未能启动”的问题...
--更新于2011/4/19,针对最新的VS2008补丁,VS2005/2010同样适用. VC9编译的程序在没有装过VC9(确切的说是.Net Framework3.5)的机器上运行时,如果提示&q ...
- cad转dxf格式文件太大_高版本的CAD图纸怎么转换成低版本的DXF格式?
高版本的CAD图纸怎么转换成低版本的DXF格式?因为软件版本的问题可能会有的时候使用软件而无法将图纸文件进行打开,在这种情况下应该进行的操作就是将CAD图纸文件进行版本间的转换了,具体应该怎么样进行操 ...
- java项目运行在浏览器_在 Java 程序中,能在 WWW 浏览器上运行的是 程序。_学小易找答案...
[简答题]已知:如图, AD 是△ ABC 的角平分线, DE//AC, 交 AB 于点 E , DF//AB ,交 AC 于点 F ,求证: AD ⊥ EF. [简答题]Java语言具有较好的安全性 ...
- as工程放到源码编译_关于AS高版本SDK编译生成的apk放入低版本android源码中集成编译...
做dfu功能的时候,遇到的这样一个问题.添加了dfu的依赖之后,会要求编译的sdk为28,我的AS版本默认生成的是27.然而target版本是25. // The DFU Library is imp ...
- 尚未提交线上版本_开发微信小程序如果显示尚未提交线上版本该怎么办
微信小程序审核通过发布后上传修改新内容的流程: 1.用微信小程序开发工具,打开项目,在开发工具里选择项目. 然后点击上传按钮,微信会提示你是否需要覆盖原来的版本,点击确定就行. 2.填写版本信息,然后 ...
- 在arm上运行x86动态库_用 qemu-user 在arm linux机器上运行amd64/x86程序
1. qemu-user 是什么 本来, 对于 QEmu, 我只知道它是一个模拟器, 可以像 VirtualBox/VMWare 那样跑一个操作系统, 只不过 QEmu 可以在 AMD64 上面跑针对 ...
- c free5.0运行程序错误_C程序源代码是如何在硬件上运行的?
PCB布板一些简易常用规则,你不得不看! 如何将微小型PCB线圈用做电感式传感器元件? (点击上方红字,即可获取) C语言的编译链接过程要把我们编写的一个C程序源代码转换成可以在硬件上运行的程序(可执 ...
- VC编写的程序不能在其他机器上运行的解决方案(续)
我在前面的文章里面提到由于side-by-side问题导致的VC编写的程序不能正常启动的问题的解决方案,这种方法是针对于单个可执行文件的解决方案,但是有的时候你可能会碰到另外一种情况-也是由于side ...
最新文章
- 技术图文:Python 匿名函数 VS. C# Lambda表达式
- 企业级微服务架构统一安全认证设计与实践!
- OpenCV3的机器学习算法-K-means-使用Python
- linux本地时间与utc不一致_Linux Windows 双系统时间不一致
- PHP脚本占用内存太多,解决方案
- mysql创建表格时候数据格式_mysql建表语句和数据类型
- (转) intellij idea部署web项目时的位置(Tomcat)
- HTML5网站大观:分享8个精美的 HTML5 网站案例
- 海龟绘图两小时上手C语言 - 3 正方形螺旋线
- 转载:jillzhang的文章索引 包括(Nhiberate,WCF,WPF,项目管理等内容)
- vb.net 教程 6-14 终止线程的例子
- 计算机组成原理——存储器容量扩充
- 国内高校大数据教研机构调研报告
- android+仿友盟更新,android友盟增量更新
- ECharts大屏数据可视化展示
- excel计算机一级打不开,电脑上的所有excel表格都打不开怎么处理?
- 网易创始人之一,周卓林先生
- 从键盘上输入长方形的长和宽,求长方形的周长和面积。
- PDF怎样转换成JPG图片 PDF转换为JPG图片教程 1
- OpenCV函数应用:基于二值图像的三种孔洞填充方法记录(附python,C++代码)