Search code examples
makefilebuildgnu-makeincremental-build

how to tell make to check files' time stamps in dependency file?


consider this simple rule:

foo.o: foo.c foo.d
    gcc -c ...

foo.d: foo.c
    gcc -M ...

now, if both foo.d and foo.o are newer than foo.c - the recipe for foo.o will not be executed.

however, one of the headers included in foo.c might have changed, so I do need the recipe to run.

So the question is how to tell make that if one of the files listed in foo.d is newer than foo.o, then it must run the recipe for foo.o?

Thanks.


Solution

  • The point of dependency files is not that they are target prerequisites, it's that they complete your target with the correct dependencies. They actually need to be included from your Makefile.

    Here is a basic example:

    SRC = foo.c main.c
    OBJ = $(SRC:.c=.o)
    DEPS = $(SRC:.c=.d)
    
    -include $(DEPS)
    
    all: myapp.o
    
    myapp.o: foo.o main.o
        gcc -c main.o foo.o -o myapp.o
    main.o: main.c
        gcc -M ...
    foo.o: foo.c
        gcc -M ...
    
    .PHONY: all
    

    Now what happens is that the content of each file in $(DEPS) will be copy-pasted in your Makefile. Since main.c probably uses foo.c and thus includes foo.h, here's what main.d would look like :

    main.o: \
     foo.c \
     foo.h
    

    If we apply the inclusion in the Makefile, here's what GNU make will finally analyze :

    SRC = foo.c main.c
    OBJ = $(SRC:.c=.o)
    DEPS = $(SRC:.c=.d)
    
    -include $(DEPS)
    
    all: myapp.o
    
    myapp.o: foo.o main.o
        gcc -c main.o foo.o -o myapp.o
    main.o: main.c foo.c foo.h
        gcc -M ...
    foo.o: foo.c
        gcc -M ...
    
    .PHONY: all
    

    Observe how foo.c and foo.h are now prerequisites of main.o. That means that if any of them changes, main.o has to be rebuilt.