在linux下用C++编程有一段时间了,但自己写的Makefile文件,总让我感觉不爽。终于今天有时间来研究这个问题。
Makefile的难点不是那几条规则的写法,而是make里存在的大量“潜规则”。其实这些潜规则,都可以通过 make -p 命令查看。里面最重要的,无非是cpp的编译潜规则: $(CXX) -c $(CPPFLAGS) $(CXXFLAGS),而链接潜规则为:$(CC) $(LDFLAGS) n.o $(LOADLIBES) $(LDLIBS)。因此,需要设置的编译链接变量一般是 CPPFLAGS,CXXFLAGS,LDFLAGS, LDLIBS。详细的说明,可以参考make的手册。有一点需要注意,如果规则的目标,依赖和命令三项都写好了,那么潜规则就不会作用于此规则。下面贴出自己不断改写得到的一个Makefile文件:
#分别为链接库,头文件目录和编译选项
LDLIBS = -lmilterplusplus -lpthread -lresolv -lsm -lsmutil -lmilter/libmilter -lvmime -lboost_filesystem-gcc41-mt
INCLUDES= -I/usr/local/include/boost-1_35
CXXFLAGS= -O2 -Winvalid-pch $(INCLUDES)
#为工程里包含的.cpp文件,相应的.h或.o文件都由.cpp文件名导出。这样就只用写一次。
SRCS = spamd.cpp spams.cpp Detector.cpp MailClassification.cpp /
Model_Window.cpp svm.cpp Train.cpp utils.cpp
#导出了.cpp文件对应的.o文件
OBJECTS = $(SRCS:.cpp=.o)
ALL: inc spamd test .PHONY : ALL
#包含.cpp对应的.d文件,这些.d文件都是由.src文件生成的依赖文件,
#是由此Makefile文件最后的%.d : %.cpp的规则产生的。
-include $(SRCS:.cpp=.d)
# 工程输出的可执行文件1
spamd: $(OBJECTS)
$(CXX) $(CXXFLAGS) $(LDLIBS) $(OBJECTS) -o $@
# 工程输出的可执行文件2
test: test.cpp
$(CXX) $(CXXFLAGS) $(LDLIBS) test.cpp -o $@
.PHONY : inc
inc: inc.h.gch
.PHONY : clean
clean:
-rm *.o *.d
-rm inc.h.gch
-rm spamd test
#使用预编译头文件
%.h.gch : %.h
$(CXX) $(CXXFLAGS) ___FCKpd___0lt;
#根据.cpp文件,生成它依赖的.h关系文件.d
%.d : %.cpp
@set -e; rm -f $@; / $(CXX) -MM $(CPPFLAGS) ___FCKpd___0lt; > $@.$$; /
sed 's,/($*/)/.o[ :]*,/1.o $@ : ,g' < $@.$$ > $@; /
rm -f $@.$$
其实以上的Makefile还不是非常简洁(也许还有一些bug),相信还有更好的办法。研究还要继续。