首页 > 解决方案 > 目标模式不包含“%”。停止。使用 $(shell sh -c "./ " ) 时(当前工作目录)

问题描述

我一直在研究 Makefile,发现了一个奇怪的错误,我的目录中有两个可执行文件,我正在构建然后运行:

TARGETS = sr_flipflop_clk_async_rst_tb sr_flipflop_tb

该错误发生在我的test目标中,其中包含以下代码:

    $(foreach src, $(TARGETS), \
        printf '\033[33m'; \
        echo "Running tests on target" $(src); \
        printf '\033[39m'; \
        $(eval $(shell sh -c "echo \"Results\" >> ../output/${src}.out")) \
        $(eval $(shell ./${src})))

错误是从这一行生成的: $(eval $(shell ./${src})))

由于某种原因,该错误仅在目标sr_flipflop_tb在第二个目标上而不在第二个目标上时发生。如果我删除指示当前工作目录的点,该错误也不会发生。我尝试了一种解决方法,将行更改为:( $(eval $(shell ../build/${src})))当前目录称为 build)

这也会产生错误。我一生都无法弄清楚为什么会发生这种情况,产生的错误是:

Makefile:28: *** target pattern contains no '%'. Stop.

其中第 28 行指的是test目标的开始。

知道这里发生了什么吗?我可以理解是否可能发生了一个不喜欢单点的错误,但是我不能跳到一个目录然后回到这个目录的事实至少可以说是令人费解的,而且它只发生在我的一个目标上. 希望有人可以帮助我解决这个问题。

如果有帮助,这是我的目录结构:

.
|-- build
|   |-- Makefile
|   |-- e~sr_flipflop_clk_async_rst_tb.o
|   |-- e~sr_flipflop_tb.o
|   |-- gather_errors.sh
|   |-- hello.txt
|   |-- sed.out
|   |-- sr_flipFlop.o
|   |-- sr_flipFlop_clk_async_rst.o
|   |-- sr_flipFlop_clk_async_rst_tb.o
|   |-- sr_flipFlop_tb.o
|   |-- sr_flipflop_clk_async_rst_tb
|   |-- sr_flipflop_tb
|   `-- work-obj93.cf
|-- output
|   |-- cat_test.out
|   |-- sr_flipflop_clk_async_rst_tb.out
|   `-- sr_flipflop_tb.out

谢谢, EJ

编辑:显然,如果我将名称更改为sr_flipflop_tb其他任何名称,它就会起作用。有人能告诉我这里发生了什么吗?它实际上与这个特定文件的名称有关。

标签: gccmakefilegnu-make

解决方案


那个代码是错误的。您不应该使用$(eval ...)它,因为它期望获得 makefile 语法(规则和 makefile 变量设置)。

因为你给它一个shell命令的输出,所以它是无效的。我怀疑您正在运行的 shell 命令以某种方式生成错误消息或其他内容。

其次,您不应该使用$(shell ...),因为在运行任何其他命令之前,所有 make 变量和函数都首先展开。这意味着您的所有调用$(shell ...)都会发生,然后 printfs 都会发生。

您应该为此使用 shell 语法,而不是 make 语法。如果你真的想要,你可以使用 make's foreach:

$(foreach src, $(TARGETS), \
    printf '\033[33m'; \
    echo "Running tests on target" $(src); \
    printf '\033[39m'; \
    echo "Results" >> ../output/${src}.out; \
    ./${src};)

或者您可以使用 shell 循环编写它:

for src in $(TARGETS); do \
    printf '\033[33m'; \
    echo "Running tests on target $$src"; \
    printf '\033[39m'; \
    echo "Results" >> "../output/$$src.out"; \
    "./$$src"; \
done

但实际上,这非常不像制造。在食谱内部循环实际上总是一个坏主意。您应该改用 make 的规则来做到这一点:

test: $(addprefix test-,$(TARGETS))

test-%:
        @printf '\033[33m'; \
        echo "Running tests on target" $*; \
        printf '\033[39m'; \
        echo "Results" >> ../output/$*.out; \
        ./$*

推荐阅读