我有一条规则,Makefile
旨在创建指向不同目录中文件的符号链接:
VPATH = ../source
foo: foo
ln -s $< $@
即使我打算让目标解析为./foo
和依赖解析为../source/foo
,但我理解为什么make
将其视为循环。有没有办法以非循环的方式表达这个规则?
我有一条规则,Makefile
旨在创建指向不同目录中文件的符号链接:
VPATH = ../source
foo: foo
ln -s $< $@
即使我打算让目标解析为./foo
和依赖解析为../source/foo
,但我理解为什么make
将其视为循环。有没有办法以非循环的方式表达这个规则?
注意链接不依赖于链接目标的变化;它只需要存在。因此,根本不需要普通的先决条件,做你想做的最简单的片段就是
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
除非您在此处 使用,否则该选项将不起作用。
我认为您在这里尝试的内容属于“VPATH 滥用”类别。
我的经验反复将我指向“显式胜于隐式”的口头禅,这就是原因之一。与 GNU make 手册中的断言相反,我的经验使我相信,在更大、更复杂的项目中,你需要更明确,而不是更少,因为文件的大小使得定位文件更加困难,除非它们的路径是明确的。
我也相信使用 VPATH 的很多需求源于使用递归 make,你没有构建完整的依赖树;正确编写您的构建系统,您根本不需要 VPATH。
在相关主题上,我坚信只指定一个或两个-I
目录:您的顶级目录src/
和include/
目录,并包含与这些路径相关的所有内容。同样,在更大、更复杂的项目中,seing#include "my/really/cool/thing.h"
提供的信息比简单的要多得多#include "thing.h"
。
也就是说,我对将 VPATH 用于库,尤其是系统库的想法持开放态度,因为您可以使用该-lfoo
语法,但我不想将其用作一般规则,因为它可能会威胁构建的可重复性。