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 шт):

Автор решения: KoVadim

Подобная проблема возникает не раз и эта задача давно уже решена. Попробуйте в консоли запустить такое

сс -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))
→ Ссылка
Автор решения: AlexGlebe

Со всеми советами разобрался. Убрал ручные зависимости хедеров. Оставил только по-файловые команды. Чтобы можно было менять опции и языки (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
→ Ссылка