带条件的 makefile foreach

问题描述 投票:0回答:1

Makefile 标记语言是新的,但我正在尝试创建一个目标以允许可选参数。对于给定的参数,我们期望它可以是单个或由空格分隔的多个输入。如果给出了参数,我想迭代该参数并为每个参数运行一个测试函数。

如果参数是单个输入,则运行,但如果提供多个输入,则失败。

run-test:
    ifdef tests
            $(foreach test_file, $(tests), $(if $(wildcard $(addprefix tests/python/test_, $(addsuffix .py, ${test_file}))), export env=preprod && pytest tests/python/test_${test_file}.py, $(info ${test_file} does not exist.)))
    endif

如果我调用

make run-test tests="foo"
它运行得很好,但如果我这样做
run-test tests="foo bar"
似乎用于导出和运行 pytest 命令的测试 cli 命令会链接在一起并且不起作用。

makefile gnu-make
1个回答
0
投票

对你的问题最直接的答案是make的函数只是文本操作操作。他们不运行命令或任何东西。

所以如果你有这样的事情:

FILES = foo.py bar.py baz.py

$(info $(foreach F,$(FILES), python $F))

你会看到输出是:

python foo.py python bar.py python baz.py

如果您将该字符串放入 shell 提示符中运行它,您将获得一个带有参数的 python 解释器

foo.py python bar.py python baz.py
。如果要运行多个命令,则必须确保函数生成的文本是有效的 shell 命令。在这种情况下,这可能意味着在它们之间添加分号:

FILES = foo.py bar.py baz.py

$(info $(foreach F,$(FILES), python $F ;))

你会看到输出是:

python foo.py ; python bar.py ; python baz.py

现在它可以工作了,但这里的问题是,如果其中任何一个(最后一个除外)失败,它将丢失错误代码。也许你并不关心这个。

但是退一步来说,你所做的整个事情并不是真正的“类似”。每当你有一个单一的配方为列表中的每个文件做一件事情时,这并不是 make 的真正设计方式。 Make 被设计为有一个规则可以做一件事。如果我是你,我会像这样重写你的 makefile:

run-test: $(tests)
.PHONY: $(tests)

$(tests): % : tests/python/test_%.py
        env=preprod pytest $<

这使用静态模式规则为每个测试定义一个单独的规则,该规则将运行测试。

© www.soinside.com 2019 - 2024. All rights reserved.