I have the following MakeFile:
TARGET = target
CC = gcc-9
CFLAGS = -g -std=c99 -Wall -Wvla -Wextra -Wundef -Wshadow -Wpointer-arith -O2 -D_FORTIFY_SOURCE=2
OBJ = dep1.o $(TARGET).o dep2.o
all: $(TARGET)
run: $(TARGET)
./$<
$(TARGET): $(OBJ)
$(CC) $(CFLAGS) $^ -o $@
$(TARGET).o: $(TARGET).c
$(CC) -c $(CFLAGS) $^
dep1.o: dep1.c
$(CC) -c $(CFLAGS) $^
dep2.o: dep2.c
$(CC) -c $(CFLAGS) $^
dep1.c: dep1.h
$(TARGET).c: dep1.h
clean:
rm -rfv $(TARGET) *.o *.a *.dylib *.dSYM
When dep1.h
changes, I want to be able to recompile with the new changes involved. dep1.c
includes dep1.h
. $(TARGET)
also includes dep1.h
I have tried several other solutions online, but none of really seemed to work. The only way I was able to get it to work was by changing all: clean $(TARGET)
. By doing so, the project would get cleaned first, and then it would recompile with the new changes in dep1.h
, but I feel like that is a really hacky solution and there is a better way, but I am not sure.
CodePudding user response:
This is incorrect:
dep1.c: dep1.h
$(TARGET).c: dep1.h
The C files do not depend on the H files. Saying that the C files depend on the H files would mean that you use the H files to create the C files. Actually, it is the object files which depend on both the H and C files.
dep1.o: dep1.c dep1.h
This is the manual way to write it. You do not need to write the rule, the implicit rule is fine, but the correct way to write an explicit rule for this requires using $<
instead of $^
, because $^
includes all dependencies (including the header files). The $<
variable only includes the first input, so you have to write the C file first in the dependencies.
dep1.o: dep1.c dep1.h
$(CC) -c $(CFLAGS) $<
There are ways to handle this automatically using the -M
flags, if your compiler supports them (GCC does, and many other compilers support them in a compatible way).