Я хочу, чтобы правило сборки запускалось с помощью директивы include, если цель включения устарела или не существует.
В настоящее время make-файл выглядит следующим образом:
program_NAME := wget++
program_H_SRCS := $(wildcard *.h)
program_CXX_SRCS := $(wildcard *.cpp)
program_CXX_OBJS := ${program_CXX_SRCS:.cpp=.o}
program_OBJS := $(program_CXX_OBJS)
DEPS = make.deps
.PHONY: all clean distclean
all: $(program_NAME) $(DEPS)
$(program_NAME): $(program_OBJS)
$(LINK.cc) $(program_OBJS) -o $(program_NAME)
clean:
@- $(RM) $(program_NAME)
@- $(RM) $(program_OBJS)
@- $(RM) make.deps
distclean: clean
make.deps: $(program_CXX_SRCS) $(program_H_SRCS)
$(CXX) $(CPPFLAGS) -MM $(program_CXX_SRCS) > make.deps
include $(DEPS)
Проблема в том, что похоже, что директива include выполняется перед правилом сборки make.deps, что фактически означает, что make либо не получает список зависимостей, если make.deps не существует, либо всегда получает make.deps изпредыдущая сборка, а не текущая.
Например:
$ make clean
$ make
makefile:32: make.deps: No such file or directory
g++ -MM addrCache.cpp connCache.cpp httpClient.cpp wget++.cpp > make.deps
g++ -c -o addrCache.o addrCache.cpp
g++ -c -o connCache.o connCache.cpp
g++ -c -o httpClient.o httpClient.cpp
g++ -c -o wget++.o wget++.cpp
g++ addrCache.o connCache.o httpClient.o wget++.o -o wget++
Редактировать
Я прочитал документы для включениядиректива , и похоже, что если цель включения не существует, она продолжит обработку родительского make-файла, попытается построить цель, но мне не совсем понятно, как это работает:
Если включенный make-файл не может быть найден ни в одном из этих каталогов, генерируется предупреждающее сообщение, но оно не является немедленно фатальной ошибкой;обработка make-файла, содержащего include, продолжается.Как только он закончит чтение make-файлов, make попытается переделать все, что устарело или не существует.Смотрите раздел Как восстанавливаются файлы Makefile.Только после того, как он попытается найти способ переделать make-файл и потерпит неудачу, он сделает диагностику отсутствующего make-файла как фатальную ошибку.
ОТВЕТ
Thisявляется модификацией ответа, который я принял.Единственное, чего не хватало, так это того, что файлы зависимостей также зависят от источников и не будут восстановлены, если они не будут добавлены в включаемые файлы deps:
%.d: $(program_CXX_SRCS)
@ $(CXX) $(CPPFLAGS) -MM $*.cpp | sed -e 's@^\(.*\)\.o:@\1.d \1.o:@' > $@
sed
добавляет имяфайл .d
в начале каждой строки зависимости, вот так:
foo.d foo.o: foo.cpp foo.h bar.h baz.h
Из этой удивительной статьи я получил представление об опасностях рекурсивного создания:
Рекурсивное созданиеСчитается вредным
Я также добавляю в make-файл следующее:
clean_list += ${program_SRCS:.c=.d}
# At the end of the makefile
# Include the list of dependancies generated for each object file
# unless make was called with target clean
ifneq "$(MAKECMDGOALS)" "clean"
-include ${program_SRCS:.c=.d}
endif