为什么-r选项(可重定位)使ld找不到任何库?

Jer*_*wen 5 linux relocation ld binutils

使用GNU ld 2.21运行Debian/Linux x86_64.

很简单,如果我链接

ld -o main main.o /usr/lib/crti.o /usr/lib/crt1.o /usr/lib/crtn.o -lc -lm
Run Code Online (Sandbox Code Playgroud)

它有效,但是当我链接时

ld -r -o main1.o main.o /usr/lib/crti.o /usr/lib/crt1.o /usr/lib/crtn.o -lc -lm
Run Code Online (Sandbox Code Playgroud)

它抱怨

ld: cannot find -lc
ld: cannot find -lm
Run Code Online (Sandbox Code Playgroud)

我实际上并没有尝试以这种方式编译代码,而是我试图弄清楚为什么别人的测试看看库是否存在无效.(因此我真的不明白发生了什么ld......通常我只是用GCC来链接)

为什么要ld以可重定位的方式链接使它突然无法找到库?如果我只是想测试它-lm存在,我还应该做些什么

ld -r -lm
Run Code Online (Sandbox Code Playgroud)

这样它会找到图书馆吗?

如果你想查看我正在处理的源代码,可以在这里下载:https://github.com/jeremysalwen/ESPS (注意,第一次提交是原始源代码,后续的是更改我亲自做过.)

Jon*_*ler 4

macOS X

\n

在 MacOS X 上,该选项的手册页ld非常明确-r

\n
\n

-r合并目标文件以生成文件类型为 MH_OBJECT 的另一个 mach-o 目标文件。

\n
\n

因此,如果您使用的是 MacOS X,问题是-lm不是 Mach-O 目标文件,也不是-lc. 但是,理论上,如果您有目标文件main.oobj1.o并且obj2.o您这样做:

\n
cp obj1.o ./-lm\ncp obj2.o ./-lc\nld -r -o main1.o main.o -lm -lc\n
Run Code Online (Sandbox Code Playgroud)\n

那么它可能会起作用。实际上,事实并非如此,并且您会遇到以下错误:

\n
ld: warning: unexpected dylib (/usr/lib/libm.dylib) on link line\nld: warning: unexpected dylib (/usr/lib/libc.dylib) on link line\n
Run Code Online (Sandbox Code Playgroud)\n

但是,运行:

\n
ld -r -o main1.o -arch x86_64 main.o obj1.o obj2.o\n
Run Code Online (Sandbox Code Playgroud)\n

装载机工作时没有任何抱怨。

\n

Linux

\n

在 Linux 上,手册页ld不太明确,但说:

\n
\n

-i 执行增量链接(与选项 -r 相同)。

\n

-r
\n--relocatable

\n

生成可重定位的输出——即生成一个输出文件,该文件又可以用作ld. 这通常称为部分链接。作为副作用,在支持标准 Unix 幻数的环境中,此选项还会将输出文件\xe2\x80\x99s 幻数设置为“OMAGIC”。如果未指定此选项,则会生成绝对文件。当链接 C++ 程序时,此选项不会解析对构造函数的引用;为此,请使用-Ur.

\n

当输入文件与输出文件的格式不同时,仅当该输入文件不包含任何重定位时才支持部分链接。不同的输出格式可能有进一步的限制;例如,某些基于“a.out”的格式根本不支持与其他格式的输入文件的部分链接。

\n

此选项与 执行相同的操作-i

\n
\n

从字里行间看,这也获取目标文件并将它们转换为目标文件;它不会添加库。如果您考虑一下,不会创建包含对库的引用的目标文件。

\n

因此,尽管在某些平台上可以在使用该-r选项时向链接器(加载器)指定库,但在其他平台上却不能。

\n

解决方法

\n

最初的问题是确定库是否存在。为什么不模仿它的autoconf做法,并创建一个main.c包含对库中定义的符号的引用的偏好,但它可以简单地包含:

\n
int main(void){return 0;}\n
Run Code Online (Sandbox Code Playgroud)\n

并用 C 编译器编译并链接它:

\n
cc -o main main.c -lm -lc\n
Run Code Online (Sandbox Code Playgroud)\n

如果它不起作用,则说明缺少其中一个库。如果您已经检查过它-lc是否存在,那么您可以推断它-lm丢失了。

\n