my Makefile:
CC=cc
INC=-I.
CFLAGS=-g -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN
LDFLAGS=-ldl
OBJS=*.o
OBJDIR=.obj
BINDIR=.obj
LIBDIR=.obj
%.o: %.c
$(CC) $(INC) $(CFLAGS) -DSFHASH -o $(OBJDIR)/$@ -c $<
VPATH = .obj
#vpath %.o $(OBJDIR)
hashtest: hashfuncs.o hast.o scanners.o parseargs.o
$(CC) -rdynamic -o $(BINDIR)/$@ $^ $(LDFLAGS)
clean:
@rm -f $(OBJDIR)/$(OBJS) $(BINDIR)/hashtest
using it for the first time: make does not rewrite gcc’s input file paths:
@delphi# make clean
@delphi# make
cc -I. -g -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN -DSFHASH -o .obj/hashfuncs.o -c hashfuncs.c
cc -I. -g -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN -DSFHASH -o .obj/hast.o -c hast.c
cc -I. -g -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN -DSFHASH -o .obj/scanners.o -c scanners.c
cc -I. -g -DDEBUG -std=gnu99 -DSFHASH -DDOMAIN -DSFHASH -o .obj/parseargs.o -c parseargs.c
cc -rdynamic -o .obj/hashtest hashfuncs.o hast.o scanners.o parseargs.o -ldl
cc: error: hashfuncs.o: No such file or directory
cc: error: hast.o: No such file or directory
cc: error: scanners.o: No such file or directory
cc: error: parseargs.o: No such file or directory
make: *** [hashtest] Error 1
using it second time in a row, it does:
@delphi# make
cc -rdynamic -o .obj/hashtest .obj/hashfuncs.o .obj/hast.o .obj/scanners.o .obj/parseargs.o -ldl
@delphi#
GNU Make manual says:
The value of the make variable VPATH specifies a list of directories
that make should search. Most often, the directories are expected to
contain prerequisite files that are not in the current directory;
however, make uses VPATH as a search list for both prerequisites and
*targets of rules*.
I would understand if VPATH is a set-once-at-startup-typeof-variable but it’s not. The fact that the target’s dependencies generated at runtime are properly looked up says so.
What’s up with that? Why is make correctly rewriting input file paths for gcc only the second time?
The explanation of this behavior can be found in section 3.7 of the GNU Make manual:
When you run the
makefor the first time, the prerequisites in the.objdirectory do not yet exist. That means that they will not be part of the dependency graph as created during the first phase. Consequently, these prerequisites are not used during the second phase when executing the rule to createhashtest— even though they exist by that time due to rules previously executed during the second phase.When you run
makefor the second time, these prerequisites do exist and are found and included in the dependency graph by virtue of theVPATHsetting.Please note that the expression in
VPATHis only a search path, nothing more. It can contain multiple directory names, separated by a colon.makewill search in that search path for prerequisites and targets while constructing the dependency graph during the first phase. If it finds a particular target in a directory in that search list, then that target is added to the dependency graph as an existing file, that might or might not be out of date.You seem to expect that
makeadds a subdirectory fromVPATHto a target, even if that target does not exist in that subdirectory and needs to be created. That is not how it works — how wouldmakedeal with multiple directories inVPATHin that case?