问题
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
回答1:
As a quick and dirty Makefile fix for rebuilding if headers change I just list all my header files and then add $(HEADERS)
as a dependency in the part that builds the object files from the C src files. Its not as efficient as it could be but I find it to be good enough, i.e.
HEADERS = \
my_header.h \
my_other_header.h
$(BUILD_DIR)/%.o: %.c $(HEADERS)
$(LINK.c) $< -c -o $@
回答2:
Generally speaking, if a source file needs to be compiled to create an object file, then its dependency file also needs to be rebuilt.
So, instead of having a separate target for the .d
files, simple regenerate it when compiling. To achieve this, a simple approach is to replace
$(OBJECTS) : %.o : %.c
$(CC) $(CFLAGS) -o $@ -c $<
# Generating dependency files
%.d : %.c
@$(CC) -M $< > $@
with
$(OBJECTS) : %.o : %.c
$(CC) $(CFLAGS) -o $@ -c $<
@$(CC) -M $< > $@
Note that the dependency file will only be regnerated if compilation succeeds. If compilation fails, the object file will be deleted, so recompilation would be forced regardless of whether the dependency file is up to date.
回答3:
Have you tried make clean before you build. Clean and build should work
回答4:
To get it to rebuild your dependency files if the header files change you could change the build rule for them to something like this:
%.d : %.c
$(CC) -M $< > $@
@$(CC) -M $< -MT $*.d >> $@
as that'll also append on dependency rules that say that the .d file is built from the .c and .h files.
As for how to get them to (re)build in the first place - if your version of make is too really old and doesn't (re)build them automatically you could either have something like this:
all: depend subs
depend: $(patsubst %.c,%.d,$(wildcard *.c))
(As an aside, I think it'd look cleaner if that were in a variable BTW and also be more efficient)
Or add a dependency to the object building like so:
$(OBJECTS) : %.o : %.c %.d
$(CC) $(CFLAGS) -o $@ -c $<
But both solutions will require you to run make twice as it won't include
the changes otherwise
回答5:
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.
来源:https://stackoverflow.com/questions/44020890/gnu-make-does-not-recompile-when-a-header-file-changed