当进行链接时,库依赖关系是如何工作的?

4
我是一名有用的助手,可以为您翻译文本。
我有一个库libmya.so和一个库libmyb.so。在libmyb.so中的函数依赖于libmya.so中的函数。此外,我有一个可执行文件myexe,它依赖于libmyb.so。当我制作这些库时,应该在哪些规则中放置-l选项?
是应该选择1):
libmya.so: $(OBJ_FILES)
    $(CPP) $(LDFLAGS) -o $@ $^

libmyb.so: $(OBJ_FILES)
    $(CPP) $(LDFLAGS) $(LIBS) -o $@ $^ -lmya

myexe: $(OBJ_FILES)
    $(CPP) $(LDFLAGS) $(LIBS) -o $@ $^ -lmyb

或者2)
libmya.so: $(OBJ_FILES)
    $(CPP) $(LDFLAGS) -o $@ $^

libmyb.so: $(OBJ_FILES)
    $(CPP) $(LDFLAGS) $(LIBS) -o $@ $^

myexe: $(OBJ_FILES)
    $(CPP) $(LDFLAGS) $(LIBS) -o $@ $^ -lmya -lmyb

还是其他组合?

1
你为什么要使用CPP?那通常是C预处理器;CXX通常是C++编译器。 - Fred Nurk
@Fred Nurk:我来的时候就是这样的!谢谢你的提示。 - Matthew Smith
你使用的是什么操作系统?我猜测你在处理so文件,应该是Unix系统,但最好还是澄清一下。 - mgiuca
2个回答

1

我会选择选项1(虽然选项2也可以,但我不建议使用,因为任何链接exe的人都需要记住所需的所有传递库)。

然而,这个建议仅适用于制作so文件,就像你上面所做的那样。 so文件(共享对象)是“智能”库,类似于可执行文件,除了它们没有主函数。 so文件可以链接到其他库(如可执行文件),当一个可执行文件链接到一个so文件时,它将自动递归包含so文件的依赖项。

因此,您创建的so文件应该与其所有依赖项链接。

一个“愚蠢”的库,比如a文件(静态库),则需要在可执行文件中进行所有链接(选项2)。

我建议您使用ldd工具来调查可执行文件和so文件的依赖关系,以了解其工作原理。

为了说明为什么选项1更好,可以尝试运行ldd /usr/lib/libpng.so来查看一个真实世界的例子。请注意,libpng与libz链接在一起。如果没有这个链接,任何链接到libpng的人也需要链接到libz。但是现在,你可以链接到libpng而不必知道libz的存在。


0

在构建库时,它们之间并不相互依赖。依赖于它们的是可执行文件(exe或dll)。库只是函数和/或数据的集合。当exe/dll在链接时使用其内容时,它们必须存在(从哪里来并不重要)。构建库时,库不会被链接,而是由图书管理员归档组成它们的对象文件。

一个库中的函数可以使用另一个库中的函数,但只有在exe/dll的链接时间才能解决这些依赖关系(这意味着两个库都必须被链接)。


看我的答案。两个选项都可以,但选项1更好。你的说法不正确(至少在Unix上是这样,因为so文件存在,所以问题可能是关于Unix的),库不仅仅是“愚蠢”的对象集合,而且它们是被链接的。对于a文件是正确的,但对于so文件则不然。库可以(而且应该)与它们的依赖项链接。 - mgiuca
@mgiuca:你不能读吗?我很明确区分了库和dll。供您参考,dll是可执行代码,因此必须链接。而库只是包含函数和代码的一组目标文件。 - engf-010
啊,我现在明白了这个区别。之前非常不清楚,而且术语也有误 -- 你使用“库”这个词作为Unix中所称的“静态库”或“归档”(一个a文件)的特定术语。你使用Windows特定的术语“dll”来表示Unix中所称的“共享库”或“共享对象”(一个so文件)。由于作者正在处理共享对象,说库不需要链接是具有误导性的,并且没有回答问题。 - mgiuca

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接