如何在gnu make中使用目标特定变量

时间:2014-03-07 18:41:34

标签: build makefile gnu-make

我有一个类似的makefile:

file1 = "path/to/some/file"
header="col1;col2;col3"

$(file1):
      some steps to create the file
call_perl_script:$(file1)
      ${perl} script.pl in=header

标头当前是硬编码的,它也在生成的file1中。我需要从file1获取标头。不知何故,我改变了它,如

file1 = "path/to/some/file"

$(file1):
      some steps to create the file
      $(eval header="$(shell $(sed) -n "/^col1;col2;col3/Ip" $(file1))")
call_perl_script:$(file1)
      ${perl} script.pl in=$(header)

它工作正常,但想知道它是否是使用目标特定变量的正确方法。在与eval一起使用之前,标头不会传递其值。 此外,如果我在call_perl_script目标中打印$(标题)它正确打印但如果我使用“if”条件来检查变量是否为空并设置默认值,则它不起作用。它设置“if”块中标题的值,而不管“sed”输出中标题中的值。

call_perl_script:$(file1)
${echo} $(header)
ifeq "$(header)" ""
      $(eval header="col1;col2;col3")
endif
      ${perl} script.pl in=$(header)

1 个答案:

答案 0 :(得分:1)

我不认为特定于目标的变量会对您有所帮助,因为它们通常是静态的。例如,如果您需要为一个特定C文件静音一种类型的警告,则可以添加foo.o: CFLAGS+=-Whatever之类的规则。

您遇到的问题是$(eval header=...)仅在$(file1)生效时执行。如果它已经存在,那么目标将不会重建,并且header将不会被设置。

在Makefile中执行此操作的更自然的方法是将标头保存到单独的文件中。这样,只要$(file)更改,它就会自动重新生成:

.DELETE_ON_ERROR:

file = foo.txt

call_perl_script: $(file) $(file).header
        echo perl script.pl in="$(shell cat $(file).header)"

$(file):
        echo "col1;col2;col3;$$(head -c1 /dev/random)" > $(file)

%.header: %
        sed -n '/^col1;col2;col3/p' $< > $@

clean::
        rm -f $(file)
        rm -f *.header

导致:

echo "col1;col2;col3;$(head -c1 /dev/random)" > foo.txt
sed -n '/^col1;col2;col3/p' foo.txt > foo.txt.header
perl script.pl in="col1;col2;col3;?"

然而,这仍然是一个问题,所以对于长期可维护性,您可能需要考虑更新script.pl来解析标题本身。