Reputation: 8452
Consider the following makefile:
.SUFFIXES:
SRC:=../Src
OBJ:=../Obj
# Sources
SOURCES := $(SRC)/App/a.c $(SRC)/App/b.c $(SRC)/App/c.c
HEADERS := $(wildcard $(SRC)/App/*.h)
# Directories
INC_DIRS := $(SRC)/App
OBJ_INC_DIRS := $(INC_DIRS:$(SRC)/%=$(OBJ)/%)
# Objects
OBJECTS := $(SOURCES:$(SRC)%=$(OBJ)%.obj)
# Dependencies
DEPS := $(SOURCES:$(SRC)%.c=$(OBJ)%.d)
-include $(DEPS)
GCC_INCLUDES := $(foreach directory, $(INC_DIRS), -I$(directory))
all: target
target: $(OBJECTS)
touch target
#Objects
$(OBJ)%.c.obj: $(SRC)%.c
@echo Compiling $@
@touch $@
# Dependencies
$(OBJ)%.d: $(SRC)%.c
@echo Checking dependencies for $<
@gcc -MM $< $(GCC_INCLUDES) -MT '$(patsubst %.d,%.c.obj,$@)' -MT '$@' -MF '$@'
@[ ! -s $@ ] && rm -f $@
# Creating directory tree before checking dependencies
$(DEPS):|$(OBJ_INC_DIRS)
$(OBJ_INC_DIRS):
@mkdir $@
clean:
echo clean
@rm $(OBJ_INC_DIRS)
When running the first time, I get:
Checking dependencies for ../Src/App/a.c
Checking dependencies for ../Src/App/b.c
Checking dependencies for ../Src/App/c.c
clean
Compiling ../Obj/App/a.c.obj
Compiling ../Obj/App/b.c.obj
Compiling ../Obj/App/c.c.obj
touch target
It's ok, but now, make again (without modifying any file):
make: `../Obj/App/a.c.obj' is up to date.
Now if I modify the file a.c
Checking dependencies for ../Src/App/a.c
Compiling ../Obj/App/a.c.obj
target
isn't remade !
It's like my file a.c is the target but it isn't... Can someone explain me what's wrong here?
If I remove the include to the DEPS, I observe the expected behavior...
Thanks
By putting the include at the end as mentioned by @Beta works but now I added the target clean and show the result...
Upvotes: 0
Views: 3339
Reputation: 99124
I'll have to do some experiments to be sure, but I think the problem is:
-include $(DEPS)
...
all: target
You include $(DEPS)
before the first target. So if you modify a.c
, Make sees that it must rebuild a.d
, then since it includes
that file it must start over, and now a.c.obj
is an earlier target than all
.
Try moving -include $(DEPS)
to the end of the makefile.
EDIT:
(Two small points: your clean
rule is incorrect, since it tries to rm
a directory, and I would do make clean; make all
rather than make all
, since I am not certain that Make promises to build targets in the given order in all cases.)
Yes, this makefile will rebuild the DEPS
even when running clean
. The makefile includes
those files and has a rule for them, so if they are missing or out of date it must rebuild them and restart, no matter what the target is. The best way to deal with this is by Advanced Auto-Dependency Generation; basically, the commands that build dependency files go in the %.obj
rule, so that a.d
is a side effect of building a.c.obj
. It's a sophisticated technique, not obvious, but it works beautifully. (Let us know if you try this and have trouble setting it up.)
Upvotes: 1