MakeFile контроль прослеживания заголовков
В процессе написания проги добавляются заголовки и иногда забывается добавить прослеживание перекомпиляции файла, если заголовок изменился. Я написал двойной контроль над забывчивостью :
header1.h :
# ifndef CONTROLheader1h
# error not CONTROLheader1h
# endif
...
header2.h :
# ifndef CONTROLheader2h
# error not CONTROLheader2h
# endif
...
source.c :
# define CONTROLheader1h
# define CONTROLheader2h
...
# include <header1.h>
# include <header2.h>
Дальше вручную прослеживаю в Makefile забыл-ли дописать зависимость :
Makefile :
source.o : source.c header1.h header2.h
...
Вопрос : какие есть удобные варианты написания Makefile, чтобы не забывать про зависимости.
Ответы (2 шт):
Подобная проблема возникает не раз и эта задача давно уже решена. Попробуйте в консоли запустить такое
сс -M source.c
и увидите необходимый список
source.o : source.c header1.h header2.h
прям то, что нужно.
В принципе этого уже достаточно, что бы запустить что то вида
find . -name *.c -exec cc -M {}\; > MakeFile.mk
и подцепить этот файл к своему Makefile через include. Но и это можно автоматизировать. И это описано в официальной документации https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html
Потом можно посмотреть на пример здесь http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/ и сделать себе хорошо.
DEPDIR := .deps
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
%.o : %.c
%.o : %.c $(DEPDIR)/%.d | $(DEPDIR)
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(DEPDIR): ; @mkdir -p $@
DEPFILES := $(SRCS:%.c=$(DEPDIR)/%.d)
$(DEPFILES):
include $(wildcard $(DEPFILES))
Со всеми советами разобрался. Убрал ручные зависимости хедеров. Оставил только по-файловые команды. Чтобы можно было менять опции и языки (C или C++). Любая перекомпиляция файла обновляет зависимости с помощью опции -MM (которая не реагирует на изменение библиотеки).
Makefile :
OBJECTS = o/a.o o/b.o o/c.o o/d.o
CGCC = gcc -MM $(1).c -MT o/$(1).o > o/$(1).d && \
gcc -c -Os $(1).c -o o/$(1).o
CGPP = g++ -MM $(1).cpp -MT o/$(1).o > o/$(1).d && \
g++ -c -Os $(1).cpp -o o/$(1).o
build: $(OBJECTS)
g++ $(OBJECTS) -o a
o/a.o:
$(call CGCC,a)
o/b.o:
$(call CGCC,b)
o/c.o:
$(call CGPP,c)
o/d.o:
$(call CGPP,d)
clean:
rm -f o/*.d o/*.o
-include o/*.d