疑难错误:/usr/bin/ld: cannot find -lxxx

·2018·5 分钟
AI摘要: 本文讲述了在开发过程中遇到的一个编译错误,即`/usr/bin/ld: cannot find -lLLVM-13-rust-1.58.0-nightly`。原因是该库的路径被写入了zshrc的配置文件中的`LD_LIBRARY_PATH`位置,导致编译器无法找到。通过查阅资料,发现`LIBRARY_PATH`和`LD_LIBRARY_PATH`的区别,并了解到它们在编译和运行时的作用及影响工具。同时,文章还提供了如何同时使用这两个变量的建议,以及在使用时应考虑的安全性问题、调试问题和持久化配置。

前几天做在做开发的时候,遇到一个编译报错问题,弄到半夜3点才解决。

具体错误是:/usr/bin/ld: cannot find -lLLVM-13-rust-1.58.0-nightly, 也就是gcc编译的时候缺少lLLVM-13-rust-1.58.0-nightly的第三方库,但是这个库的存放位置已经被写入zshrc的配置文件中的LD_LIBRARY_PATH位置,所以百思不得其解,最终查看各种资料才发现LIBRARY_PATHLD_LIBRARY_PATH的区别。


1. LIBRARY_PATH

  • 用途:

    • 用于 编译阶段,告诉编译器(如 gccclang)在哪里查找静态库 (.a) 和动态库 (.so.dylib)。

    • 编译器在链接时使用这个路径来找到依赖的库文件。

  • 常见场景:

    • 当你编译程序并需要链接某些库(例如 gcc main.c -o main -lfoo),如果 foo 不在默认的库搜索路径下,你可以通过设置 LIBRARY_PATH 来告诉编译器去哪里找。
  • 影响工具:

    • 主要被编译器(如 gccclang)使用。
  • 示例:

    
    export LIBRARY_PATH=/custom/lib/path:$LIBRARY_PATH
    
    gcc main.c -o main
    

2. LD_LIBRARY_PATH

  • 用途:

    • 用于 运行阶段,告诉动态链接器(ld.sold-linux.so)在加载动态库时,优先从哪里查找 .so 文件。

    • 这是运行时的动态库搜索路径。

  • 常见场景:

    • 当运行的程序依赖的动态库不在默认的搜索路径(如 /usr/lib/lib)中时,可以通过设置 LD_LIBRARY_PATH 告诉系统去哪里找动态库。
  • 影响工具:

    • 主要被动态链接器(ld.so)使用。
  • 示例:

    
    export LD_LIBRARY_PATH=/custom/lib/path:$LD_LIBRARY_PATH
    
    ./main
    

主要区别

| 属性 | LIBRARY_PATH | LD_LIBRARY_PATH |

| ------------ | ------------------------------ | --------------------------------------- |

| 作用阶段 | 编译阶段 | 运行阶段 |

| 使用场景 | 查找静态库和动态库以供链接 | 加载动态库以供程序运行 |

| 使用工具 | 编译器(如 gccclang) | 动态链接器(如 ld.sold-linux.so) |

| 作用对象 | 静态库 (.a) 和动态库 (.so) | 动态库 (.so) |


如何同时使用

如果你在开发时需要编译和运行程序,并且库文件不在系统默认路径中,你可能需要同时设置这两个变量。


export LIBRARY_PATH=/custom/lib/path:$LIBRARY_PATH

export LD_LIBRARY_PATH=/custom/lib/path:$LD_LIBRARY_PATH

gcc main.c -o main

./main

这样,编译器和动态链接器都能正确找到所需的库文件。


注意事项

  1. 安全性问题:

    • 滥用 LD_LIBRARY_PATH 可能引入安全风险,特别是在多用户系统中,攻击者可以通过伪造动态库进行攻击。

    • 如果可能,优先使用 rpathRUNPATH 来指定运行时库路径,而不是依赖 LD_LIBRARY_PATH

  2. 调试问题:

    • 设置过多的路径可能导致链接器行为复杂化,建议仅在必要时设置,并注意路径的优先级。
  3. 持久化配置:

    • 如果需要长时间使用这些变量,可以将它们添加到 ~/.bashrc~/.zshrc 中。

总结

  • 编译时找不到库 → 设置 LIBRARY_PATH

  • 运行时找不到库 → 设置 LD_LIBRARY_PATH

  • 它们的功能不同,不是同一个东西。

Kaggle学习赛初探