G ++ / LD失败:实际上不需要库时找不到库

时间:2014-01-30 16:34:04

标签: gcc linker makefile

我有一个程序foo我正在尝试编译和链接,我正在遇到鸡蛋和鸡蛋的困境。

由于原因,我将在下面解释,在给定的目录中,我被迫添加一个链接到我们构建的几个库(让我们称之为libAlibB),无论我的目标是什么。我知道我的节目实际上只需要libA;所以在构建了所有的lib并构建了这个二进制文件后,我使用ldd -u -r foo验证了libB是未使用的直接依赖项。

未使用我更改了makefile和标记,libB-Wl --as-needed-Wl --no-as-needed包围。我进行重建,再次使用ldd,这次它没有显示任何未使用的deps。到目前为止一切都很好。

现在有趣的部分:因为它未被使用,我希望如果libB找不到/可用/构建,我仍然可以编译并链接foo libA }是可用的。 (例如:如果我在尝试编译此特定测试之前进行了新的检出并且只构建了libA)。但ld

导致/usr/bin/ld: cannot find -lB错误

这表明ld需要找到libB,即使它不需要它提供的任何符号?这似乎没有意义。如果已经满足所有符号依赖性,为什么它甚至需要查看其他库? (这可以解释ld的问题以及为什么这是不可能的)

有没有办法可以说“如果你找不到这个图书馆我们不应该抱怨,我们不需要与它联系?”

承诺的理由
由于我无法控制的各种原因,由于项目的makefile层次结构,我必须在此目录中与makeflags共享许多其他测试。所有这些测试都有一个两级makefile,表示foo是假目标,他的食谱是make -f generictest.mk target=foo,而generictest.mk只是说源文件是$(target).C ,这个二进制文件需要使用我们构建的每个库,指定我们的根目录的相对路径,然后包括root的通用makefile。根目录泛型makefile扩展了所有其他东西(标志,选项,编译器,通过g ++等依赖的自动生成),最重要的是对于在generictest.mk中添加-lX中使用“use libX”的每个语句1}}到旗帜(或者在我的情况下,根据需要包裹)

虽然我很清楚有很多事情在makefile最佳实践方面非常不理想和/或非常不正确,但我没有权限/身体能力来改变它。与其他文件夹中使用的替代方法相比,其他文件为每个目标制作了这个makefile的单独具体副本,我非常喜欢它;因为这会迫使我在修改整个制作模式时编辑所有这些,并产生很多其他拼写错误和问题。

我当然可以创建另一个generictest.mk类似的文件用于某些测试,并根据实际的库需求将它们组合在一起,但如果我没有那么长的时间它就会很整洁说“你不是全部,你需要每一个,但只有你实际使用它”。

1 个答案:

答案 0 :(得分:1)

链接器无法知道不需要库。即使在链接了所有“普通”库之后,仍然存在大量未解析的符号:C运行时库的符号(printf等)。链接器不知道它们将来自何处。

如果链接器没有抱怨,即使每个符号都已经解决,我个人也会感到惊讶。毕竟在这里可能有一些奇特的东西:弱绑定等等,这可能意味着稍后在链接线上找到的符号将优先于之前找到的符号(我不是100%确定这是可能的但我不会感到惊讶。

至于你的情况,如果你知道不需要库,你不能只在链接命令行上使用$(filter-out ...)来摆脱它吗?您必须使用自己的配方为此编写自己的显式规则,而不是使用默认配方,但至少可以使用所有相同的变量。

或者,可能可以使用特定于目标的变量来玩一些技巧。为该目标声明一个特定于目标的变量,该变量重置包含“坏库”的变量,其值不包含它(可能使用上面的$(filter-out ...)),并且它将覆盖该目标的值只要。有一些微妙的问题,特定于目标的变量会覆盖“更一般”的变量,但我认为它会起作用。