我想要一个makefile,它会将一些字符串作为某些文件的前缀(NAMES
),并从那里开始处理目标和必备文件名。例如,在下面的示例中,我们的想法是将2个csv文件(foo.csv
和bar.csv
)转换为表格(尽管我只是回应目标和先决条件)。
NAMES = foo bar
PR = $(patsubst %,%.csv,$(NAMES))
TB = $(patsubst %,%.tsv,$(NAMES))
all: $(TB)
%.tsv: $(PR)
@echo $< $@
打印:
foo.csv foo.tsv
foo.csv bar.tsv
因此,看起来makefile没有正确扩展PR
中的先决条件,因为我希望在第二行看到bar.csv bar.tsv
。
但是,如果我打印$PR
和$TB
,两者似乎都设置正确:
$(info $$PR is [${PR}])
$(info $$TB is [${TB}])
# prints
$PR is [foo.csv bar.csv]
$TB is [foo.tsv bar.tsv]
知道如何让它正常工作吗?
请注意,我在工作目录中有foo.csv
和bar.csv
个文件。
答案 0 :(得分:2)
问题在于您使用内置变量$<
的方式。如果手动展开变量并重写makefile,则变为......
NAMES = foo bar
PR = $(patsubst %,%.csv,$(NAMES))
TB = $(patsubst %,%.tsv,$(NAMES))
all: foo.tsv bar.tsv
%.tsv: foo.csv bar.csv
@echo $< $@
但$<
引用的the first prerequisite始终为foo.csv
,无论目标是什么。
一种解决方案可能是使用scoped static pattern rule。所以......就像......
NAMES = foo bar
PR = $(patsubst %,%.csv,$(NAMES))
TB = $(patsubst %,%.tsv,$(NAMES))
all: $(TB)
# Tell make how to build a .tsv from a .csv but constrain the rule
# so that it only applies to .tsv files that are part of $(TB).
#
$(TB): %.tsv: %.csv
@echo 'building target [$@] with $$< = [$<]'
上述结果为......
building target [foo.tsv] with $< = [foo.csv]
building target [bar.tsv] with $< = [bar.csv]