Makefile header dependencies

I am new to using make and have been learning the basics through this tutorial. Here is the final example makefile example from the tutorial:

IDIR =../include
CC=gcc
CFLAGS=-I$(IDIR)

ODIR=obj
LDIR =../lib

LIBS=-lm

_DEPS = hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))

_OBJ = hellomake.o hellofunc.o 
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))


$(ODIR)/%.o: %.c $(DEPS)
    $(CC) -c -o $@ $< $(CFLAGS)

hellomake: $(OBJ)
    gcc -o $@ $^ $(CFLAGS) $(LIBS)

.PHONY: clean

clean:
    rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ 

This should work fine assuming all .c files are only including hellomake.h, but it wouldn't work if each .c file was including different headers. Is it possible to write a makefile that knows what each .c file is including, so I don't have to go in and do it manually like:

foo.o: foo.c something.h
    ...

bar.o: bar.c somethingelse.h
    ...

because that seems like it would be a big waste of time.


Solution 1:

Suppose foo.c has a line:

#include "something.h"

You'd like a line in the makefile:

foo.o: foo.c something.h

The gcc compiler can construct that line for you. The command

gcc -MMD -c -o foo.o foo.c

will build foo.o and foo.d which contains the line. (Try it.)

So just modify your makefile to produce these *.d files and include them, and you're done:

$(ODIR)/%.o: %.c $(DEPS)
    $(CC) -MMD -c -o $@ $< $(CFLAGS)

-include $(ODIR)/*.d

(Further refinements are possible, like specifying where the *.d files should go.)