为什么 -r 选项(可重定位)会导致 ld 找不到任何库?
介绍
在编程和计算机科学的世界里,有各种各样的技术和工具被用来解决各种问题。程序员遇到的一个常见问题是链接错误。当程序被编译和链接时,它必须找到必要的库才能运行。然而,有时链接器无法找到所需的库,从而导致链接错误。在本文中,我们将讨论为什么 -r 选项(可重定位)会导致 ld 找不到任何库,并提供示例。
什么是 -r 选项?
-r 选项是与 GNU 链接器 ld 一起使用的命令行选项。该选项指定链接器的输出应该是一个可重定位的目标文件,它是一个可以进一步链接以创建可执行文件或共享对象文件的文件。-r 选项通常用于将目标文件链接起来以创建静态库。当使用 -r 选项时,链接器不会解析目标文件中的所有未定义符号,并且输出是一个可重定位的目标文件,可用于以后的进一步链接。
为什么 -r 选项会导致 ld 找不到任何库?
当使用 -r 选项时,ld 不会查找任何库,因为它假设所有必要的符号都在输入目标文件中定义。这意味着,如果存在任何未定义的符号,ld 将无法在任何库中找到它们,从而导致链接错误。
示例
为了更好地理解为什么 -r 选项会导致 ld 找不到任何库,让我们考虑一个示例。假设我们有两个目标文件 a.o 和 b.o,我们希望将它们链接起来以创建一个静态库。这两个目标文件包含一些需要解析的未定义符号。
如果我们使用以下命令链接目标文件:
$ ld -r a.o b.o -o libab.o
输出将是一个可重定位的目标文件 libab.o,可用于以后的进一步链接。但是,如果我们尝试链接 libab.o 以创建可执行文件,我们将收到一个链接错误,因为目标文件中的未定义符号未得到解析。
$ ld libab.o -o myprog
未定义符号:_foo _bar
在这种情况下,ld 未找到包含 _foo 和 _bar 符号的任何库,导致链接错误。
解决方案
为了解决由 -r 选项引起的链接错误,我们需要显式地链接必要的库。这意味着我们需要使用 -l 选项来指定包含未定义符号的库。
例如,如果目标文件中的未定义符号在 libmylib.a 库中定义,我们可以如下链接目标文件和库:
$ ld -r a.o b.o -lmylib -o libab.o
这将链接目标文件和库以创建一个可重定位的目标文件 libab.o,可用于以后的进一步链接。
其他信息
-r 选项在创建静态库时很有用,因为它允许我们创建一个可用于创建多个静态库的中间目标文件。这节省了时间并减少了冗余,因为我们不必每次想要创建静态库时都重新编译目标文件。
-r 选项也可用于创建可重定位的共享库。共享库是在运行时加载到内存中的库,可以由多个程序共享。在创建共享库时,我们可以使用 -r 选项创建一个中间可重定位的目标文件,该文件可以与其他目标文件和共享库链接以创建共享库。
需要注意的是,-r 选项不会阻止 ld 在创建可执行文件或共享库时搜索库。该选项仅影响链接器在创建可重定位目标文件时的行为。
结论
总之,-r 选项会导致 ld 找不到任何库,因为它假设所有必要的符号都在输入目标文件中定义。如果存在任何未在输入文件中定义的未定义符号,这可能会导致链接错误。为了解决链接错误,我们需要使用 -l 选项显式地链接必要的库。了解 -r 选项的工作原理以及如何解决由该选项引起的链接错误对于希望创建静态库和可执行文件的程序员来说非常重要。