最近学习Makefile,写了一个C++编译的通用Makefile模板
它能做什么:
1. 能编译出应用程序,静态库,动态库
2. 可以用在任意目录结构的工程
3. 可以指定多个源文件后缀
4. 可以指定源文件的排除目录和排除文件列表
5. 已经充分考虑了源文件与头文件的依赖关系
6. 使用简单,只需要修改USER-DEFINED SECTION中的几个参数
执行流程:
1. USER-DEFINED参数检查
2. 搜索当前目录下的所有目录及子目录,并去掉排除目录,得到源文件目录
3. 在源文件目录中搜索带有源后缀的源文件,并去掉排除文件,得到源文件列表
4. 根据源文件列表得到.o和.d文件列表
5. 对源文件列表里的每个文件,计算其依赖关系,并动态生成规则
6. 执行BEFOREBUILD规则,做些准备工作,用户可以在这里做些其它工作,如,编译依赖工程
7. 执行TARGET规则,根据TYPE编译目标
8. 执行AFTERBUILD规则,做些后期工作,用户可以在这里做些收尾工作,如,把目标拷到指定目录
下面是这个模板的内容
###################################################################
# Makefile template
# author hitzheng@gmail.com
# date 2012-03-18
# usage:
# 1. customize the USER-DEFINED SECTION
# 2. make build the target
# 3. make clean clean all
# 4. make objs build .o and .d only
# 5. make help show help
# 6. make show show build variables
# 7. add something to BEFOREBUILD or AFTERBUILD if needed
###################################################################
#### USER-DEFINED SECTION #########################################
# compiler
CC := g++
# target name
TARGET :=
# compile flags
CFLAGS := -g -Wall
# ld flags for libraries
LDFLAGS :=
# target type: exe static shared
TYPE := exe
# source file extension
SRCEXT := .c .cpp
# output directory
OBJ_DIR := bin
# dirs exclude from searching sources
EXCLUDE_DIRS := $(OBJ_DIR) .svn
# files exclude from source list
EXCLUDE_FILES :=
#### DO NOT CHANGE THIS SECTION ###################################
EMPTY :=
SPACE := $(EMPTY) $(EMPTY)
TARGET := $(strip $(TARGET))
TYPE := $(strip $(TYPE))
ifeq ($(TARGET),)
TARGET := a.out
endif
TARGET := $(TARGET:%=$(OBJ_DIR)/%)
ifeq ($(filter $(TYPE),exe static shared),)
$(error type $TYPE is error)
endif
# regexp for exclude dirs used in grep
EXCPAT := $(foreach d,$(EXCLUDE_DIRS),\\/$(d)\\\>)
EXCPAT := $(subst $(SPACE),\\\|,$(EXCPAT))
# get all dirs exclude the EXCLUDE_DIRS
SRCDIRS := $(patsubst ./%,%,$(shell find . -type d | grep -v $(EXCPAT)))
# get the source list
SRCLIST := $(foreach d,$(SRCDIRS),$(wildcard $(addprefix $(d)/*, $(SRCEXT))))
SRCLIST := $(filter-out $(EXCLUDE_FILES), $(SRCLIST))
# objects list
OBJS := $(basename $(notdir $(SRCLIST)))
OBJS := $(OBJS:%=$(OBJ_DIR)/%.o)
DEPS := $(OBJS:.o=.d)
#generate rules for objects, $1:rule $2:source
define rule_objs
$(OBJ_DIR)/$1
$(CC) -c $(CFLAGS) $2 -MMD -o $(patsubst %,$(OBJ_DIR)/%.o,$(basename $(notdir $2)))
endef
###################################################################################
.PHONY: all objs clean show help
all : BEFOREBUILD $(TARGET) AFTERBUILD
objs : $(OBJS)
# GENERATE RULES FOR OBJECTS
$(eval $(foreach src,$(SRCLIST),$(call rule_objs,$(shell $(CC) -MM $(src)),$(src))))
# TARGET RULE
$(TARGET) : $(OBJS)
ifeq ($(TYPE),exe)
@echo "build exe...."
$(CC) $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@
else ifeq ($(TYPE),static)
@echo "build static library..."
ar rcs $@ $(OBJS)
else ifeq ($(TYPE),shared)
@echo "build shared objects..."
$(CC) -fpic -shared $(CFLAGS) $(OBJS) $(LDFLAGS) -o $@
else
@echo "target type:$(TYPE) error!!!"
endif
# DO SOMETHING HERE BEFORE BUILD
BEFOREBUILD:
@echo "do preparations before build..."
@if [ ! -e $(OBJ_DIR) ];then mkdir -p $(OBJ_DIR);echo "mkdir $(OBJ_DIR)";fi
# DO SOMETHING HERE AFTER BUILD
AFTERBUILD:
@echo "build finish, do something here"
clean:
$(RM) $(OBJS) $(DEPS) $(TARGET)
help:
@echo "usage:"
@echo "1. customize the USER-DEFINED SECTION"
@echo "2. make build the target"
@echo "3. make clean clean all"
@echo "4. make objs build .o and .d only"
@echo "5. make help show help"
@echo "6. make show show build variables"
@echo "7. add something BEFOREBUILD or AFTERBUILD if needed"
# DEBUG USE ONLY
show:
@echo "TARGET: "$(TARGET)
@echo "TYPE: "$(TYPE)
@echo "CFLAGS: "$(CFLAGS)
@echo "LDFLAGS: "$(LDFLAGS)
@echo "EXCLUDE_DIRS: "$(EXCLUDE_DIRS)
@echo "EXCLUDE_FILES: "$(EXCLUDE_FILES)
@echo "EXCPAT: "$(EXCPAT)
@echo "SRCDIRS: "$(SRCDIRS)
@echo "SRCLIST: "$(SRCLIST)
@echo "OBJS: "$(OBJS)
@echo "DEPS: "$(DEPS)
本文介绍了一个通用的Makefile模板,能够支持C++项目的编译,包括应用程序、静态库和动态库。该模板支持任意目录结构,可自定义源文件后缀,并已实现源文件与头文件的依赖管理。

400

被折叠的 条评论
为什么被折叠?



