GNU-Make does not recompile when a header file changed

Viewed 8121

GNU-Make does not recompile when hdr.h file changed. As below printed lines, it did not try to recompile even main.d file is generated. Can you guide me why it happend?

hdr.h

#ifndef __HDR_H__  

#define LOOP_CNT 1000  

#endif /* __HDR_H__ */  

main.c

#include <stdio.h>  
#include "hdr.h"  

int main(void)  
{  
    int i, sum = 0;  
    for (i = 0; i < LOOP_CNT; i++) sum += i;  
    (void)printf("sum = %d\n", sum);  
    return 0;  
}  

Makefile

SUFFIXES += .d

.PHONY: clean  

OBJECTS = $(patsubst %.c,%.o,$(wildcard *.c))  
CC = armcc  
LD = armcc  
CFLAGS += 

# Default target  
all: sum  

sum : $(OBJECTS)  
    $(CC) $(CFLAGS) -o $@ $^  

$(OBJECTS) : %.o : %.c   
    $(CC) $(CFLAGS) -o $@ -c $<  

# Generating dependency files  
%.d : %.c  
    @$(CC) -M $< > $@  

# Include dependency file to have gcc recompile necessary sources  
include $(patsubst %.c,%.d,$(wildcard *.c))  
#$(info $(patsubst %.c,%.d,$(wildcard *.c)))

clean:  
    rm -f *.o *.d core $(EXEC_NAME)  

Here is printed line in second.

C:\project\dep>make all
Makefile:24: main.d: No such file or directory
armcc    -o main.o -c main.c
armcc    -o sum main.o

C:\project\dep>make all
make: Nothing to be done for `all'. 

main.d file is generated as below.

__image.axf: main.c
__image.axf: C:\Program Files\ARM\RVCT\Data\4.1\713\include\windows\stdio.h
__image.axf: hdr.h
5 Answers

The problem with the Makefile is this:

Incorrect:

$(OBJECTS) : %.o : %.c
    $(CC) $(CFLAGS) -o $@ -c $<

Correct (notice the added %.d dependency, %.c cannot be elimin):

$(OBJECTS) : %.o : %.c %.d
    $(CC) $(CFLAGS) -o $@ -c $<

The dependency chain is like this:

all
+->sum
   +->x.o
      +->x.c
---------------------------------
x.d
+->x.c
[generate rule: "x.d: x.c x.h"]

after include:
x.d
+->x.c
+->x.h

In the original version, the %.d rules are do triggered, I guess the include directives are responsible (without that, the %.d-s won't be built). But even though they are triggered, nothing connects them to the %.o files. Thus, even if they are rebuilt, because of the changed %.h files, there is no dependency chain to the %.o files.

Connecting the dependency chains fixes this problem.


Note that running the corrected Makefile after a clean will generate error messages like this one:

Makefile:123: x.d: No such file or directory

As explained in the make docs, when include cannot find a Makefile, it emits an error message, but at this point it does not consider this a fatal error and tries to find a rule that would create the missing files.

Adding

$(info $(shell ls))

to the object file creation / linking recipe can confirm that the rules are indeed there, at that time.

Related