我想使用静态模式规则来指定一类目标的默认配方,但是会覆盖一些特定目标的配方。
这是一个简单的例子,说明了我尝试做的事情。对于包含文件的每个目录" test.py"我想调用命令" run_test.py",除非目录名为" one"我想调用一组不同的命令:
TESTS := $(shell find * -name "test.py" | xargs -I {} dirname {})
.PHONY: $(TESTS)
all: $(TESTS)
$(TESTS): %:
python run_test.py $@
one:
python run_test.py $@ mode=1
python run_test.py $@ mode=2
python check_results.py $@
这样可行,但会发出警告:
$ make
Makefile:12: warning: overriding commands for target `one'
Makefile:9: warning: ignoring old commands for target `one'
是否有另一种方法可以做到这一点,或消除警告?
答案 0 :(得分:3)
不,你不能这样做。静态模式规则实际上不是模式规则:相反,它只是编写大量显式规则的简写。
如果你想让大多数目标使用一个食谱而少数使用另一个食谱,你应该为"大多数"定义一个真正的模式规则。目标,而不是静态模式规则,然后使用显式规则覆盖:
%.o: %.cc
g++ -c $< -o $@
test.o: test.cc
g++ -Wall -c $< -o $@
为什么要使用静态模式规则而不是常规模式规则?
ETA 您还可以使用特定于目标的变量:
CFLAGS =
test.o: CFLAGS = -Wall
$(OBJS): %.o: %.cc
g++ $(CFLAGS) -c $< -o $@
ETA2 好的,这与你原来的例子大不相同。
我可以看到两个明显的选择。第一种是从列表中删除特殊目标;类似的东西:
SPECIAL_TESTS := one
TESTS := $(patsubst %/test.py,%,$(shell find * -name "test.py"))
.PHONY: all $(TESTS)
all: $(TESTS)
$(filter-out $(SPECIAL_TESTS),$(TESTS)):
python run_test.py $@
$(SPECIAL_TESTS):
python run_test.py $@ mode=1
python run_test.py $@ mode=2
python check_results.py $@
另一种方法是使用定义整个配方的特定于目标的变量,如下所示:
TEST_RECIPE = python run_test.py $@
one: TEST_RECIPE = python run_test.py $@ mode=1 \
&& python run_test.py $@ mode=2 \
&& python check_results.py $@
TESTS := $(patsubst %/test.py,%,$(shell find * -name "test.py"))
.PHONY: all $(TESTS)
all: $(TESTS)
$(TESTS):
$(TEST_RECIPE)