您的位置:首页 > 其它

一个通用Makefile模板

2012-03-19 16:27 387 查看
最近学习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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: