c++ - makefile 混淆中的链接器库路径

标签 c++ c linux makefile linker

我已经编程了一段时间,但我仍然不完全理解链接器的行为方式。

例如,今天我下载并安装了一个库,我想在我的 Linux 应用程序中使用它。 (它是 Xerces - 用于解析 XML 文件)。

我创建了一个 makefile 并在我的命令中为它提供了 .so 和 .a 文件的路径:-L/usr/local/lib 并告诉它要包含的库的名称:-lxerces-c-3.1 .

我的应用程序编译正常,但在运行时失败,显示“无法打开共享对象文件 libxerces-c-3.1.so”。当我在 makefile 中正确地给它指定路径和名称时,为什么会这样?

然后我将库路径添加到我的 .bashrc 文件中的 LD_LIBRARY_PATH 变量,然后它就可以工作了。这很好,但如果我现在在我的 makefile 中删除库的路径并且甚至不包括库的名称,它仍然有效。

我对这里发生的事情感到困惑。它如何仅通过将路径分配给 LD_LIBRARY_PATH 变量就能找到正确的库,并且只有在我这样做时才会起作用?我在别处读到甚至不使用 LD_LIBRARY_PATH。

我很感激任何对此的回答。这个问题有点长,希望不是题外话,但我希望其他人也能从中吸取教训。谢谢

最佳答案

编译和运行是两回事。 :)

1) make 文件包含有关如何构建应用程序的规则。因此,当您编写如下规则时:

    -L/usr/local/lib -lxerces-c-3.1

您正在将选项传递给链接器。 -L 选项告诉链接器将附加库(在本例中为“/usr/local/lib”)添加到链接器的搜索路径。 -l 选项命名应该链接的库。

2) 当你去运行一个可执行文件时,加载器需要找到所有需要的库。例如,在 Linux 系统上,您可以使用 ldd 命令查看使用了哪些共享库。例如在我的系统上:

ldd FEParser
    linux-vdso.so.1 =>  (0x00007ffcdc7c9000)
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f835b143000)
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f835ae3d000)
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f835ac27000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f835a862000)
/lib64/ld-linux-x86-64.so.2 (0x00007f835b447000)

从这里,您可以看到链接到“=>”标记左侧的库的名称,以及右侧的库路径。如果找不到库,它将显示为丢失。

现在,在您的情况下,由于提供了要使用的路径和库名称,您能够成功编译和链接您的程序。由于加载程序无法在运行时找到库,您无法运行该程序。

这里有几个选项:

1) 您可以将库移动到加载程序搜索路径中的目录中。

2) 您可以修改 LD_LIBRARY_PATH 以将其他目录添加到加载器搜索路径。此外,LD_LIBRARY_PATH 中指定的目录将传递给链接器(它将附加在所有 -L 标志之后)。你确实需要小心这一点,就好像你在全局设置它一样(比如在 .bashrc 中),那么它会影响你所做的所有编译。您可能想要也可能不想要这种行为。

3) 正如其他人指定的那样,您可以使用 -Wl,rpath=....,但它已被弃用,我很少使用它。

4) 如果您需要将库安装在不寻常的位置,您可以在 /etc/ld.so.conf.d 下添加一个文件,其中包含例如(文件是 yaml .conf):

# yaml default configuration
/opt/yaml/lib

在系统启动时,加载程序读取此目录中的所有文件并将路径附加到加载程序路径。如果您对该目录进行了修改,您可以使用 ldconfig 命令使加载程序重新处理 /etc/ld.so.con.d。注意我知道这适用于 GNU/Linux 的 centOS 和 Ubuntu 风格 - 不能权威地谈论其他风格。

关于c++ - makefile 混淆中的链接器库路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34909040/

相关文章:

android - Linux 应用程序可以在 Android 中运行吗?

c++ - mex : undefined reference to ".." 错误

c# - 我可以在不使用 "unsafe"的情况下使用二维数组编码 C 结构吗?

c++ - 邻域点删除的并行化

c++ - 什么是 WaitNamedPipe 的重叠 I/O 替代方案?

linux - 重定向输出时创建嵌套文件

在 Linux 中收集具有不同参数的 C 代码的输出

c++ - 唯一指针如何保证唯一性?

c++ - 线程似乎在应该不同时获得相同的线程参数(PThreads)

C++接口(interface)设计问题