前言什么是 gcc[gcc 官方网站](https://gcc./) GCC(GNU Compiler Collection,GNU编译器套件),是由 GNU 开发的编程语言编译器。它是以 GPL(General Public License)许可证所发行的自由软件,也是 GNU 计划的关键部分(GPU 是一个软件工程项目,是 GNU's Not Unix 的缩写)。 GCC 原本作为 GNU 操作系统的官方编译器,现已被大多数类 Unix 操作系统(如Linux、BSD、Mac OS X等)采纳为标准的编译器,GCC 同样适用于微软的Windows。GCC 是自由软件过程发展中的著名例子,由自由软件基金会以 GPL 协议发布。 什么是 glibc[glibc 官方网站]( glibc 是 gnu 发布的 libc 库,即 c 运行库。glibc 是 linux 系统中最底层的 api,几乎其他任何的运行库都会依赖 glibc. glibc 除了封装 linux 操作系统所提供的系统服务外,它本身提供了许多其它一些必要服务的实现,主要有:
gcc 和 glibc 的关系首先,gcc 是编译器,基本上 linux 下所有程序(包括内核)都是 gcc 编译的,libc 也是。但 gcc 和 libc 又是相互依赖的,什么意思呢?就是在编译 c/cpp 代码时,既需要 gcc,也需要 libc. gcc 发行版本截止2021年8月,最新版本已经到 gcc11.2 了。 glibc 发行版本截止2021年8月,最新版本已经到 glibc2.34 了,历史版本有 glibc2.29、2.30、2.31、2.32、2.33 等。 查看命令1、查看当前系统的 glibc 版本
/lib/x86_64-linux-gnu/libc.so.6 为什么这个库可以直接运行呢?原来是在 libc 的代码中有一点小手脚: void__libc_main (void) { __libc_print_version (); _exit (0); }
ldd 命令也是 glibc 提供的,所以也能查看 glibc 版本: ldd --version 2、查看 glibc 的 api 版本strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC 3、查看 so 信息`objdump -p test_gcc.so`,其他类似命令还有 `nm` 和 `readelf` 4、查看当前so依赖哪些so
`ldd test_gcc.so`
`objdump -x test_gcc.so | grep NEEDED` 5、获取 gcc 依赖的某个 so 文件位置`gcc --print-file-name=libz.so.1` 6、查看当前使用的 gcc 版本和引用的头文件路径`echo | gcc -v -x c -E -` 7、查看当前so使用了GLIBC_2.23中哪些函数`objdump -T test_gcc.so | grep GLIBC_2.23` 8、查看当前so使用的memcpy版本`nm test_gcc.so | grep memcpy -w``objdump -T /lib/x86_64-linux-gnu/libc.so.6 | grep memcpy` 9、设置 c、c++ 头文件路径`export CPLUS_INCLUDE_PATH=/opt/compiler/gcc-8.2/x86_64-custom-linux-gnu/include/c++/8.2.0:/usr/include/x86_64-linux-gnu/``export C_INCLUDE_PATH=......` 10、编译时如何设置链接器版本指定正确的 ldd 路径,也就是对应具体的 glibc 版本(非常重要)。 11、设置链接库路径
先查看:`echo $LD_LIBRARY_PATH`,可通过该环境变量直接设置。 或者,`gcc --print-search-dirs`
`ldconfig -v`: 查看所有动态链接库 `vim /etc/ld.so.conf`,显示 `include /etc/ld.so.conf.d/*.conf`,然后`cd /etc/ld.so.conf.d` 修改完之后,要重新运行下 `ldconfig` 解释: linux 下的共享库机制采用了类似于高速缓存的机制,将库信息保存在`/etc/ld.so.cache`里边。 程序连接的时候首先从这个文件里边查找,然后再到`ld.so.conf`的路径里边去详细找。 这就是为什么修改了`ld.so.conf`要重新运行一下`ldconfig`的原因 12、c++ 标准库: stdlibc++ 和 libc 的版本号是不一样的`objdump -T /usr/lib/gcc/x86_64-linux-gnu/5/libstdc++.so | grep GLIBCXX` 13、gcc 头文件的搜索路径顺序1. 优先搜索`-I`指定的路径2. 查找GCC的环境变量`C_INCLUDE_PATH`/`CPLUS_INCLUDE_PATH`/`OBJC_INCLUDE_PATH`指定的路径3. 查找默认的搜索路径`/usr/include`、`/usr/local/include` 14、gcc搜索链接库(编译期 + 运行期)的顺序gcc在编译时按照如下顺序寻找所需要的库文件: 1. gcc会去找`-L`指定的目录 2. 再找gcc的环境变量`LIBRARY_PATH` 3. 再找内定目录
这是当初 compile gcc 时写在程序内的。 这里有两个问题:
这时,使用`-Wl`,`--no-undefined`参数,如果使用了 include 文件,链接器却找不到相应的实现,就会产生错误提示。
运行时动态库的搜索路径的先后顺序是: 1. 编译目标代码时指定的动态库搜索路径;这是通过gcc的参数`-Wl,-rpath=`指定。当指定多个动态库搜索路径时,路径之间用冒号 :分隔 2. 环境变量`LD_LIBRARY_PATH`指定的动态库搜索路径 3. 配置文件`/etc/ld.so.conf`中指定的动态库搜索路径 4. 默认的动态库搜索路径,如:`/lib`, `/usr/lib` 注意: 1. 动态库搜寻路径并不包括当前目录,所以当即使可执行文件和其所需的so文件在同一文件夹,也会出现找不到问题 2. 一般不推荐直接修改环境变量,而是修改`/etc/ld.so.conf`,将相应的路径添加上,然后`ldconfig`一下就好 3. ldconfig做的这些东西都与运行程序时有关,跟编译时一点关系都没有,编译的时候还是该加`-L`就得加,不要混淆了 4. 往`/lib`和`/usr/lib`里面加 `lib`,是不用修改`/etc/ld.so.conf`的,但是完了之后要调一下`ldconfig`(很重要),不然这个`lib`会找不到。而往其他目录加`lib`,需要修改`/etc/ld.so.conf`,并且要`ldconfig`一下。 15、如何安装指定版本glibc
../sysdeps/x86_64/multiarch/strstr.c:47:30
|
|
来自: 菌心说 > 《编程+、计算机、信息技术》