模块式编译的Makefile

来源:互联网 发布:js 原生排序 编辑:程序博客网 时间:2024/06/04 23:30


              平时少不了在linux下写Demo,每次都gcc -o 或者单独写个不可移植的Makefile真的很麻烦,所以写个通用的Makefile很重要。我们在shell下make,有时当前目录下是子目录,有时是编译目录。这点需要区分。这里约定,如果当前目录下是子目录,则需要一个dirs文件。我们假设一个目录如下:

-rwxr--r-- 1 stewart stewart   68 Aug  8 09:36 dirsdrwxr-xr-x 2 stewart stewart 4096 Aug 14 15:49 Iteractive_Server_Maindrwxr-xr-x 2 stewart stewart 4096 Aug 14 15:48 Iterative_Logging_Serverdrwxr-xr-x 2 stewart stewart 4096 Aug  9 14:47 Logging_Clientdrwxr-xr-x 2 stewart stewart 4096 Aug 12 09:23 Logging_Server

这里的dirs文件内容:

DIRS=Logging_ServerDIRS+=Iterative_Logging_ServerDIRS+=Server_Main
代表依次编译Logging_Server , Iterative_Logging_Server和Server_Main三个目录。


如果当前目录就是需要编译的目录,这里约定需要一个sources文件,制定编译的依赖,目标名以及目标类型。假设有个目录如下:

-rwxr--r-- 1 stewart stewart  883 Aug  7 13:35 Iterative_Logging_Server.cpp-rwxr--r-- 1 stewart stewart 1334 Aug  7 14:02 Iterative_Logging_Server.h-rwxr--r-- 1 stewart stewart 2001 Aug  7 09:55 Logging_Handler.cpp-rwxr--r-- 1 stewart stewart 1014 Aug  7 09:56 Logging_Handler.h-rwxr--r-- 1 stewart stewart  324 Aug  9 14:20 sources
这里的sources文件如下:

TARGET_NAME=libiterlogserTARGET_TYPE=soINCLUDE=/home/stewart/iWork/Thrid_party/ACE_wrappers/INCLUDE+=-I/home/stewart/iWork/ACE/Logging_ServerC_FLAGS=-L/home/stewart/iWork/Thrid_party/ACE_wrappers/lib -L/home/stewart/iWork/lib -llogging_server -lACESOURCES=Logging_Handler.cppSOURCES+=Iterative_Logging_Server.cpp
代表我要编译一个libiterlogser.so,它需要的头文件一个第三方库都在里面制定。下面Makefile登场:

.PHONY:all clear rebuild globalMAKEDIR=$(shell pwd)MAKE=makeCC=gccCP=g++AR=arCOPY=cpMV=mvRM=rm -fUSER_NAME=$(shell whoami)MAKE_CMD=ISLIB=DIR_WORK_ROOT=/home/stewart/iWorkDIR_SYS_INC=$(DIR_WORK_ROOT)/includeDIR_SYS_LIB=$(DIR_WORK_ROOT)/libDIR_INCLUDE_LOCAL=$(DIR_WORK_ROOT)/commonDIR_INCLUDE_DBUS=/usr/include/dbus-1.0DIR_INCLUDE_SOCKET=/usr/include/arpaHEAD_INCLUDE=-I$(DIR_SYS_INC) -I$(DIR_INCLUDE_LOCAL) -I$(DIR_INCLUDE_DBUS) -I$(DIR_INCLUDE_SOCKET)DIR_LIB_CONFIG=/usr/lib/pkgconfigDIR_COMMON_MAKEFILE=$(DIR_WORK_ROOT)/common/makefile_common.mk$(shell export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(DIR_SYS_LIB))PKG_DBUS=$(wildcard $(DIR_LIB_CONFIG)/dbus-1.pc)ifneq "$(PKG_DBUS)" ""PKG_CONFIG_DBUS=`pkg-config "dbus-1 > 1.0.0" --cflags --libs`else#$(info *WARNING* 'DBus' package file no found , the function may not be avaiable)PKG_CONFIG_DBUS=endifPKG_GTK=$(wildcard $(DIR_LIB_CONFIG)/gtk+-2.0.pc)ifneq "$(PKG_GTK)" ""PKG_CONFIG_GTK=`pkg-config "gtk+-2.0 > 2.0.0" --cflags --libs`else#$(info *WARNING* 'gtk+' package file no found , the function may not be avaiable)PKG_CONFIG_GTK=endifCOMPILE_CC=$(CC) -O2 -g $(HEAD_INCLUDE) $< $(PKG_CONFIG_DBUS) $(PKG_CONFIG_GTK) -finput-charset=utf-8 -L$(DIR_SYS_LIB)COMPILE_CP=$(CP) -O2 -g $(HEAD_INCLUDE) $< $(PKG_CONFIG_DBUS) $(PKG_CONFIG_GTK) -finput-charset=utf-8 -L$(DIR_SYS_LIB)TEMP_CP=$(CP) -O2 -g $(HEAD_INCLUDE) $(PKG_CONFIG_DBUS) $(PKG_CONFIG_GTK) -finput-charset=utf-8 -L$(DIR_SYS_LIB)SOURCES=$(wildcard $(MAKEDIR)/sources)   #检测当前目录下是否有sources文件OBJITEM=$(strip $(SOURCES))DIRS=$(wildcard $(MAKEDIR)/dirs)     #检测当前目录下是否有dir文件ifneq ($(SOURCES),)    MAKE_CMD=make_file         #如果当前目录下有sources文件,则define MAKE_CMD ,方便下面区分目录或者文件    include $(SOURCES)    TARGET_NAME:=$(strip $(TARGET_NAME))   #获取编译目标名    TARGET_TYPE:=$(strip $(TARGET_TYPE))        #获取编译目标类型(so , bin or  a)    ifeq ($(TARGET_NAME),)        $(error "*ERROR* variable 'TARGET_NAME' hasn't been set !")    endif    ifeq ($(TARGET_TYPE),)        $(error "*ERROR* variable 'TARGET_TYPE' hasn't been set !")    endif    ifeq ($(SOURCES),)        $(error "*ERROR* variable 'SOURCE_TYPE' hasn't been set ! ")    endif    ifneq "$(INCLUDE)" ""        EXTERN_INC+= -I$(INCLUDE)  #添加sources文件中的INCLUDES变量    endif    C_SOURCES=$(wildcard $(MAKEDIR)/*.c)    CPP_SOURCES=$(wildcard $(MAKEDIR)/*.cpp)    ifneq "$(CPP_SOURCES)" ""        ifeq "$(C_SOURCES)" ""            C=$(COMPILE_CP)        endif    endif    ifneq "$(C_SOURCES)" ""        ifeq "$(CPP_SOURCES)" ""            C=$(COMPILE_CC)        endif    endif#dispatch c and cpp source code#  对编译的目标类型进行区分#    ifeq "$(TARGET_TYPE)" "so"        C_FLAGS+=-shared -fPIC        TARGET_TYPE=.so    endififeq "$(TARGET_TYPE)" "bin"        TARGET_TYPE=endififeq "$(TARGET_TYPE)" "lib"        TARGET_TYPE=.a        ISLIB=yes    endifelse #ifneq "$(SOURCES)" ""    ifneq "$(DIRS)" ""        MAKE_CMD=        include $(MAKEDIR)/dirs    #如果当前目录下是子目录,则需要包含dirs文件,递归子目录    else        $(error dirs or sources file no found in current directory ($(MAKEDIR)))    endifendifOBJS=$(patsubst %.cpp,%.o,$(SOURCES))HFILE=$(shell ls *.h)ifndef MAKE_CMD     #如果 MAKE_CMD no defined,则需要遍历目录下的子目录all:traveltravel:@for dir in $(DIRS);do $(MAKE) -C $$dir -f $(DIR_COMMON_MAKEFILE) ;done   #递归地遍历目录下的目录或文件clean:@for dir in $(DIRS);do $(MAKE) -C $$dir -f $(DIR_COMMON_MAKEFILE) clean ;donerebuild:all cleanglobal:@echo Cleaning ...@$(RM) $(DIR_WORK_ROOT)/lib/*.*@$(RM) $(DIR_WORK_ROOT)/include/*.*@echo Clobber done...else .PHONY:all clean rebuild globalall:$(DIR_SYS_LIB)/$(TARGET_NAME)$(OBJS):$(SOURCES)@$(CP) -O2 -g -c -fPIC -finput-charset=utf-8 $(HEAD_INCLUDE) $(EXTERN_INC) $*.cpp -o $@  #编译目录下cpp文件为o$(DIR_SYS_LIB)/$(TARGET_NAME):$(OBJS)@echo Building $(MAKEDIR)    ifndef ISLIB@$(TEMP_CP) $(OBJS) -g -rdynamic -o $(DIR_SYS_LIB)/$(TARGET_NAME)$(TARGET_TYPE) -ldl -lrt $(C_FLAGS) #链接o文件    else@$(AR) rcs $(DIR_SYS_LIB)/$(TARGET_NAME)$(TARGET_TYPE) *.o  #ar o文件为a库    endif@$(MV) ./*.o $(DIR_WORK_ROOT)/lib@$(COPY) ./*.h $(DIR_WORK_ROOT)/includeclean:@echo Cleaning ...@$(RM) $(DIR_SYS_LIB)/$(TARGET_NAME)$(TARGET_TYPE)@for obj in $(OBJS);do $(RM) $(DIR_SYS_LIB)/$$obj ;done@echo Clean done...rebuild:clean allglobal:@echo Cleaning ...@$(RM) $(DIR_WORK_ROOT)/lib/*.*@$(RM) $(DIR_WORK_ROOT)/include/*.*@echo Clobber done...endif

以后每次编译只需make -f [makefile]即可,确实方便不少。也可以把这条命令写进shell脚本。

原创粉丝点击