lld是编译期链接器,不提供运行时依赖查看功能;它仅生成elf文件并写入dt_needed条目,运行时依赖需用readelf -d或ldd等工具分析。

lld 本身不提供运行时依赖查看功能
lld 是链接器,只在编译/链接阶段工作,它不会记录或输出“最终实际链接了哪些文件”,更不会像 ldd 那样分析运行时依赖。你用 lld 链接一个可执行文件后,它就完成了任务——生成 ELF 文件,之后的事(比如加载哪个 .so、从哪找 libc.so.6)完全交给动态链接器 ld-linux-x86-64.so.2 和系统路径机制。所以别指望 lld --verbose 或类似参数能列出“运行时会加载的库路径”。
想确认 lld 实际用了哪些输入文件和库,得看链接命令本身
lld 的行为由你传给它的参数决定,它不会自动扫描系统目录或猜测你要链什么。关键点在于:
-
lld默认**不搜索任何库路径**,除非你显式用-L指定目录、用-l请求库名 -
-lfoo不会自动变成libfoo.a或libfoo.so;它按顺序查找:libfoo.a(静态)→libfoo.so(动态),取决于是否启用了--static或--shared - 如果你用了
-v(verbose)选项,lld会打印它**尝试打开的每个文件路径**,包括.o、.a、.so,这是最接近“实际链接了什么”的线索
示例:
lld -flavor gnu -o myapp main.o -L/usr/local/lib -lcurl -lz
加 -v 后你会看到类似:
attempt to open /usr/local/lib/libcurl.a failed attempt to open /usr/local/lib/libcurl.so succeeded attempt to open /usr/lib/x86_64-linux-gnu/libz.so succeeded
这说明它跳过了静态版 libcurl,选了动态版;而 libz 直接命中了系统路径下的 .so。
验证最终二进制里“声明依赖了哪些共享库”
链接完成后,真正能告诉你“这个文件启动时需要哪些 .so”的是 ELF 动态段信息,不是 lld 的日志。用以下命令查:
-
readelf -d myapp | grep NEEDED—— 显示所有DT_NEEDED条目,即链接时写死进二进制的库名(如libcurl.so.4) -
objdump -p myapp | grep NEEDED—— 等效,输出更紧凑 -
ldd myapp—— 进一步解析这些名字到**当前系统中实际映射的路径**(注意:它会尝试加载,对不可信文件慎用)
三者关系是:lld 决定了写进 NEEDED 的名字 → readelf/objdump 读出这些名字 → ldd 根据 ldconfig -p 缓存和 LD_LIBRARY_PATH 找到对应文件路径。
容易被忽略的坑:链接时的 -rpath 和运行时路径脱节
即使 lld 成功链接并写入了 libfoo.so.1 到 NEEDED,程序运行时仍可能报 not found。常见原因:
- 没加
-rpath或--rpath,导致动态链接器不知道去哪找该库(尤其自建库放在/opt/mylib时) - 用了
-rpath '$ORIGIN/../lib',但运行时二进制不在预期目录结构里 -
ldconfig -p里没有那个库名 → 说明它不在缓存路径中,sudo ldconfig也没刷新对的配置文件 -
LD_LIBRARY_PATH覆盖了rpath,但你忘了设,或 shell 没 export
查 rpath 本身:用 readelf -d myapp | grep PATH,看 DT_RUNPATH 或 DT_RPATH 字段。它才是运行时搜库的第一依据,比 /etc/ld.so.cache 优先级还高。











