高版本gcc编译出的程序在低版本glibc机器上运行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高版本gcc编译出的程序在低版本glibc机器上运行相关的知识,希望对你有一定的参考价值。

参考技术A

比如我们用gcc 9.3.0编译程序,但需要发布的机器gcc版本是4.8.5,怎么办?

你可能想到如下方法

将libc和libstdc++静态编译,编译时带上如下参数。

glibc并不推荐静态链接,你依赖的其他库可能依赖的了glibc,并且往往是动态链接的,可以通过 nm <bin> | grep GLIBC_ 确定你的程序是否依赖了glibc。

使用携带gcc9.3.0环境的容器发布程序,是可以的。但是在一些没有容器且没有sudo权限的场合,依然不太友好。

这个方法虽然听起来不是很优雅,但其实如果你对elf文件有一些了解,是不错的方式。下面说下具体的方法。

当你有条件获得程序源码,并能够重新编译时,可以直接在编译时指定相关参数来解决。
先说编译时要增加的参数:

gcc参数

ld参数

这两个参数分别设置的elf文件中的rpath和interpreter字段。

rpath
全名 run-time search path ,是elf文件中一个字段,它指定了可执行文件执行时搜索so文件的第一优先位置,一般编译器默认将该字段设为空。elf文件中还有一个类似的字段runpath,其作用与rpath类似,但搜索优先级稍低。搜索优先级:

如果你需要使用相对路径指定lib文件夹,可以使用 ORIGIN 变量,ld会将ORIGIN理解成可执行文件所在的路径。

interpreter
动态库加载器,程序启动时,操作系统会先把控制权转交给ld-linux-x86-64.so.2,该so负责加载所有程序依赖的so。。这个字段在链接时会帮你自动设置,64bit程序一般为 /lib64/ld-linux-x86-64.so.2 。修改rpath或者LD_LIBRARY_PATH指向本地lib目录,但通过ldd程序,发现/lib64/ld-linux-x86-64.so.2这个so仍然指向系统so。原因就是这个字段是写死在elf文件中的,并不受LD_LIBRARY_PATH影响。

编译时带上这两个参数,下面只需要将你程序依赖的so打包一份,随程序进行发布即可。

当你无法编译程序时,也可以通过其他方式修改rpath和interpreter。这种情况需要使用到一个工具 patchelf ,通过 dnf install patchelf 即可安装。你可以通过它修改elf文件的rpath和interpreter:

除了绝对路径,一种比较常见的方式是在部署前,使用 pwd 获取当前路径,使用相对路径指向本地lib。

编译GCC4.8.2

    公司的机器上默认是GCC4.4.6,为了完整的体验C++11,可以自己编译一个GCC4.8.2出来(自带了更高版本的glibc)。
  以下是备忘。
1、下载GCC源码以及依赖库
2、解压
tar -jxvf gmp-6.1.1.tar.bz2
unzip mpfr-3.1.5.zip
tar -xzvf mpc-1.0.2.tar.gz
tar -jxvf gcc-4.8.2.tar.bz2
3、把依赖库放到gcc源目录中
mv gmp-6.1.1 ./gcc-4.8.2/gmp
mv mpfr-3.1.5 ./gcc-4.8.2/mpfr
mv mpc-1.0.2 ./gcc-4.8.2/mpc
4、编译
cd gcc-4.8.2/
mkdir build
cd build/
../configure --prefix=/usr/local/cswuyg/local/gcc-4.8.2
make -j16 && make install
5、使用
GCC_4_8_2_PATH=/usr/local/app/cswuyg/local/gcc-4.8.2
export PATH=${GCC_4_8_2_PATH}/bin:$PATH
export LIBRARY_PATH=${GCC_4_8_2_PATH}/lib64:$LIBRARY_PATH
export CPLUS_INCLUDE_PATH=${GCC_4_8_2_PATH}/include:$CPLUS_INCLUDE_PATH
export C_INCLUDE_PATH=${GCC_4_8_2_PATH}/include:$C_INCLUDE_PATH
export LD_LIBRARY_PATH=${GCC_4_8_2_PATH}/lib64:$LD_LIBRARY_PATH
将以上5行代码保存到~/.gcc482 文件中,每次需要使用gcc4.8.2之前,执行: source ~/.gcc482
LD_LIBRARY_PATH 是为了升级glibc。
 
本文所在:http://www.cnblogs.com/cswuyg/p/6220700.html
 

以上是关于高版本gcc编译出的程序在低版本glibc机器上运行的主要内容,如果未能解决你的问题,请参考以下文章

GLIBC_2.14 not found

编译GCC4.8.2

Linux 环境下安装 gcc 详细过程 以及安装 glibc

Linux 环境下安装 gcc 详细过程 以及安装 glibc

用VC2010以上版本编译可以在低版本XP和2003的运行程序的方法

linux安装配置交叉编译器arm-linux-gnueabi-gcc