快速实现工程makefile的简单通用模板

以前刚开始接触linux开发的时候,发现makefile真麻烦,我学C/C++开发已经花了不少时间了,现在还要花这个时间类搞这玩意,真是麻烦。真希望能出现一个模板,我只需要填下我需要编译的文件,以及相应的目录,其他的我啥都不用管,该多好呀。本文就是奔着这个目标来的,所以本文不会描述makefile的语法啥的。
工作了这么多年,大大小小的工程已经也开发了不少,幸好公司也有一个模板,我平时都是用公司的模板,我只需要往里面填一些个要编译的文件,以及工程依赖的其他库、头文件目录、库目录,生成目录,除了这些外,我基本上啥都不用关心,真心舒服,但是公司模板也有他的缺陷,就是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
好了,你可以尝试试用下看看。我修改我的大型工程,修改起来还是很快的。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值