覆盖Makefile中的静态模式规则(不发出警告)

时间:2015-03-09 18:39:05

标签: makefile

我想使用静态模式规则来指定一类目标的默认配方,但是会覆盖一些特定目标的配方。

这是一个简单的例子,说明了我尝试做的事情。对于包含文件的每个目录" 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'

是否有另一种方法可以做到这一点,或消除警告?

1 个答案:

答案 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)