快速实现工程makefile的简单通用模板
2016-12-08 19:43
399 查看
以前刚开始接触linux开发的时候,发现makefile真麻烦,我学C/C++开发已经花了不少时间了,现在还要花这个时间类搞这玩意,真是麻烦。真希望能出现一个模板,我只需要填下我需要编译的文件,以及相应的目录,其他的我啥都不用管,该多好呀。本文就是奔着这个目标来的,所以本文不会描述makefile的语法啥的。
工作了这么多年,大大小小的工程已经也开发了不少,幸好公司也有一个模板,我平时都是用公司的模板,我只需要往里面填一些个要编译的文件,以及工程依赖的其他库、头文件目录、库目录,生成目录,除了这些外,我基本上啥都不用关心,真心舒服,但是公司模板也有他的缺陷,就是C和C++不能同时编译,还有就是所有的.o文件不能放到同一个目录,当然这些都不是问题,对于我来说,有点受够了,于是自己对公司的模板动手了。
先写一个我平时写的makefile
这就是一个进程的makefile 。这样看起来可能也是有点多,如果就仅仅是编译一个helloworld,用这个确实很麻烦,还不如我直接调用gcc -c -o …来的快,但是如果写一个工程量较大的makefile来说的话,这个还是很方便的,你只需要关注几个变量:
SRCS:所有的源码都需要使用这个,类似如下:
SRCS += $(SRC_DIR)/SDL.c
SRCS += $(SRC_DIR)/SDL_assert.c
…
INC_PATH 所有的头文件的路径 类似SRCS的写法可以使用 +=
LIBS 依赖的所有库
APP_TARGET进程的标示,SO_TARGET 动态库 ARC_TARGET静态库标示
COMM_DIR存放cxxcommon.mk路径
其他的基本上都是一些个临时变量了,所有的东西都在cxxcommon.mk
,这个里面的东西,你基本不用修改,而只需要关注自己的makefile就好了,除非你有特殊的要求。我的cxxcommon.mk的内容粘贴下
你可以把这些信息拷贝下来,保存到你的.mk文件中,下文最后一行include给修改成你的mk文件就好了,另外你的mk的路径就是COMM_DIR
好了,你可以尝试试用下看看。我修改我的大型工程,修改起来还是很快的。
工作了这么多年,大大小小的工程已经也开发了不少,幸好公司也有一个模板,我平时都是用公司的模板,我只需要往里面填一些个要编译的文件,以及工程依赖的其他库、头文件目录、库目录,生成目录,除了这些外,我基本上啥都不用关心,真心舒服,但是公司模板也有他的缺陷,就是C和C++不能同时编译,还有就是所有的.o文件不能放到同一个目录,当然这些都不是问题,对于我来说,有点受够了,于是自己对公司的模板动手了。
先写一个我平时写的makefile
TOP := .. COMM_DIR := . SRC_DIR := $(TOP)/source ## Name and type of the target for this Makefile INSTALL_APP_PATH := ./debug APP_TARGET := smart ## Define debugging symbols DEBUG = 1 ## Object files that compose the target(s) SRCS := $(wildcard $(SRC_DIR)/*.cpp) ## Libraries to include in shared object file LIBS :=pthread dl ## Add driver-specific include directory to the search path CFLAGS += -D_LINUX_ INC_PATH += $(TOP)/include LIB_PATH := ./debug INSTALL_LIB_PATH = ./debug include $(COMM_DIR)/cxxcommon.mk
这就是一个进程的makefile 。这样看起来可能也是有点多,如果就仅仅是编译一个helloworld,用这个确实很麻烦,还不如我直接调用gcc -c -o …来的快,但是如果写一个工程量较大的makefile来说的话,这个还是很方便的,你只需要关注几个变量:
SRCS:所有的源码都需要使用这个,类似如下:
SRCS += $(SRC_DIR)/SDL.c
SRCS += $(SRC_DIR)/SDL_assert.c
…
INC_PATH 所有的头文件的路径 类似SRCS的写法可以使用 +=
LIBS 依赖的所有库
APP_TARGET进程的标示,SO_TARGET 动态库 ARC_TARGET静态库标示
COMM_DIR存放cxxcommon.mk路径
其他的基本上都是一些个临时变量了,所有的东西都在cxxcommon.mk
,这个里面的东西,你基本不用修改,而只需要关注自己的makefile就好了,除非你有特殊的要求。我的cxxcommon.mk的内容粘贴下
### Keda Telecom, Inc.(kedacom.com 俺东家) ### ARC_TARGET - target name for archive file, excluding file extension. ### ARC_TARGET - 静态库 ### ### SO_TARGET - target name for shared object file, excluding file extension. ### SO_TARGET - 动态库 ### APP_TARGET - target name of application. ### APP_TARGET - 进程 ### ### SRCS 源代码文件 一般是.c .cpp等 非头文件 ### ### LIB_SUFFIX 其实就是在文件后面加一个字符串,一般没啥用 ### ### TOP 顶层目录 ### ### OBJDIR 临时库存放的目录,如果没有给出,就会在顶层目录下面创建一个build目录 ### ### INC_PATH 所有头文件的目录 ### ### LIB_PATH 如果是so 或者是APP,需要依赖的lib库目录 ### ### LIBS 所有的依赖库 ### ### INSTALL_LIB_PATH 静态库安装目录 ### ### INSTALL_APP_PATH APP安装目录 ### ### APP_DIR APP安装在INSTALL_APP_PATH目下的子目录 如果定义了INSTALL_APP_PATH,就会忽略APP_DIR ### ### CROSS 交叉编译时使用 ### ### SUB_FILE 其他需要安装的文件列表 ### ### CP_FILE 需要拷贝的文件 ### ### CPFILE_PATH 需要拷贝到指定的目录 ## ARC_TARGET 静态库 后面加 .a ifneq ($(ARC_TARGET),) ARC_TARGET := lib$(ARC_TARGET)$(LIB_SUFFIX).a endif ## SO_TARGET shared库 后面加.so ifneq ($(SO_TARGET),) SO_TARGET := lib$(SO_TARGET)$(LIB_SUFFIX).so endif ## 如果木有存放临时库的地方,存放top目录下build ifeq ($(OBJDIR),) OBJDIR :=$(TOP)/build/ endif ## C的源文件 CSRCS:=$(filter %.c %.C,$(SRCS)) ## C++的源文件 CPPSRCS:=$(filter %.cc %.CC %.cpp %.Cpp %.CPP,$(SRCS)) ## 去除目录,只剩文件名和后缀,此时只需要把后缀修改成.o然后再加上一个目录,就是OBJS了 SRCFILE:=$(notdir $(SRCS)) ## 所有 .o文件存放路径 #OBJS:=$(patsubst %.c,%.o,$(SRCFILE)) OBJS :=$(SRCFILE:.c=.o) OBJS :=$(OBJS:.C=.o) OBJS :=$(OBJS:.cc=.o) OBJS :=$(OBJS:.CC=.o) OBJS :=$(OBJS:.cpp=.o) OBJS :=$(OBJS:.Cpp=.o) OBJS :=$(OBJS:.CPP=.o) #OBJS :=$(addprefix $(OBJDIR),$(OBJS)) OBJS :=$(foreach file,$(SRCS),$(OBJDIR)$(basename $(notdir $(file))).o) ## 如果是 Debug模式 如下 ifeq ($(DEBUG),1) CFLAGS += -g CFLAGS += -O0 CFLAGS += -DDEBUG=$(DEBUG) endif ## Release ifeq ($(DEBUG),0) CFLAGS += -O2 CFLAGS += -DNDEBUG endif # 动态库 ifneq ($(SO_TARGET),) CFLAGS += -fpic endif #科达的通讯库如osp必须要 _LINUX_,所以此处增加一个,木有坏处 CFLAGS += -D_LINUX_ #所有头文件 路径 CFLAGS += $(foreach dir,$(INC_PATH),-I$(dir)) #依赖的静态库路径 LDFLAGS += $(foreach lib,$(LIB_PATH),-L$(lib)) # 动态库 ifneq ($(SO_TARGET),) LDFLAGS += -shared endif ## 加入 rt库 LDFLAGS += -lrt ##链接的所有静态库 LDFLAGS += $(foreach lib,$(LIBS),-l$(lib)$(LIB_SUFFIX)) ## 如果木有提供INSTALL_LIB_PATH 程序自动给出目录 ifndef INSTALL_LIB_PATH INSTALL_LIB_PATH = $(TOP)/lib/ endif ## 默认应用程序安装路径 ifndef INSTALL_APP_PATH ## ifneq($(APP_DIR),) ## INSTALL_APP_PATH = $(TOP)/app/$(APP_DIR) ## else INSTALL_APP_PATH = $(TOP)/app ## endif endif CP = $(CROSS)cp CC = $(CROSS)gcc CPP = $(CROSS)g++ LD = $(CROSS)g++ AR = $(CROSS)ar INSTALL = install -D -m 644 OBJDUMP = objdump RM = -@rm -f define NEWLINE endef ## 去掉前后空格后ARC_TARGET还有值 ifneq ($(strip $(ARC_TARGET)),) ## CFLAGS += -DFD_SETSIZE=512 all: $(ARC_TARGET) ARLINK ARCINSTALL install_arc: $(ARC_TARGET) ARLINK ARCINSTALL #$(AR) crus $(ARC_TARGET) $(OBJS) #$(INSTALL) $(ARC_TARGET) $(INSTALL_LIB_PATH)/$(ARC_TARGET) $(ARC_TARGET) : GENEOBJ ARLINK: $(AR) crus $(ARC_TARGET) $(OBJS) ARCINSTALL: $(INSTALL) $(ARC_TARGET) $(INSTALL_LIB_PATH)/$(ARC_TARGET) uninstall: uninstallarc uninstallarc: $(foreach file, $(INSTALL_INC), $(RM) $(INSTALL_INC_PATH)/$(file) $(NEWLINE)) $(RM) $(INSTALL_LIB_PATH)/$(ARC_TARGET) clean: cleanarc cleanarc: $(RM) $(ARC_TARGET) $(OBJS) endif ifneq ($(strip $(SO_TARGET)),) all: install install: install_inc install_so install_so: $(SO_TARGET) $(INSTALL) $(SO_TARGET) $(INSTALL_LIB_PATH)/$(SO_TARGET) $(foreach file, $(SUB_FILE), $(INSTALL) $(file) $(INSTALL_LIB_PATH)/$(file) $(NEWLINE)) $(foreach file, $(CP_FILE), $(CP) -rf $(CPFILE_PATH)$(file) $(INSTALL_LIB_PATH)/$(file) $(NEWLINE)) $(SO_TARGET) : GENEOBJ $(LD) $(OBJS) -o $(SO_TARGET) $(LDFLAGS) -fpic uninstall: uninstallso uninstallso: $(foreach file, $(INSTALL_INC), $(RM) $(INSTALL_INC_PATH)/$(file) $(NEWLINE)) $(RM) $(INSTALL_LIB_PATH)/$(ARC_TARGET) clean: cleanso cleanso: $(RM) $(SO_TARGET) $(CP_FILE) $(OBJS) else #echo $(SRCFILE) #$(foreach file,$(OBJS), $(file)) endif ## Rules for making applications ifneq ($(strip $(APP_TARGET)),) all: install install: install_inc install_app install_app: $(APP_TARGET) $(INSTALL) $(APP_TARGET) $(INSTALL_APP_PATH)/$(APP_TARGET) $(APP_TARGET): GENEOBJ $(LD) $(OBJS) -o $(APP_TARGET) $(LDFLAGS) clean: cleanapp cleanapp: $(RM) $(APP_TARGET) endif GENEOBJ: createdir $(foreach file,$(CSRCS),$(CC) $(CFLAGS) -c -o $(OBJDIR)$(basename $(notdir $(file))).o $(file) $(NEWLINE)) $(foreach file,$(CPPSRCS),$(CPP) $(CFLAGS) -c -o $(OBJDIR)$(basename $(notdir $(file))).o $(file) $(NEWLINE)) install_inc: $(foreach file, $(INSTALL_INC), $(INSTALL) $(file) $(INSTALL_INC_PATH)/$(notdir $(file)) $(NEWLINE)) ##判断目录是否存在,不存在就创建 createdir: test -d $(OBJDIR) || mkdir -p $(OBJDIR) clean: cleanobjs cleanobjs: $(RM) $(OBJS) setup: (cd $(TOP); \ make install_inc; \ echo )
你可以把这些信息拷贝下来,保存到你的.mk文件中,下文最后一行include给修改成你的mk文件就好了,另外你的mk的路径就是COMM_DIR
好了,你可以尝试试用下看看。我修改我的大型工程,修改起来还是很快的。
相关文章推荐
- 一个简单的通用Makefile实现
- 简单的通用Makefile模板
- linux下面简单通用的Makefile模板
- 一个简单的通用Makefile实现
- 一个简单的通用Makefile实现
- linux简单的通用Makefile模板
- 一个简单的通用Makefile模板
- 一个简单的通用Makefile实现
- 一个简单的通用Makefile实现
- XML与ASP简单结合实现HTML模板功能
- 快速实现简单高效并可以灵活配置的URL重写方案(附源代码)
- 一个函数返回两值的通用实现方法(简单,备忘)
- 简单通用的makefile文件
- 最简单快速的apache二级域名实现方法
- 分析模板的一段简单快速的算法片段
- XML与ASP简单结合实现HTML模板功能
- 常见内部排序算法 简单数组实现与分析(快速(偶原创partition函数,望众高手指正)、归并、希尔、插入、选择、冒泡)
- 快速实现简单高效并可以灵活配置的URL重写方案(附源代码)
- ant build.xml 之 tomcat工程的通用模板
- [DataGrid技巧]将RadioButton加入到DataGrid模板列后单选简单实现