我的Makefile已重新编译我的所有源文件,即使它们没有更改。我用make -d
看了一下,发现了这样的东西:
...
Prerequisite `setup' of target `bin/exception/Exceptions.o' does not exist.
Must remake target `bin/exception/Exceptions.o'.
...
请注意,这是 bin/exception/Exceptions.o
编译完成后的内容。
现在地球上没有先决条件意味着什么呢?我已经非常明确地宣布了这一点,并将其标记为PHONY。这个例子应该为你产生相同的结果(你应该只能运行它 - 我已经为它生成了所有必要的文件)
OBJ_DIR=bin
SRC_DIR=src
OBJS=$(OBJ_DIR)/exception/Exception.o
.PHONY: all
all: $(OBJ_DIR)/app
.PHONY: setup
setup:
mkdir -p $(sort $(dir $(OBJS)))
# To make the source file for you
$(SRC_DIR)/%.cpp:
@mkdir -p $(dir $@)
touch $@
$(OBJ_DIR)/app: setup $(OBJS)
@echo CXX -o $@
@touch $@
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp setup
@echo CXX -c -o $@
@cp $< $@
如果我取消setup
的要求,那么我的程序将不会按预期重新编译未更改的来源。
为什么make认为需要重建?
答案 0 :(得分:2)
[Phony targets]不应该是真实目标文件的先决条件。
来自Phony
targets的手册部分。
您所看到的是原因的一部分。 make 总是认为虚假的目标是过时的,需要重建。因此(并且因为文件不存在)也适用于任何依赖于它的东西。
这个问题有两个简单的解决方案。
首先是让setup
成为Force Target而不是.PHONY
目标,这将使其正常运作(它也可能也想成为Empty Target但是只要它被触及至少一次它应该工作)。
第二个是让setup
成为order-only prerequisite:
$(OBJ_DIR)/app: $(OBJS) | setup
和
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | setup
您还可以确保正常的输出目标配方在尝试使用之前创建输出目录。
$(OBJ_DIR)/app: $(OBJS)
@mkdir -p $(@D)
@echo CXX -o $@
@touch $@
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp
@mkdir -p $(@D)
@echo CXX -c -o $@
@cp $< $@