【问题标题】:target pattern contains no '%'. Stop. When using $(shell sh -c "./ " ) (current working directory)目标模式不包含“%”。停止。使用 $(shell sh -c "./ " ) 时(当前工作目录)
【发布时间】:2020-11-25 02:43:34
【问题描述】:

我一直在研究 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 的名称更改为其他任何名称,它就会起作用。有人能告诉我这里发生了什么吗?它实际上与这个特定文件的名称有关。

【问题讨论】:

  • 我还注意到,当我将违规行更改为:$(shell sh -c "./${src}" ) ) 我得到一个不同的错误:/bin/sh: 1: Syntax error: word unexpected (expecting ")") Makefile:28: recipe for target 'test' failed
  • 您在 make recipe 中使用了 make 函数(foreachevalshell),而 make recipe 通常是 shell 脚本。这真的很奇怪。独立于您的错误,您应该首先以更标准的方式使用make。例如,$(eval $(shell ./${src}))) 根本没有意义。而且,顺便说一句,您应该向我们提供更多信息:正如错误所说,它与目标模式有关,但您只显示配方,而不是目标。如果没有充分的了解,我们无能为力。

标签: gcc makefile gnu-make


【解决方案1】:

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

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

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

您应该为此使用 shell 语法,而不是 make 语法。如果你真的想要,你可以使用 make 的 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; \
        ./$*

【讨论】:

  • 我修复了 shell 调用;我猜你的意思是使用$$src 而不是${src}$(src)(原文如此),但请查看。
猜你喜欢
  • 2014-08-07
  • 2013-10-27
  • 2020-01-21
  • 1970-01-01
  • 1970-01-01
  • 2020-09-05
  • 2022-06-16
  • 2018-06-18
  • 1970-01-01
相关资源
最近更新 更多