转自 http://c4fun.cn/blog/2014/01/30/common-makefile/
赶在蛇年的最后一天,写了一个通用的GNU/Linux环境下的Makefile。
该Makefile适用于最后生成若干个可执行文件的小型C/C++工程,只要将该Makefile放在源码根目录下make,它会自动查找该目录下(包括子目录)的所有源码文件(支持.cpp .c .h格式)并自动生成正确的依赖关系,并且为了不污染源码文件夹,源码和编译过程中的中间文件会分开(Debug模式编译生成的中间文件在Debug目录下,Release模式在Release目录下)。
试了几个之前写过的Project,都是OK的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | ########################################################### # # 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") sources_c := $(filter %.c, $(sources_all)) sources_cpp := $(filter %.cpp, $(sources_all)) sources_h := $(filter %.h, $(sources_all)) 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))) # 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 += $(addprefix -I ,$(sort $(dir $(sources_h)))) CXXFLAGS = $(CFLAGS) LDFLAGS := LOADLIBES += #-L/usr/include/mysql LDLIBS += #-lpthread -lmysqlclient # 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) |