makefile通用模板

###########################################################
#
# 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)
原文地址:https://www.cnblogs.com/fengtai/p/12640603.html