Waf编译基础
Waf介绍
随着项目代码工程化时,整体的复杂度是越来越复杂,构建项目所用的编译过程也越来越复杂。库与库之间是有十分复杂的依赖关系,人工去进行维护是十分困难的。这个时候就需要类似Make或者Waf工具来进行维护。Waf编译工具相对于Make编译工具更加轻量化。不用了解很多生涩的正则表达式,但是貌似在C/C++编程领域用的更多的时Make。
Waf(C++/C)
C/C++构建包括将源文件转换(编译)为目标文件,并在最后组装(链接)目标文件。 理论上,单一的编程语言应该足以编写任何应用程序,但情况通常更复杂:
- 源文件可能由其他语言的其他编译器创建
- 链接步骤中可能会输入附加文件(库、目标文件),并且应用程序可能分为动态或静态库
- 不同的平台可能需要不同的处理规则
为了隐藏实现细节和可移植性问题,每个目标(程序、库)都可以包装为单个任务生成器对象。
def options(opt):
opt.load('compiler_c') #扩展 compiler_c、compiler_cxx、compiler_fc 和 compiler_d 分别提供对 C、C++、Fortran 和 D 语言的支持
def configure(conf):
conf.load('compiler_c')
def build(bld):
bld.program(source='main.c', target='app', use='myshlib mystlib') #这声明了一个从 main.c 构建并使用其他两个库的程序
bld.stlib(source='a.c', target='mystlib', use='myobjects') #这声明了一个静态库,使用来自 myobjects 的对象
bld.shlib(source='b.c', target='myshlib') #这声明了一个动态库
bld.objects(source='c.c', target='myobjects')
Waf其他属性
def options(opt):
opt.load('compiler_c')
def configure(conf):
conf.load('compiler_c')
def build(bld):
bld.program(
source = 'main.c',
target = 'appname', #目标会自动转换为 target.exe 或 libtarget.so,具体取决于平台和类型
includes = ['.'],
defines = ['LINUX=1', 'BIDULE'],
lib = ['m'], #出于可移植性的原因,应提供不带文件扩展名的库名
libpath = ['/usr/lib'],
rpath = ['/opt/kde/lib']
vnum = '1.2.3',
idx = 123, #有时需要为目标文件扩展名设置计数器以避免目标文件名冲突
install_path = '${SOME_PATH}/bin', #默认情况下安装程序和共享库。要禁用安装,请设置无。
cflags = ['-O2', '-Wall'], #其他标志,应用于支持它们的源文件
)
库交互(use)
在各种库进行交互时,需要用use来处理库和库之间的依赖关系。
def build(bld):
bld.stlib(
source = 'test_staticlib.c',
target = 'mylib',
name = 'stlib1') #name 属性指向一个Task generator
bld.program(
source = 'main.c',
target = 'app',
includes = '.',
use = ['stlib1'])
值得注意的是use具有递归属性:
def build(bld):
bld.shlib(
source = 'a.c',
target = 'lib1')
bld.stlib(
source = 'b.c',
use = 'cshlib', #cshlib 标志将传播到库和程序。
target = 'lib2')
bld.shlib(
source = 'c.c',
target = 'lib3',
use = 'lib1 lib2')
bld.program( #由于共享库依赖 lib1 → lib2,程序应用程序应该同时链接 lib1 和 lib3,但不链接 lib2
source = 'main.c',
target = 'app',
use = 'lib3')
Includes
-use 关键字不仅可以指向具体的库,还可以指向仅有头文件的路径。
def build(bld):
bld(
includes = '. src',
export_includes = 'src', #include 属性是私有的,但 export_includes 将被其他task generator使用
name = 'com_includes')
bld.stlib(
source = 'a.c',
target = 'shlib1',
use = 'com_includes') #添加的路径是相对于其他task generator
bld.program(
source = 'main.c',
target = 'app',
use = 'shlib1', #export_includes 将传播到其他任务生成器
)
Waf C/C++ 使用变量和Task generator属性
- 图中defines中可以在其中定义全局宏。
Waf常见commod
all: builds all programs of all group
bin: builds all programs of bin group
build: excutes the build
check: builds all programs and run tests
check-all: "waf check --alltests"
clean: cleans the project
configure: configures the project
dist: makes a tarball for redistributing the sources
distcheck: checks if the project compiles
distclean: removes build folder and data
examples: builds all programs of examples group
copter: builds copter programs
plane: builds plane programs
rover: builds rover programs
tests: builds all programs of tests group
tools: builds all programs of tools group
uninstall: removes the targets installed