使用VPATH的GNU make:目标显示为循环,但实际上不应该是

时间:2013-09-02 20:15:50

标签: makefile gnu-make circular-dependency

我的Makefile中有一条规则用于创建不同目录中文件的符号链接:

VPATH = ../source
foo: foo
    ln -s $< $@

即使我打算让目标解析为./foo并依赖解析为../source/foo,我理解为什么make将其视为循环。有没有办法以非循环的方式表达这条规则?

2 个答案:

答案 0 :(得分:0)

请注意,链接不依赖于链接目标的更改;它只需要存在。因此,根本不需要普通的先决条件,并且最简单的片段可以做你想做的事情

foo:
    ln -sf ../source/$@

但是,如果您仍需要VPATH用于其他目的,这将无法正常工作。如果是这样,那么在我看来最简单的方法是使用绝对路径忽略VPATH这个规则:

VPATH := ../source
$(CURDIR)/foo:
    ln -sf ../source/$(@F)

最后,如果文件../source/foo也是由Make生成的目标,那么最好的方法可能是:

VPATH := ../source

.SECONDEXPANSION:
$(CURDIR)/foo: | ../source/$$(@F)
    ln -sf $|

请注意,我们不依赖于此处先决条件的更改,仅取决于它是否存在。

顺便说一下,我使用-f选项的原因是,Make应支持-B选项。除非您在此处使用-f,否则该选项无效。

答案 1 :(得分:0)

我认为您在此尝试的内容属于“VPATH滥用”类别。

我的经历一再指向我的口头禅“明确胜于隐性”,这也是其中一个原因。与GNU make Manual中的断言相反,我的经验让我相信,在更大,更复杂的项目中,你需要更多明确而不是更少,因为它的大小使得它更难以找到文件,除非它们的路径是明确的。

我也相信很多使用VPATH的需要源于使用递归make,你没有构建完整的依赖树;正确编写您的构建系统,您根本不需要VPATH。

在相关主题上,我坚信只指定一个或两个-I目录:您的顶级src/include/目录并使全部< / em>相对于这些路径的包含。同样,在更大,更复杂的项目中,seing #include "my/really/cool/thing.h"比仅仅#include "thing.h"提供更多信息。

那就是说,我愿意将VPATH用于库,尤其是系统库,因为你可以使用-lfoo语法,但我不想将它作为一般规则使用,因为它可能会威胁到构建的可重复性。