########################################################### # # MAKEFILE FOR C/C++ PROJECT # Author: swm8023 <swm8023@gmail.com> # Date: 2014/01/30 # ########################################################### .PHONY: all clean all: # annotation when release version DEBUG := y TARGET_PROG := main # project directory DEBUG_DIR := ./Debug RELEASE_DIR := ./Release BIN_DIR := $(if $(DEBUG), $(DEBUG_DIR), $(RELEASE_DIR)) # shell command CC := gcc CXX := g++ RM := rm -rf MKDIR := mkdir -p SED := sed MV := mv # init sources & objects & depends sources_all := $(shell find . -name "*.c" -o -name "*.cpp" -o -name "*.h") #$(filter PATTERN…,TEXT) #功能:过滤掉字串“TEXT”中所有不符合模式“PATTERN”的单词,保留所有符合此模式的单词。可以使用多个模式,存在多个模式时,模式表达式之间使用空格分割。 模式中一般需要包含模式字符“%”。 #返回:空格分割的“TEXT”字串中所有符合模式“PATTERN”的字串。 sources_c := $(filter %.c, $(sources_all)) sources_cpp := $(filter %.cpp, $(sources_all)) sources_h := $(filter %.h, $(sources_all)) #$(strip <string> ) #名称:去空格函数——strip。 #功能:去掉<string>字串中开头和结尾的空字符,并将中间的多个连续空字符(如果有的话)合并为一个空字符。 #返回:返回被去掉空格的字符串值。 #说明: 空字符包括 空格,tab等不可显示的字符 #$(addprefix fixstring,string1 string2 ...) #fixstring表示任意要添加的固定前缀,在逗号的后面可以是一个或多个要添加前缀的子字符串,多个子字符串之间用空格隔开 objs := $(addprefix $(BIN_DIR)/,$(strip $(sources_cpp:.cpp=.o) $(sources_c:.c=.o))) deps := $(addprefix $(BIN_DIR)/,$(strip $(sources_cpp:.cpp=.d) $(sources_c:.c=.d))) # $(foreach <var>,<list>,<text>) #foreach 把参数<list>;中的单词逐一取出放到参数<var>;所指定的变量中,然后再执行< text>;所包含的表达式。每一次<text>;会返回一个字符串,循环过程中,<text>;的所返回的每个字符串会以空格分隔,最后当整个循环结束时,<text>;所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。 #sort 函数功能:给字串“LIST”中的单词以首字母为准进行排序(升序),并取掉重复的单词。 #返回值:空格分割的没有重复单词的字串。 #$(dir <names...>) #dir 功能:从文件名序列<names>中取出目录部分。目录部分是指最后一个反斜杠(“/”)之前的部分。如果没有反斜杠,那么返回“./”。 #返回:返回文件名序列<names>的目录部分。 # create directory $(foreach dirname,$(sort $(dir $(sources_c) $(sources_cpp))), $(shell $(MKDIR) $(BIN_DIR)/$(dirname))) # complie & link variable CFLAGS := $(if $(DEBUG),-g -O, -O2) CFLAGS += -Wl,-rpath=./ CFLAGS += $(addprefix -I ,$(sort $(dir $(sources_h)))) CFLAGS += -I. -I/usr/local/include/mysqlconnector1.1.9 -I/usr/local/include/mysqlconnector1.1.9/cppconn CXXFLAGS = $(CFLAGS) LDFLAGS := #LOADLIBES += #-L/usr/include/mysql #LDLIBS += #-lpthread -lmysqlclient LOADLIBES += -L. LDLIBS += -lpthread -lmysqlcppconn #-llog4cxx -lzlog4cxx #1、vpath PATTERN DIRECTORIES #为符合模式“PATTERN”的文件指定搜索目录“DIRECTORIES”。多个目录使用空格或者 #冒号(:)分开。类似上一小节的“VPATH” #2、vpath PATTERN #清除之前为符合模式“PATTERN”的文件设置的搜索路径 # add vpath vpath %.h $(sort $(dir $(sources_h))) vpath %.c $(sort $(dir $(sources_c))) vpath %.cpp $(sort $(dir $(sources_cpp))) # generate depend files # actually generate after object generated, beacasue it only used when next make) ifneq "$(MAKECMDGOALS)" "clean" sinclude $(deps) endif # make-depend(depend-file,source-file,object-file,cc) define make-depend $(RM) $1; $4 $(CFLAGS) -MM $2 | $(SED) 's,($(notdir $3)): ,$3: ,' > $1.tmp; $(SED) -e 's/#.*//' -e 's/^[^:]*: *//' -e 's/ *\$$//' -e '/^$$/ d' -e 's/$$/ :/' < $1.tmp >> $1.tmp; $(MV) $1.tmp $1; endef # rules to generate objects file $(BIN_DIR)/%.o: %.c @$(call make-depend,$(patsubst %.o,%.d,$@),$<,$@,$(CC)) $(CC) $(CFLAGS) -o $@ -c $< $(BIN_DIR)/%.o: %.cpp @$(call make-depend,$(patsubst %.o,%.d,$@),$<,$@,$(CXX)) $(CXX) $(CXXFLAGS) -o $@ -c $< # add-target(target,objs,cc) define add-target REAL_TARGET += $(BIN_DIR)/$1 $(BIN_DIR)/$1: $2 $3 $(LDFLAGS) $$^ $(LOADLIBES) $(LDLIBS) -o $$@ endef # call add-target $(foreach targ,$(TARGET_PROG),$(eval $(call add-target,$(targ),$(objs),$(CXX)))) all: $(REAL_TARGET) $(TARGET_LIBS) clean: $(RM) $(BIN_DIR)