异想天开

What's the true meaning of light, Could you tell me why

Makefile模板

日期:2015-03-25 10:45:28
  
最后更新日期:2015-06-22 13:12:00
【技术】
写个程序,才发现连个makefile的模板之前也没有积累,于是网上查找了一些makefile模板,改写了下面这个适用自个今后开发的模板。
PS:直接从浏览器复制,并不能直接使用,因为makefile所要求的那个tab,被复制没了
适用情况:
1.文件目录层次要求,目录层次一般只有一层,lib/里面可以准许有子目录,里面可以放一些的改动过的开源源码库。整体目录层次如下:
----dev----
bin/
server/
core/
lib/
lib/json/
lib/jsonp/
Makefile
尽量使用文件夹将耦合性不大的文件隔开。
2.makefile的规则显示指定。
3.支持源码里面c文件和cpp文件混合。

[code lang="cpp"]
CC=gcc
CXX=g++
INCLUDE:= -I./
CFLAGS:= -g -Wall -Werror $(INCLUDE)
CPPFLAGS:= $(CFLAGS)
LIB=

PROGRAM:=bin/test
LIBSRC=lib
LIBDIR:=$(patsubst %/,%,$(wildcard $(LIBSRC)/*/))
SUBDIRS:=core server $(LIBDIR)
SOURCES=$(foreach SUBDIR,$(SUBDIRS),$(wildcard $(SUBDIR)/*.c) $(wildcard $(SUBDIR)/*.cpp))
OBJECTS=$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
DEPENDENCE:=$(patsubst %.o,%.d,$(OBJECTS))

INCLUDE+=$(patsubst %,-I%,$(SUBDIRS))
CFLAGS+=$(INCLUDE)
CPPFLAGS+=$(INCLUDE)

all:$(PROGRAM)

$(PROGRAM): $(OBJECTS)
$(CXX) $(CPPFLAGS) $^ $(LIB) -o $(PROGRAM)

%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@

%.o: %.cpp
$(CXX) $(CPPFLAGS) -c $< -o $@


define gen_dep
set -e; rm -f $@; \
$(CXX) -MM $(CPPFLAGS) $< > $@.temp ; \
sed 's,\(.*\.o\)[ ]*:,$*\.o $@ : ,g' < $@.temp > $@ ; \
rm -f $@.temp
endef

%.d: %.c
$(gen_dep)

%.d: %.cpp
$(gen_dep)

-include $(DEPENDENCE)

.PHONY: clean
clean:
rm -f $(PROGRAM) $(OBJECTS) $(DEPENDENCE)

echo:
@echo SOURCES=$(SOURCES)
@echo OBJECTS=$(OBJECTS)
@echo DEPENDENCE=$(DEPENDENCE)
@echo $(patsubst %/,%,$(wildcard $(LIBSRC)/*/))
[/code]
解释:
1.扫描一层目录的源代码,扫描lib目录的子目录,生成目标.o文件名和依赖.d文件名。
[code lang="cpp"]
PROGRAM:=bin/test
LIBSRC=lib
LIBDIR:=$(patsubst %/,%,$(wildcard $(LIBSRC)/*/))
SUBDIRS:=core server $(LIBDIR)
SOURCES=$(foreach SUBDIR,$(SUBDIRS),$(wildcard $(SUBDIR)/*.c) $(wildcard $(SUBDIR)/*.cpp))
OBJECTS=$(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
DEPENDENCE:=$(patsubst %.o,%.d,$(OBJECTS))
[/code]

2..d规则(生成.o的规则容易看懂)
[code lang="cpp"]
define gen_dep
set -e; rm -f $@; \
$(CXX) -MM $(CPPFLAGS) $< > $@.temp ; \
sed 's,\(.*\.o\)[ ]*:,$*\.o $@ : ,g' < $@.temp > $@ ; \
rm -f $@.temp
endef
[/code]
该条规则类似一个宏,需要注意的是,利用g++产生依赖时,目标文件,不是绝对路径,而依赖的文件是带有绝对路径的。
[code lang="cpp"]
[root@localhost proxy]# g++ -MM core/ngx_rbtree.c
ngx_rbtree.o: core/ngx_rbtree.c
[/code]
故需要改写,同时.o和.d的依赖是一样的,需要在g++ -MM 的结果添加.d文件。这条命令:
[code lang="cpp"]
sed 's,\(.*\.o\)[ ]*:,$*\.o $@ : ,g' < $@.temp > $@
[/code]
就是做这样的事,$*,$@是makefile里面的自动变量。
[code lang="cpp"]
core/ngx_rbtree.o : core/ngx_rbtree.c core/ngx_rbtree.h
@echo $* $@
[/code]
$@为core/ngx_rbtree.o,$*为core/ngx_rbtree。
3.sed是stream edit命令,s即执行替换,原型如下:
[code lang="cpp"]
sed 's,正则匹配部分,替换部分,参数'
[/code]
参数为g表示全局替换。
4.make的内建函数
subpatst执行替换
wildcard扫描符合条件的文件或目录