关于Makefile的基本写法网上已经很多了,这里不再叙述, 这里主要探讨在实际的项目中,怎样写Makefile才能更容易维护和扩展.
我们知道,在写C/C++的程序中,少不了引用系统的头文件, 库文件以及自己定义的共通头文件, 库文件,
为了有利于以后的扩展,应该将他们分别定义成不同的变量, 写入共通的makefile中.另外 C/C++的各种编译,
连接选项,编译命令也应该写入共通的makefile中, 在各个编译子目录只需要将这个make file
包含(include)进来就可以了,下面通过一个具体的例来说明这个共通的make file的写法
1, file.mk
#系统头文件的目录
SYS_INCLUDE_PATH=/usr/include /usr/local/include usr/include/c++/3.4.3
#系统库文件的定义
SYS_LIB_PATH=/usr/lib /usr/local/lib
SYS_LIB=stdc++ c
#项目共通头文件的目录
LOCAL_INCLUDE_PATH=/work/common/include
#项目共通库文件的定义
LOCAL_LIB_PATH=/work/common/lib
LOCAL_LIB= util message exception
#把系统头文件的目录, 项目共通头文件的目录连接成编译器需要的头文件路径
INCLUDE_PATHS=$(LOCAL_INCLUDE_PATH) $(SYS_INCLUDE_PATH)
#把系统库文件的定义, 项目共通库文件的定义连接成编译器需要的库文件
LIB_PATH=$(LOCAL_LIB_PATH) $(SYS_LIB_PATH)
LIBS=$(LOCAL_LIB) $(SYS_LIB)
#对这些头文件加上-I/path
INCLUDE_PATHS:=$(INCLUDE_PATHS:%=-I%)
#对这些库文件目录加上-L/path
LIB_PATH:=$(LIB_PATH:%=-L%)
#对这些库文件目录加上-l/file
LIBS:=$(LIBS:%=-l%)
#编译器选项
CC=g++
DEBUG_FLAGS=-g
CCFLAGS=
CPPFLAGS=$(DEBUG_FLAGS) $(CCFLAGS) $(INCLUDE_PATH)
#编译成SO文件所需要的选项
SHARED_LIB=-shared -fPIC
#将目录中所有.cc文件取出来
SRC=$(wildcard *.cc)
#OBJS=$(patsubst %.cc,%.o,$(SRC))
#通过.cc文件名生成对应的.o文件名
OBJS=$(SRC:%.cc=%.o)
#分析目标文件的类型(执行文件,静态库文件,动态库文件)
SUFFIX=$(suffix $(TARGET))
#根据不同的目标文件类型,作成对应的连接指令
ifeq ($(SUFFIX),.so)
#so文件
LD_CMD=$(CC) $(SHARED_LIB) -o $@ $^
else
ifeq ($(SUFFIX),.a)
#.a文件
LD_CMD=ar rc $@ $^
else
#一般可执行文件
LD_CMD=$(CC) -o $@ $^ $(LIB_PATH) $(LIBS)
endif
endif
#连接
$(TARGET):$(OBJS)
$(LD_CMD)
#编译
%.o:%.cc
$(CC) $(CPPFLAGS) -c -o $@ $< $(INCLUDE_PATHS)
#伪目标
.phony:clean
clean:
rm -f *.o $(TARGET)
2, 各个编译子目录的Makefiel只要如下写就可以了
#目标
TARGET=libcommon.so
include /make_common/file.mk
3, 多目录同时编译的共同Makefile
dir.mk
SUBDIRS=$(SUBDIRNAME:%=`pwd`/%)
all:
@for d in $(SUBDIRS); do \
cd $$d; make; \
done
clean:
@for d in $(SUBDIRS); do \
cd $$d; make clean; \
done
4, 然后在各个编译子目录的父目录下加入如下的Makefile
#各个编译子目录
SUBDIRNAME=app lib
include /make_common/dir.mk
另外,make -v 可以查看各个编译步骤