Make всегда будет пытаться переделать Makefile перед выполнением Makefile. Для этого make будет искать правила, которые можно использовать для воссоздания Makefile. Make будет искать довольно много неявных правил и других непонятных методов для (пере) создания Makefile.
В вашем случае make каким-то образом решил, что шаблонное правило %.o: $(BUILD_DIR)/stamp
должно использоваться для воссоздания Makefile, который не удался.
Чтобы предотвратить повторный сбор Makefile в make, вы можете написать правило с пустым рецептом:
Makefile: ;
Прочтите главу Переработка файлов Makefile в руководстве по сборке для более подробного объяснения.
О включенных Makefiles: Включенные Makefile всегда будут включены, независимо от цели. Если включенные make-файлы отсутствуют (или старше, чем их предварительные требования), то они сначала будут (повторно) созданы. Это означает, что make clean
сначала сгенерирует .d
Make-файлы, только чтобы удалить их снова.
Вы можете предотвратить включение для определенных целей, заключив директиву include
в условное выражение:
ifneq ($(MAKECMDGOALS),clean)
include $(DEPENDENCIES)
endif
Вот весь ваш Makefile с некоторыми исправлениями. Я отметил места, где я что-то изменил.
# Makefile
# $(call setsuffix,newsuffix,files)
# Replaces all the suffixes of the given list of files.
setsuffix = $(foreach file,$2,$(subst $(suffix $(file)),$1,$(file)))
# $(call twinfile,newdir,newsuffix,oldfile)
# Turns a path to one file into a path to a corresponding file in a different
# directory with a different suffix.
twinfile = $(addprefix $1/,$(call setsuffix,$2,$(notdir $3)))
MAIN = main
SOURCE_DIR = src
INCLUDE_DIR = include
BUILD_DIR = build
SOURCES = $(wildcard $(SOURCE_DIR)/*.cpp)
OBJECTS = $(call twinfile,$(BUILD_DIR),.o,$(SOURCES))
DEPENDENCIES = $(call twinfile,$(BUILD_DIR),.d,$(SOURCES))
CXX = g++
LIBS = -lpng
CXXFLAGS = -I $(INCLUDE_DIR)
.PHONY: all
all: $(MAIN)
$(MAIN): $(OBJECTS)
$(CXX) $(LIBS) $^ -o $(MAIN)
# -------> only include if goal is not clean <---------
ifneq ($(MAKECMDGOALS),clean)
include $(DEPENDENCIES)
endif
# ---------> fixed this target <--------------
$(BUILD_DIR)/%.o: $(SOURCE_DIR)/%.cpp $(BUILD_DIR)/stamp
$(CXX) $(CXXFLAGS) -c $(call twinfile,$(SOURCE_DIR),.cpp,$@) -o $@
# ---------> and this target <---------------
$(BUILD_DIR)/%.d: $(SOURCE_DIR)/%.cpp $(BUILD_DIR)/stamp
@ echo Generate dependencies for $@;
@set -e; rm -f $@; \
$(CC) -M $(CPPFLAGS) $< > $@.$$$$; \
sed 's,\($*\)\.o[ :]*,$(BUILD_DIR)\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
$(BUILD_DIR)/stamp:
mkdir -p $(BUILD_DIR)
touch $@
.PHONY: clean
clean:
rm -rf $(BUILD_DIR)
.PHONY: printvars
printvars:
@ echo $(SOURCES)
@ echo $(OBJECTS)
@ echo $(DEPENDENCIES)