Wiki

by yszheda

View project onGitHub

My Makefile Tips

Automatic Variables

  • $@

The file name of the target of the rule.

  • $<

The name of the first prerequisite.

e.g.

%.o: %.c
	$(CC) -c $<
  • $^

The names of all the prerequisites, with spaces between them.

e.g.

program: dep1.o dep2.o
	$(CC) $^ -o $@
  • $?

The names of all the prerequisites that are newer than the target, with spaces between them.

e.g.

lib: dep1.o dep2.o
	ar r lib $?
all.tar: file1 file2
	tar rf all.tar $?

Reference: http://www.gnu.org/software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables

File Name Functions

  • $(addprefix prefix,names...)

e.g.

OBJECTS = a.o b.o c.o
OBJDIR = ../bin
OBJPROG = $(addprefix $(OBJDIR)/, $(OBJECTS))
# generates ../bin/a.o ../bin/b.o ../bin/c.o

Reference: http://www.gnu.org/software/make/manual/html_node/File-Name-Functions.html

Recursive Wildcard

Sample code from my Android.mk:

############################################################
# automatically set LOCAL_SRC_FILES and LOCAL_C_INCLUDES
############################################################
SRC_SUFFIX := *.cpp *.c 
SRC_ROOT := $(LOCAL_PATH)/../../Classes

# recursive wildcard
rwildcard = $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
SRC_FILES := $(call rwildcard,$(SRC_ROOT)/,$(SRC_SUFFIX))
LOCAL_SRC_FILES := $(SRC_FILES:$(LOCAL_PATH)/%=%)

Equivalently, you can use extern shell command:

# WARNING: Shell command is used, it is only works on a UNIX-like OS.
# Replace it with Makefile rules if you want to run on Windows.
SRC_FILES := $(shell find $(SRC_ROOT) -type f)
LOCAL_SRC_FILES := $(SRC_FILES:$(LOCAL_PATH)/%=%)

Reference:

Filter Out By Pattern

Sample code from my Android.mk (here we do not want to compile the source code from some thrid party libraries):

Use filter-out

# exclude ASIO source code from $(SRC_FILES)
EXCLUDE_SRC_FILES := $(SRC_ROOT)/3rdParty/Asio/asio/impl/%.cpp
SRC_FILES := $(filter-out $(EXCLUDE_SRC_FILES),$(SRC_FILES))

NOTE: filter-out cannot handle complex regex like %${infix}%. Therefore, you might have to know what exactly are in the paths of the third party libraries.

More General Solution

Sample code from my Android.mk (here we do not want to compile the source code from some thrid party libraries):

# exclude ASIO source code from $(SRC_FILES)
EXCLUDE_SRC_PATTERN := asio
FILTER_OUT_PATTERN = $(foreach v,$(2),$(if $(findstring $(1),$(v)),,$(v)))
SRC_FILES := $(call FILTER_OUT_PATTERN,$(EXCLUDE_SRC_PATTERN),$(SRC_FILES))

NOTE:

  • I strongly recommend this method because the details of the third party libraries are hidden and it doesn't depend on external commands, which is portable.
  • DO NOT use SPACE to format the Makefile formulas!

e.g. The following command will not work as expected, since the " " is treated as part of the input strings.

SRC_FILES := $(call FILTER_OUT_PATTERN, $(EXCLUDE_SRC_PATTERN), $(SRC_FILES))

Reference:

Print Variable for Debugging

$(warning $(VAR))