探索GNU Makefile的写法
时间:2009-05-17 来源:js_jammy
关于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 可以查看各个编译步骤
#系统库文件的定义 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 可以查看各个编译步骤
相关阅读 更多 +