gcc -L命令混乱

时间:2015-01-30 07:13:10

标签: c++ gcc

假设我有一个共享库文件libdemo.so,其中libdemo.so是最后一个链接器。

如果我想构建可执行文件,并且库文件在当前工作目录中,我将其与-L. -ldemo标志链接。

但是当我运行可执行文件时,除非我指定库路径LD_LIBRARY_PATH=.,否则可执行文件找不到该链接。那么为什么需要额外的LD_LIBRARY_PATH设置呢?标志用于链接时库路径,环境变量应该是运行时库路径。

或者,如果我构建可执行文件并使用-Wl,-rpath,.指定运行时库路径,我可以省略-L. -ldemo

我知道这与链接时和运行时有关,但我不清楚它们之间的区别。例如,当不使用-rpath时,如果可执行文件需要-L. -ldemo来查找库文件,那么LD_LIBRARY_PATH实际上做了什么?当使用后一种方法时,如果指定-rpath意味着将目录位置复制到运行时库路径中,为什么这也允许省略-L. -ldemo

如果链接时库路径和运行时库路径不同,那么后一种方法在构建时不需要链接时库路径?链接时库路径和运行时库路径之间有什么区别?

2 个答案:

答案 0 :(得分:1)

因为链接是由两个不同的链接器实例完成的。

当你编译&链接您的程序,像/usr/bin/ld这样的链接器检查外部引用并构建您的可执行文件,添加外部引用libdemo.so

运行程序时,运行时链接程序/lib64/ld-linux-x86-64.so.2(或通常说ld.so)会加载所有需要的共享对象。有几个原因-L未保存:

  • libdemo.so没有必要位于编译期间的同一路径上(因为您可以将二进制文件复制到另一台主机上,该路径是内部构建路径等)。
  • 它可能不安全,所以ld.so通常会寻找非root用户无法写入的“可信”路径列表

但是,有些情况下保存-L会很有用(例如,软件安装到/opt),因此某些的Unix引入了RPATH。

答案 1 :(得分:0)

经过一些研究(阅读教科书),我找到了我正在寻找的答案。

基本上,由于可执行文件不再包含目标文件的副本,因此需要某种方法来识别它所需的共享库。在链接阶段,共享库的名称嵌入在可执行文件中,但尚未指定特定位置。所以-L. -ldemo实际上只是提供库文件的名称。请注意,在问题中,我说在设置-L. -ldemo时未指定-rpath。那是因为在那个命令中我实际上直接传递了库的名称libdemo.so。如果我没有这样做,那么用-L. -ldemo指定它是必要的。

随后提供运行时库路径以指定执行时的确切位置。