GNU Autotools 构建通过但运行时共享库依赖符号查找错误排查
问题根本原因
当前主流Linux发行版的GNU链接器默认开启--as-needed优化选项,逻辑是:扫描链接参数中的动态库时,仅当当前存在未解析的符号需要由该库提供时,才会将该库标记为二进制文件的NEEDED依赖。
你的配置里-lb写在main_LDADD中,而main.c本身没有调用func_b(),所有对func_b()的引用都在liba.so内部。链接器扫描到-lb时,仅检查main程序的未解析符号(此时只有func_a()未解析,已经由liba.so满足),发现main没有用到libb.so的任何符号,就直接丢弃了libb.so的依赖,最终main的依赖里没有libb.so,运行时liba.so找不到func_b()就报错。
当你在main.c里直接调用func_b()时,main会产生func_b()的未解析符号,链接器扫描到-lb时检测到该符号需要libb.so满足,就会保留libb.so作为main的依赖,问题自然消失。
解决方案
有两种常用的修复方案,优先推荐第一种,符合动态库依赖的设计逻辑:
- 方案1:将libb.so的依赖绑定到实际使用它的liba.so上
修改你的Makefile.am,给liba.la添加依赖配置:
这样编译liba.so时,链接器会检测到liba存在liba_la_LIBADD = -lbfunc_b()的未解析符号,自动将libb.so标记为liba.so的NEEDED依赖,不管main程序如何链接都能正常找到符号。 - 方案2:强制main程序保留libb.so的依赖
如果你出于特殊原因不想修改liba的编译配置,可以修改main的链接参数,用--no-as-needed强制链接器保留libb依赖:
该参数会临时关闭main_LDADD = liba.la -Wl,--no-as-needed -lb -Wl,--as-needed--as-needed优化处理-lb,强制将libb.so标记为main的NEEDED依赖,后面再加-Wl,--as-needed是恢复默认优化,避免影响后续其他库的链接逻辑。
验证方法
修复后可以用以下命令查看依赖是否正确:
- 查看main程序的依赖:
readelf -d main | grep NEEDED - 查看liba.so的依赖:
readelf -d .libs/liba.so | grep NEEDED
如果输出中包含libb.so说明配置生效。
如果仍有问题,可确认/usr/local/lib是否在系统动态库搜索路径中,可将路径写入/etc/ld.so.conf.d/custom.conf后执行sudo ldconfig刷新缓存。
内容的提问来源于stack exchange,提问作者drymon
相关产品推荐
相关产品推荐

