在每个 gnu Makefile 中使用 basename

Using basename inside for each gnu Makefile

我想知道如何在每个内部使用 basename?我认为 basename 不起作用的原因可能是每个“$file”实际上是文件的路径,而不仅仅是文件名。

DOCKER_TAG=foobar
DOCKER_RUN=docker run -v `pwd`:/root -it --rm -w /root ${DOCKER_TAG}
TEST_DIR=test_cases

dockerbuild: App/App.csproj
    docker build . -t ${DOCKER_TAG}

%.run: %.txt dockerbuild 
    ${DOCKER_RUN} $<

%.out: %.txt dockerbuild
    ${DOCKER_RUN} $< > $@

%.test: %.out
    python3 evaluate.py $<

.PHONY: regression
regression: $(TEST_DIR)/*.txt
    for file in $^ ; do \
        echo $(basename $${file}).test ; \
    done

Returns(我预计 .txt 已替换为 .test

test_cases/00_example.txt.test
test_cases/01_simplest_possible.txt.test
test_cases/02_two_users.txt.test
test_cases/03_five_users.txt.test
test_cases/04_one_interferer.txt.test
test_cases/05_equatorial_plane.txt.test
test_cases/06_partially_fullfillable.txt.test
test_cases/07_eighteen_planes.txt.test
test_cases/08_eighteen_planes_northern.txt.test
test_cases/09_ten_thousand_users.txt.test
test_cases/10_ten_thousand_users_geo_belt.txt.test
test_cases/11_one_hundred_thousand_users.txt.test
test_cases/test.txt.test

$(basename) 函数由 make shell 运行 循环之前计算。所以你实际上是 运行ning

for file in /path/to/moo.txt /path/to/bar.txt /path/to/baz.txt; do
    echo ${file}.test ;
done

shell 的 basename 命令也删除了路径,但您可能想用

之类的东西来解决这个问题
.PHONY: regression
regression: $(TEST_DIR)/*.txt
    printf '%s\n' $^ | sed 's/\.txt$$/.test/'

当然,更好的解决方案是使用 make 函数。

.PHONY: regression
regression: $(TEST_DIR)/*.txt
    printf '%s\n' $(patsubst %,%.test,$(basename $^))

如果你想做的不仅仅是打印文件名,更惯用的解决方案是创建一个模式规则,运行 它在每个输入文件上。

.PHONY: regression
regression: $(patsubst %.txt,%.test,$(wildcard $(TEST_DIR)/%.txt))

$(TEST_DIR)/%.test: $(TEST_DIR)/%.txt
    printf '%s\n' $@ # or whatever you really wanted to do