【发布时间】:2014-01-30 16:34:04
【问题描述】:
我有一个程序foo 我正在尝试编译和链接,但我遇到了先有鸡还是先有蛋的困境。
出于我将在下面解释的原因,在给定目录中,我不得不添加指向我们构建的几个库的链接(我们称它们为 libA 和 libB),而不管我的目标是什么。我知道我的程序实际上只需要libA;所以在构建了所有库并构建了这个二进制文件之后,我用ldd -u -r foo 验证了libB 是一个未使用的直接依赖项。
由于未使用,我更改了 makefile 和标志,使 libB 被 -Wl --as-needed 和 -Wl --no-as-needed 包围。我进行了重建,再次使用ldd,这次它没有显示任何未使用的部门。到目前为止一切顺利。
现在有趣的部分:由于它未使用,我希望如果 libB 未找到/可用/构建,我应该仍然能够编译和链接 foo,只要 libA 可用。 (例如:如果我在尝试编译此特定测试之前进行了新的结帐并且只构建了libA)。但是ld 与/usr/bin/ld: cannot find -lB 出错
这表明ld 需要找到libB,即使它不需要它提供的任何符号?这似乎没有意义。如果已经满足所有符号依赖项,为什么还要查看这个其他库? (这可以解释 ld 的问题以及为什么这是不可能的)
有没有办法让我说“嘿,如果你找不到这个库,不要抱怨,我们不需要链接它?”
承诺的理由如下
由于我无法控制的各种原因,由于项目 makefile 层次结构,我必须与此目录中的许多其他测试共享 makeflags。所有这些测试都有一个两级生成文件,上面写着foo 是一个虚假目标,他的配方是make -f generictest.mk target=foo,而generictest.mk 只是说源文件是$(target).C,这个二进制文件需要使用每个我们构建的库,指定到我们的根目录的相对路径,然后包含根的通用 makefile。根目录通用 makefile 扩展了所有其他内容(标志、选项、编译器、通过 g++ 自动生成依赖项等),最重要的是,对于在 generictest.mk 中说“使用 libX”的每个语句,它会将 -lX 添加到旗帜(或者在我的情况下,根据需要包裹在旗帜中)
虽然我很清楚在 makefile 最佳实践方面有很多非常不理想和/或非常不正确的事情,但我没有权限/物理能力来更改它。与其他文件夹中使用的替代方法相比,其他文件夹为每个目标制作此 makefile 的单独具体副本,我非常喜欢它;因为这迫使我在想要修改我们的整个制作模式时编辑所有这些,并产生许多其他拼写错误和问题。
我当然可以创建另一个类似generictest.mk 的文件以用于某些测试,并根据实际库需要将使用每个测试的那些组合在一起,但如果我不必这样做,那将是一种整洁,只要我说“你不需要全部,你需要它们中的每一个,但前提是你实际使用它”。
【问题讨论】:
-
makefile 设计错误——或者是根据现在过时的假设设计的。重新设计它,这样您就不会尝试链接那些既不存在也不对所讨论的测试程序不必要的库。另一种选择是确保构建
libB——它成为makefile(generictest.mk)中目标的显式依赖。当然,无论如何,它应该是;如果程序与其链接,则程序(或链接命令行)取决于现有的库。 -
@JonathanLeffler 我知道它的设计严重错误。我只是没有能力改变它。我再次同意你所说的一切;但这对我没有帮助。我可以让它依赖于 libB,但我不想在不需要的时候浪费构建 libB 的时间。它们不存在只是因为我没有建造它们;在“真实”构建中,它们通常都会存在。
-
好的;如果你不听智慧的话,你将不得不继续在破损建筑的泥沼中溃烂。或者等待一些天才想出一个解决方案。但是最好的办法是不要与编译器和链接器强加的系统作斗争;最好的办法是修复滥用编译器和链接器的工具(即
generictest.mk文件)中的缺陷。你的电话……玩得开心! (“我无法修复”在软件中并不适用;软件具有延展性——这就是它被称为 soft 的原因。如果是当权者在强加规则,请问他们如何解决你的困境。) -
?我不反对你。我正在尝试找到一种解决方法来解决我遇到的难题。我无法从头开始更改整个系统;这不在我的权限范围内。如果由我来决定,我会完全按照你的要求去做,而不必问这个荒谬的问题。
-
软件只有在您的经理和旧版兼容性协议允许的情况下才具有可塑性。仅仅因为它可以改变并不意味着它值得他们花时间;在现实世界中,您经常会发现人们对这种改变的“风险”持怀疑态度,即使您和我都知道这是等待发生的世界末日:-p 欢呼,尽管我认为您重申了我的目前正在使用另一个文件。