Inclusive Makefile
来源:互联网 发布:sai for mac版 编辑:程序博客网 时间:2024/06/06 14:53
以前项目中,我都用Recursive Make去构建编译环境。这种方式感觉直观,而且单一,仅仅用Makefile就可以完成,但是不足之处是,扩展起来麻烦,数据定义和规则耦合在一起,并且每执行一次子Make都要step到那个目录。耗时。最近发现在北电的项目中,使用了一种叫做Inclusive的Make。完全摒弃了Recursive的缺点。尤其是在定义和规则相分离上优势明显,并且扩展起来很方便。项目中通过Makefile+Perl+shell共同构建起了load build系统。我理解了他的思想后,写了一个demo.为了简化,我采用了Python+Makefile的组合。一共包含三个部分:
1.控制部分(build.xml)
2.模板部分
3.实例数据部分
控制部分主要的责任就是,利用模板将每个实例部分用实例数据实例化一个make对象,并执行它。
如果我们要添加模块,只需要在新模块目录下添加一份用来实例化对象的数据文件Build.mk就行了。
build.py / build.xml
from xml.etree.ElementTree import ElementTree
import os
import sys
from optparse import OptionParser
class InitConfiguration:
def __init__(self):
self.dir = ""
self.modules = []
def initialize(self , file):
if os.path.exists(file):
print "parsing:" , file
else:
print "can not find the file:" , file
sys.exit(-1)
xmlTree = ElementTree().parse(file)
for node in xmlTree.getchildren():
if node.tag == "topdir":
self.dir = node.text
if node.tag == "module":
self.modules.append(node.text)
def invoke(self):
cmd = "make MODULE=/'"
for arg in self.modules:
cmd = "make MODULE="
cmd += arg
cmd += " TOPDIR="
cmd += self.dir
print cmd
os.system(cmd)
def clean(self):
cmd = "make MODULE=/'"
for arg in self.modules:
cmd = "make MODULE="
cmd += arg
cmd += " TOPDIR="
cmd += self.dir
cmd += " clean_objs"
print cmd
os.system(cmd)
os.system("make clean_libs clean_bins")
def main():
init = InitConfiguration()
init.initialize("../config/Build.xml")
usage = "%prog options"
optionParser = OptionParser(usage)
optionParser.add_option('--opt', dest='opt' , help='')
(options , args) = optionParser.parse_args()
if options.opt == "clean":
init.clean()
return
init.initialize("../config/Build.xml")
init.invoke()
return
if __name__ == "__main__":
main()
------------------------------------------------------------------
<build>
<topdir>../../src/lteoff/domain/oam</topdir>
<module>pm</module>
<module>fm</module>
<module>sm</module>
<module>util</module>
</build>
模板Makefile:
MODULEDIR = $(patsubst %,$(TOPDIR)/%,$(MODULE))
INSTALL = /usr/bin/install
CC = g++
AR = $(CC)
ARFLAGS = -shared
RM = rm -rf
CXXFLAGS = -O3 -g -Wall
LDFLAGS = -lpthread
CPPFLAGS = -I./
LIBPATH = -L./
LINK = $(CC) -o ../../bin/$@ $^
ARCLIB = $(AR) $(ARFLAGS) -o ../../lib/lib$@.so $^ $(LDFLAGS) $(LIBPATH)
include $(patsubst %,%/Build.mk,$(MODULEDIR))
ifneq (,$(ARCHIVE))
ifneq (,$(PROGRAM))
DEPEND += $(ARCHIVE) $(PROGRAM)
else
DEPEND += $(ARCHIVE)
endif
else
ifneq (,$(PROGRAM))
DEPEND += $(PROGRAM)
endif
endif
APP_VAR = $($(PROGRAM)_SRC)
ARC_VAR = $($(ARCHIVE)_SRC)
APP_OBJS = $(patsubst %.cpp,%.o,$(APP_VAR))
ARC_OBJS = $(patsubst %.cpp,%.o,$(ARC_VAR))
%.o: %.cpp
@(echo compiling $@)
$(CC) -c $< -o $@ $(CPPFLAGS) $(CXXFLAGS)
all: $(DEPEND)
@(echo done)
$(ARCHIVE): $(ARC_OBJS)
@(echo creating archive $(LIB))
$(ARCLIB)
$(PROGRAM): $(APP_OBJS)
@(echo creating executing file $(BIN))
$(LINK)
.PHONY: clean_objs clean_libs clean_bins
clean_objs:
$(RM) $(MODULEDIR)/*.o
clean_libs:
$(RM) ../../lib/*
clean_bins:
$(RM) ../../bin/*
最后是数据Makefile,在每个字模块目录下面都有一个Build.mk,里面存放了为模板Makefile实例化的数据
Build.mk
PROGRAM = fmApp
fmApp_SRC = $(TOPDIR)/fm/fmApp.cpp
ARCHIVE = fm
fm_SRC = $(TOPDIR)/fm/fm.cpp
1.控制部分(build.xml)
2.模板部分
3.实例数据部分
控制部分主要的责任就是,利用模板将每个实例部分用实例数据实例化一个make对象,并执行它。
如果我们要添加模块,只需要在新模块目录下添加一份用来实例化对象的数据文件Build.mk就行了。
from xml.etree.ElementTree import ElementTree
import os
import sys
from optparse import OptionParser
class InitConfiguration:
def __init__(self):
self.dir = ""
self.modules = []
def initialize(self , file):
if os.path.exists(file):
print "parsing:" , file
else:
print "can not find the file:" , file
sys.exit(-1)
xmlTree = ElementTree().parse(file)
for node in xmlTree.getchildren():
if node.tag == "topdir":
self.dir = node.text
if node.tag == "module":
self.modules.append(node.text)
def invoke(self):
cmd = "make MODULE=/'"
for arg in self.modules:
cmd = "make MODULE="
cmd += arg
cmd += " TOPDIR="
cmd += self.dir
print cmd
os.system(cmd)
def clean(self):
cmd = "make MODULE=/'"
for arg in self.modules:
cmd = "make MODULE="
cmd += arg
cmd += " TOPDIR="
cmd += self.dir
cmd += " clean_objs"
print cmd
os.system(cmd)
os.system("make clean_libs clean_bins")
def main():
init = InitConfiguration()
init.initialize("../config/Build.xml")
usage = "%prog options"
optionParser = OptionParser(usage)
optionParser.add_option('--opt', dest='opt' , help='')
(options , args) = optionParser.parse_args()
if options.opt == "clean":
init.clean()
return
init.initialize("../config/Build.xml")
init.invoke()
return
if __name__ == "__main__":
main()
------------------------------------------------------------------
<build>
<topdir>../../src/lteoff/domain/oam</topdir>
<module>pm</module>
<module>fm</module>
<module>sm</module>
<module>util</module>
</build>
MODULEDIR = $(patsubst %,$(TOPDIR)/%,$(MODULE))
INSTALL = /usr/bin/install
CC = g++
AR = $(CC)
ARFLAGS = -shared
RM = rm -rf
CXXFLAGS = -O3 -g -Wall
LDFLAGS = -lpthread
CPPFLAGS = -I./
LIBPATH = -L./
LINK = $(CC) -o ../../bin/$@ $^
ARCLIB = $(AR) $(ARFLAGS) -o ../../lib/lib$@.so
include $(patsubst %,%/Build.mk,$(MODULEDIR))
ifneq (,$(ARCHIVE))
ifneq (,$(PROGRAM))
DEPEND += $(ARCHIVE) $(PROGRAM)
else
DEPEND += $(ARCHIVE)
endif
else
ifneq (,$(PROGRAM))
DEPEND += $(PROGRAM)
endif
endif
APP_VAR = $($(PROGRAM)_SRC)
ARC_VAR = $($(ARCHIVE)_SRC)
APP_OBJS = $(patsubst %.cpp,%.o,$(APP_VAR))
ARC_OBJS = $(patsubst %.cpp,%.o,$(ARC_VAR))
%.o: %.cpp
@(echo compiling $@)
$(CC) -c $< -o $@ $(CPPFLAGS) $(CXXFLAGS)
all: $(DEPEND)
@(echo done)
$(ARCHIVE): $(ARC_OBJS)
@(echo creating archive $(LIB))
$(ARCLIB)
$(PROGRAM): $(APP_OBJS)
@(echo creating executing file $(BIN))
$(LINK)
.PHONY: clean_objs clean_libs clean_bins
clean_objs:
$(RM) $(MODULEDIR)/*.o
clean_libs:
$(RM) ../../lib/*
clean_bins:
$(RM) ../../bin/*
PROGRAM = fmApp
fmApp_SRC = $(TOPDIR)/fm/fmApp.cpp
ARCHIVE = fm
fm_SRC = $(TOPDIR)/fm/fm.cpp
- Inclusive Makefile
- Array#[inclusive range]
- Array#[inclusive range]=
- Array#slice![inclusive range]
- fc6.0 3d desktop inclusive functions;
- 4.4 To be inclusive or not to be…
- 4.4 To be inclusive or not to be 1
- Makefile
- Makefile
- makefile
- makefile
- makefile
- Makefile
- Makefile
- Makefile
- Makefile
- Makefile
- Makefile
- JavaScript的方法和技巧(三)
- 各种段的特权级检查
- CRC-16生成过程
- GCC二进制工具介绍
- Linux交叉编译环境构建
- Inclusive Makefile
- 原创 ···DELPHI 图片图形图像处理 PS置换滤镜效果,亮度/对比度,纹理贴图效果
- 动态链接库 Tips
- 编译Tips
- SMP MPP NUMA
- apache rewrite
- subpixel反走样
- linux引导程序剖析(一)
- linux引导程序剖析(二)