在$(shell)调用中使用它之前创建目标

时间:2017-06-29 09:51:40

标签: shell gnu-make

我有一个可以通过scenario.xml文件配置的项目。该项目包含一个小工具,用于从此xml文件(tools/xmlq)中提取信息,该文件是从c源文件编译而来的。 Makefile使用此工具通过将其输出分配给各种make变量(如

)来影响构建
SOME_VAR := $(shell tools/xmlq some_query)

这种方法的问题在于,在干净的构建中,tools/xmlq不存在,SOME_VAR将不包含预期值。

我的问题是:在使用它的tools/xmlq调用执行之前,是否有某种方法可以确保make $(shell ...)?如果不是:我可以使用哪些变通方法来避免这个问题?

到目前为止我想到的一些可能的解决方法:

  1. 使用文件而不是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已成为先决条件。

  2. 只需使用make tools/xmlq

    在makefile的开头调用$(shell make tools/xmlq)

    (显然必须有一些警卫来避免无限递归)。这里的缺点是Makefile基本上被读了两次。一次构建tools/xmlq,一次构建原始调用。

1 个答案:

答案 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