gcc -v 显示完整编译链,包括预处理、编译、汇编和链接各阶段调用的底层工具(如cc1、as、collect2/ld)及参数;其中以collect2或ld开头的命令行即真实链接动作,含所有输入文件、库路径和展开后的库全路径。

gcc -v 会显示完整链接过程
直接加 -v 就能看到链接阶段调用了什么、传了哪些参数、加载了哪些库。它不是“查看链接”,而是让 GCC 把整个编译链(包括链接)的底层命令都打印出来。
常见错误是只用 gcc -v -o app main.c,但没注意输出里真正执行链接的是 collect2 或 ld 这一行——那一行之后的所有参数才是链接器实际收到的。
- 输出中以
collect2或ld开头的那条长命令,就是真实链接动作 - 里面会列出所有
.o文件、.a静态库、.so动态库路径、-lxxx展开后的完整路径(比如-lm变成/usr/lib/x86_64-linux-gnu/libm.so) - 如果链接失败,错误就出在这条命令执行时,而不是前面的编译阶段
gcc -Wl,--verbose 只显示链接器内部行为
-Wl,--verbose 是把 --verbose 透传给链接器 ld,它不会像 -v 那样展示 GCC 包装层,而是直接让 ld 打印它自己搜索路径、尝试打开哪些库、是否找到符号等细节。
适用场景:你已经确认是链接问题(比如 undefined reference),想看 ld 到底搜了哪些目录、加载了哪些库文件。
- 必须和
-o一起用,否则没链接动作,ld不会触发--verbose - 输出非常冗长,重点看
attempt to open和found行 - 如果看到
attempt to open /usr/lib/libxxx.so failed,说明路径或库名不对
gcc -Xlinker --verbose 不起作用
-Xlinker 是用来透传单个参数给链接器的,但 --verbose 是 ld 的原生命令行选项,不是链接器脚本或输入文件,所以 gcc -Xlinker --verbose 会被拒绝或静默忽略。
正确写法只有两种:-Wl,--verbose(推荐),或者直接调用 ld --verbose 查看系统默认链接脚本。
-
-Wl,表示后面所有逗号分隔的内容都传给链接器;--verbose必须紧贴在逗号后,不能有空格 -
ld --verbose输出的是链接脚本(linker script),不是本次链接过程,别混淆 - 别写成
-Wl,--verbose,xxx去试图传多个参数——除非你明确知道ld支持逗号分隔
链接失败时优先看 collect2 那行的 -L 和 -l
当报 undefined reference to 'foo',不要急着改代码,先用 gcc -v 看 collect2 行里有没有你期望的 -L/path/to/lib 和 -lmylib。
最容易被忽略的是:路径存在、库文件名也对,但 libmylib.so 缺少 soname 符号链接(比如只有 libmylib.so.1.2,没有 libmylib.so 指向它),ld 就找不到。
-
ls -l /path/to/lib/libmylib*确认软链接是否存在 -
readelf -d libmylib.so | grep SONAME看实际 soname 是什么 -
gcc -L/path/to/lib -lmylib中的mylib必须和SONAME去掉lib前缀、去掉版本号后的名字一致











