The Basics: VPATH and vpath

[article]

else

SRCS := foo.c bar.c baz.c

OBJS := $(SRCS:.c=.o)

.PHONY: debug release

debug: all

debug: CPPFLAGS += -g

release: all

all: $(OBJS)

foo.o: foo_header.h

bar.o: string.h

vpath %.h /usr/include

vpath %.c ../src

INCLUDE_DIRECTORIES = ../include

vpath %.h $(INCLUDE_DIRECTORIES)

CPPFLAGS += $(addprefix -I ,$(INCLUDE_DIRECTORIES))

endif

The mode is controlled by setting the DEBUG variable on the command-line to yes or no.  If DEBUG is set then the first part of the Makefile is used (and it only contains a single all rule).  The first part first translates the setting of DEBUG into either debug or release and then executes a sub-Make in the appropriate directory.

For example, if you do make DEBUG=yes then the Makefile will

execute:

make debug -C debug -f ../Makefile DEBUG= That starts GNU Make in the debug sub-directory (that's the -C debug > part), using the same Makefile (the -f ../Makefile ; the .. is necessary because this will be executed from debug/), clears the DEBUG variable and tells the sub-Make to run the debug rule.

When the Makefile is rerun the first part is ignored (because DEBUG was cleared) and the main part runs.  In this case the debug target is built.  It modifies CPPFLAGS and builds all.

Here's what happens when you do a debug build:

$ make DEBUG=yes

make debug -C debug -f ../Makefile DEBUG= cc  -I ../include -g  -c -o foo.o ../src/foo.c cc  -I ../include -g  -c -o bar.o ../src/bar.c cc  -I ../include -g  -c -o baz.o ../src/baz.c And a release build:

$ make DEBUG=no

make release -C release -f ../Makefile DEBUG= cc  -I ../include  -c -o foo.o ../src/foo.c cc  -I ../include  -c -o bar.o ../src/bar.c cc  -I ../include  -c -o baz.o ../src/baz.c In both cases the output has been separated into a directory with the sources coming from the same location.  For the debug build you can see that the -g option has been added to the compiler command-line.

<size=12pt>You don't need them

Most of the time you can completely avoid using VPATH and vpath.  For most dependencies you'll be using some automatic dependency search program (such as makedepend or gcc

- -MP ) and so you won't need to have GNU Make search for those files because the dependencies will be fully specified.

On the other hand, the separation of different binary types (debug/release, or different architectures) is very handy.  It can, however, be easily achieved without using the VPATH/vpath by explicitly setting the paths for sources and objects in the Makefile.  The only problem with doing this is that GNU Make's built-in pattern rules cannot be used (because they either assume source and binary are in the same directory, or they use a

VPATH/vpath search).   To make up for that you have to provide your own versions of those pattern rules.

Here's my sample Makefile rewritten to eliminate vpath entirely (I cheated slightly be omitting the automatic dependency generation part).  It still separates output into debug/ and release/ but uses explicit paths to do so, and it doesn't require the GNU Make restart that the previous solution used.

OBJDIR := $(if $(filter yes,$(DEBUG)),debug,release) SRCDIR := src

INCLUDE_DIRECTORIES = include

CPPFLAGS += $(addprefix -I ,$(INCLUDE_DIRECTORIES))

SRCS := foo.c bar.c baz.c

OBJS := $(addprefix $(OBJDIR)/,$(SRCS:.c=.o)) SRCS := $(addprefix $(SRCDIR)/,$(SRCS))

all: $(OBJS)

ifeq ($(OBJDIR),debug)

all: CPPFLAGS += -g

endif

$(OBJDIR)/%.o: $(SRCDIR)/%.c

~    $(COMPILE.c) $(OUTPUT_OPTION) $<

If you don't know the commands used by a built-in rule you can type make -p to get GNU Make to print them out.  For this rewrite I used the definition of the %.o: %.c rule:

%.o : %.c

~   

About the author

John Graham-Cumming's picture John Graham-Cumming

John Graham-Cumming is Co-Founder at Electric Cloud, Inc . Prior to joining Electric Cloud, John was a Venture Consultant with Accel Partners, VP of Internet Technology at Interwoven, Inc. (IWOV), VP of Engineering at Scriptics Corporation (acquired by Interwoven), and Chief Architect at Optimal Networks, Inc. John holds BA and MA degrees in Mathematics and Computation and a Doctorate in Computer Security from Oxford University. John is the creator of the highly acclaimed open source POPFile project. He also holds two patents in network analysis and has others pending.

AgileConnection is one of the growing communities of the TechWell network.

Featuring fresh, insightful stories, TechWell.com is the place to go for what is happening in software development and delivery.  Join the conversation now!

Upcoming Events

Nov 09
Nov 09
Apr 13
May 03