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:
- [Android.mk - build all source file in a directory](http://stackoverflow.com/questions/18348969/android-mk-build-all-source-file-in-a-directory)
- [Recursive wildcards in GNU make?](http://stackoverflow.com/questions/2483182/recursive-wildcards-in-gnu-make)
- [Sources from subdirectories in Makefile](http://stackoverflow.com/questions/4036191/sources-from-subdirectories-in-makefile)
- [Makefile issue: smart way to scan directory tree for .c files](http://stackoverflow.com/questions/3774568/makefile-issue-smart-way-to-scan-directory-tree-for-c-files)
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:
- [Makefile: Filter out strings containing a character](http://stackoverflow.com/questions/6145041/makefile-filter-out-strings-containing-a-character)
- [Makefile Using ifeq condition inside foreach loop](http://stackoverflow.com/questions/8503043/makefile-using-ifeq-condition-inside-foreach-loop)
Print Variable for Debugging
$(warning $(VAR))