我有以下makefile:
CC = gcc
CFLAGS = -g -O2
ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
TEST_DIR = $(ROOT_DIR)/test
TEST_SOURCES := $(wildcard $(TEST_DIR)/*.c)
TEST_OBJECTS := $(TEST_SOURCES:.c=.o)
.PHONY: test
test: $(TEST_OBJECTS)
$(TEST_DIR)/%.o: $(TEST_DIR)/%.h
@echo "here"
$(TEST_DIR)/%.h: $(TEST_DIR)/%.c
java -jar ../aceunit/generator/AceUnit.jar $(basename $<) $(ROOT_DIR)/test/test_map > $@
正如您所看到的,此文件正在编译AceUnit测试文件(.c)。这样做的第一步是使用AceUnit的头生成器,如上一条规则所示。所以我试图在编译之前将头文件(.h)添加为对象(.o)文件的依赖项,但它不起作用。您看到的规则与%.o
模式不匹配,而是运行make的默认构建规则。但是,如果我删除了依赖项,则匹配规则并且它会回显here
。方法如下:
$(TEST_DIR)/%.o:
@echo "here"
依赖是如何造成这种情况的?我该如何解决?我也尝试使用$($@:.o=.h)
代替$(TEST_DIR)/%.h
。虽然规则匹配,但$<
变量似乎是空的,但我需要匹配的模式。另外,它根本没有运行最后一条规则,我从源(.c)构建了头文件(.h)。
答案 0 :(得分:0)
问题在于make正在使用.o
规则中的内置.c
因为它比通过.h
规则更快,因此它具有更高的优先级。
您可以使用%.o: %.c
行cancel内置规则。
此时make仍会考虑.h
和intermediate file,并在完成后将其删除。如果这对您没问题,那就完成了!否则,请继续阅读。
阻止删除的正确方法是将.h
个文件添加到special target .SECONDARY
。遗憾的是,.SECONDARY
不接受模式规则,因此您必须创建所有生成标头的显式列表。 .PRECIOUS
接受模式规则,但即使出现问题,它也会保留文件,这可能是您不想要的。此外,没有先决条件的.SECONDARY
会将所有内容标记为辅助,如果您没有中间目标,这可能是一个可行的解决方案(不幸的是.INTERMEDIATE
不会覆盖空的.SECONDARY
)。
另一方面,有好消息。让.SECONDARY
和.INTERMEDIATE
接受模式的是TODO list!我打赌它会很棒,他们一直在为17 years工作。