我有一个可以通过scenario.xml
文件配置的项目。该项目包含一个小工具,用于从此xml文件(tools/xmlq
)中提取信息,该文件是从c源文件编译而来的。 Makefile使用此工具通过将其输出分配给各种make变量(如
SOME_VAR := $(shell tools/xmlq some_query)
这种方法的问题在于,在干净的构建中,tools/xmlq
不存在,SOME_VAR
将不包含预期值。
我的问题是:在使用它的tools/xmlq
调用执行之前,是否有某种方法可以确保make $(shell ...)
?如果不是:我可以使用哪些变通方法来避免这个问题?
到目前为止我想到的一些可能的解决方法:
使用文件而不是make变量。
这意味着像
这样的结构SOME_VAR := $(shell tools/xmlq some_query)
some-target: some-prerequisites
some-command $(SOME_VAR) $^
会改为
some-var.txt: tools/xmlq scenario.xml
$< some_query > $@
some-target: some-var.txt some-prerequisites
some-command $$(cat $<) $(filter-out $<,$^)
这有一个优点,它感觉非常惯用,但有一个很大的缺点,我不能使用,例如$(SOME_VAR).o
已成为先决条件。
只需使用make tools/xmlq
$(shell make tools/xmlq)
(显然必须有一些警卫来避免无限递归)。这里的缺点是Makefile基本上被读了两次。一次构建tools/xmlq
,一次构建原始调用。
答案 0 :(得分:1)
您不需要解决方法,只需要适当的make
逻辑。详细地
这取决于源文件xmlq.c
所在的位置。为了说明
我假设它在tools
: -
SOME_VAR = $(shell tools/xmlq some_query)
some-target: some-prerequisites | tools/xmlq
some-command $(SOME_VAR) $^
tools/xmlq: tools/xmlq.o
$(CC) -o $@ $^ # Or however you build it.
解决方案有两点: -
立即分配
SOME_VAR := $(shell tools/xmlq some_query)
替换为懒惰的分配
SOME_VAR = $(shell tools/xmlq some_query)
所以定义$(shell tools/xmlq some_query)
只会在$(SOME_VAR)
时展开
扩展,即当配方some-command $(SOME_VAR) $^
扩展时,
当make
决定运行它时。所以tools/xmlq
不需要存在,直到那个回忆。
规则
some-target: some-prerequisites | tools/xmlq
使tools/xmlq
成为order-only prerequisite
some-target
。这意味着tools/xmlq
是否应该some-target
,但是如果确定some-target
应该
制作完成后,tools/xmlq
将首先制作。因此tools/xmlq
之前就会存在
make
展开$(SOME_VAR)
。
演示:
工具/ xmlq.c 强>
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; ++i) {
fputs(argv[i],stdout);
}
return 0;
}
和
<强>生成文件强>
.PHONY: clean foo World
SOME_VAR = $(shell tools/xmlq Hello)
foo: World | tools/xmlq
echo $(SOME_VAR) $^
tools/xmlq: tools/xmlq.o
$(CC) -o $@ $^
World:;
clean:
rm -fr tools/xmlq.o tools/xmlq
的运行方式如下:
$ make
cc -c -o tools/xmlq.o tools/xmlq.c
cc -o tools/xmlq tools/xmlq.o
echo Hello World
Hello World
这可能会减少为:
.PHONY: clean foo World
foo: World | tools/xmlq
echo $$(tools/xmlq Hello) $^
tools/xmlq: tools/xmlq.o
$(CC) -o $@ $^
World:;
clean:
rm -fr tools/xmlq.o tools/xmlq