GNU Make path handling

[article]

that would work with a different separator.   One way to do that is to define a variable called / (GNU Make lets you get away using almost anything as a variable name) and use it in place of /.

/ := /
SRCDIR := src
MODULE_DIR := module_1
MODULE_SRCS := $(SRCDIR)$/$(MODULE_DIR)

Of course, if that makes you uncomfortable just call is SEP:

SEP := /
SRCDIR := src
MODULE_DIR := module_1
MODULE_SRCS := $(SRCDIR)$(SEP)$(MODULE_DIR)

Now when switching to Windows you can just redefine / or SEP to \.  I use $(strip) to define / because it's hard to get a literal \ on its own (since GNU Make interprets it as a line continuation and it can't be escaped).

/ := $(strip \)
SRCDIR := src
MODULE_DIR := module_1
MODULE_SRCS := $(SRCDIR)$/$(MODULE_DIR)

Note, however, that the Windows builds of GNU Make will also accept / as a path separator, so paths like c:/src are legal.  Using those paths will simplify the Makefile but be careful when passing them to a native Windows tool that expects \ separaed paths.   If that's necessary then the follwing simple function will convert a forward slash path to a back slash path:

forward-to-backward = $(subst /,\,$1)

A Windows oddity: case insensitive but case preserving On POSIX systems file names as case sensitive, on Windows they are not.  On Windows the files File, file and FILE are all the same physical file.  But Windows also has the oddity that the first time a file is accessed the specific case used is recorded and preserved.  Thus if we touch File it will appear as File in the file system (but can be accessed as FILE, file or any other combination of case).

By default GNU Make does case sensitive target comparisons and thus the following Makefile does not do what you might expect:

.PHONY: all
all: File
file:
    @touch $@

It is possible to compile GNU Make on Windows to do case insensitive comparisons (with the HAVE_CASE_INSENSITIVE_FS option).

This oddity is more likely to arise when a target is specified in a Makefile and also found using a wildcard search.  The target names may differ in case and that may cause an unexpected 'No rule to make' error.

GNU Make built in path functions and macros
It's possible to find out the current working directory in GNU Make using the built in CURDIR.  Note that CURDIR will follow symlinks so suppose you are in /foo but /foo is actually a symlink to /somewhwere/foo.   CURDIR will report the directory as /somewhere/foo.  If you need the non-symlink-followed directory name then call pwd via $(shell):

CURRENT_DIRECTORY := $(shell pwd)

The other directory that it's often interesting to find is the directory in which the current Makefile is stored.  This can be done using the MAKEFILE_LIST macro that was introduced in GNU Make 3.80.   At the start of a Makefile it's possible to extract its directory as follows:

CURRENT_MAKEFILE := $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
MAKEFILE_DIRECTORY := $(dir $(CURRENT_MAKEFILE))

GNU Make has functions for splitting paths into components: dir, notdir, basename and suffix.

Consider a file name /foo/bar/source.c stored in the macro FILE.   The four functions above can be used to extract the directory, file name and suffix:

Function Result
dir /foo/bar/
notdir source.c
basename source
suffix .c

You can see that the directory, the non-directory part, the suffix (or extension) and the non-directory part without the suffix have been extracted.   These four functions make file name manipulation easy.   If there was no directory specified then GNU Make assumes ./.  For example, suppose that FILE was just source.c:

Function Result
dir ./
notdir source.c
basename source
suffix .c

Since these functions

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

May 04
May 04
May 04
Jun 01