waf帮助构建及编译系统
waf 是一个帮助构建和编译系统的框架。
一、下载waf安装包
下载安装包: https://waf.io/
或者: $ curl -o waf-2.0.9.tar.bz2 https://waf.io/waf-2.0.9.tar.bz2
二、解压及安装
$ tar xjvf waf-2.0.9.tar.bz2
$ cd waf-2.0.9
$ ./waf-light
三、为了方便使用,将waf添加到PATH路径
$ cd waf-2.0.9
$ PATH=$PATH:$PWD
四、waf项目的目录大致结构如下
- $ tree
- |-- src
- | `-- wscript
- `-- wscript
主目录下有一个主的wscript脚本,要编译的子目录src目录下也有一个wscript脚本(每个wscript是python脚本)。
五、一个简单的例子
主目录的wscript内容:
- #! /usr/bin/env python
- # encoding: utf-8
- top = '.'
- out = 'build'
- def configure(ctx):
- print(' -> configureing the project in ' + ctx.path.abspath())
- def ping(ctx):
- print('-> ping from ' + ctx.path.abspath())
- ctx.recurse('src')
说明: 设置top目录为当前路径,输出路径为当前目录的build目录
src目录下的wscript内容:
- #! /usr/bin/env python
- # encoding: utf-8
- def ping(ctx):
- print('-> ping from ' + ctx.path.abspath())
(1) 首先执行
$ waf configure
Setting top to : /home/fcx/share/test/waf_learn/simple_test
Setting out to : /home/fcx/share/test/waf_learn/simple_test/build
-> configureing the project in /home/fcx/share/test/waf_learn/simple_test
'configure' finished successfully (0.036s)
于是在新建的build目录会生成一下配置文件
- |-- build
- | |-- c4che
- | | |-- build.config.py
- | | `-- _cache.py
- | `-- config.log
- |--.lock-wafbuild
- |-- src
- | `-- wscript
- `-- wscript
其中配置数据存储在build/c4che/目录下,命令行选项和环境变量存储在build.config.py中。用户的配置设置存储在_cache.py中。
(2)然后执行:
$ waf ping
-> ping from /home/fcx/share/test/waf_learn/simple_test
-> ping from /home/fcx/share/test/waf_learn/simple_test/src
'ping' finished successfully (0.002s)
如果执行 waf distclean 将会删除build的目录。distclean函数不需要在主wscript脚本中定义,如果你自己定义了该函数,则默认的distclean函数调用将会被你定义的函数覆盖。
(3)waf dist命令
默认执行该命令将会把项目代码打包为一个名为noname-1.0.tar.bz2的压缩包,如果要自己命名,则在主wscript脚本的top命令前添加如:
- #! /usr/bin/env python
- # encoding: utf-8
- APPNAME = 'waf_learn'
- VERSION = '1.0.0'
- top = '.'
- out = 'build'
- def configure(ctx):
- print(' -> configureing the project in ' + ctx.path.abspath())
- def ping(ctx):
- print('-> ping from ' + ctx.path.abspath())
- ctx.recurse('src')
这样生成的压缩包名为:waf_learn-1.0.0.tar.bz2
(4)waf --help
- $ waf --help
- waf [command] [options]
- Main commands (example: ./waf build -j4)
- build : executes the build
- clean : cleans the project
- configure: configures the project
- dist : makes a tarball for redistributing the sources
- distcheck: checks if the project compiles (tarball from 'dist')
- distclean: removes the build directory
- install : installs the targets on the system
- list : lists the targets to execute
- step : executes tasks in a step-by-step fashion, for debugging
- uninstall: removes the targets installed
- Options:
- --version show program's version number and exit
- -h, --help show this help message and exit
- -j JOBS, --jobs=JOBS amount of parallel jobs (2)
- -k, --keep keep running happily even if errors are found
- -v, --verbose verbosity level -v -vv or -vvv [default: 0]
- --zones=ZONES debugging zones (task_gen, deps, tasks, etc)
- configure options:
- -o OUT, --out=OUT build dir for the project
- -t TOP, --top=TOP src dir for the project
- --prefix=PREFIX installation prefix [default: '/usr/local/']
- --download try to download the tools if missing
- build and install options:
- -p, --progress -p: progress bar; -pp: ide output
- --targets=TARGETS task generators, e.g. "target1,target2"
- step options:
- --files=FILES files to process, by regexp, e.g. "*/main.c,*/test/main.o"
- install/uninstall options:
- --destdir=DESTDIR installation root [default: '']
- -f, --force force file installation
(5)自定义命令行参数(定义options函数)
- #! /usr/bin/env python
- # encoding: utf-8
- APPNAME = 'waf_learn'
- VERSION = '1.0.0'
- top = '.'
- out = 'build'
- def options(ctx):
- ctx.add_option('--arg1', action='store', default=False, help='set argument 1')
- ctx.add_option('--arg2', action='store', default='false', help='set argument 2')
- def configure(ctx):
- print(' -> configureing the project in ' + ctx.path.abspath())
- print('-- the value of arg1 is %s' % ctx.options.arg1)
- print('-- the value of arg2 is %s' % ctx.options.arg2)
- def ping(ctx):
- print('-> ping from ' + ctx.path.abspath())
- ctx.recurse('src')
然后执行 : waf configure --arg1=true --arg2='false'
有如下输出:
Setting top to : /home/fcx/share/test/waf_learn/simple_test
Setting out to : /home/fcx/share/test/waf_learn/simple_test/build
-> configureing the project in /home/fcx/share/test/waf_learn/simple_test
-- the value of arg1 is true
-- the value of arg2 is false
'configure' finished successfully (0.012s)
六、配置环境变量
- #! /usr/bin/env python
- # encoding: utf-8
- APPNAME = 'waf_learn'
- VERSION = '1.0.0'
- top = '.'
- out = 'build'
- def options(ctx):
- # 设置命令行参数,及默认值
- ctx.add_option('--arg1', action='store', default=False, help='set argument 1')
- ctx.add_option('--arg2', action='store', default='false', help='set argument 2')
- def configure(ctx):
- print(' -> configureing the project in ' + ctx.path.abspath())
- print('-- the value of arg1 is %s' % ctx.options.arg1)
- print('-- the value of arg2 is %s' % ctx.options.arg2)
- # 将命令行参数赋值给环境变量
- ctx.env.ENV_ARG1 = ctx.options.arg1
- # 查找应用并赋值给环境变量: 实现 CC=XXX/gcc
- ctx.find_program('gcc', var='CC')
- ctx.find_program('abc', mandatory=False) #测试不能找到的情况
- # 为一个环境变量添加选项列表
- ctx.env.CFLAGS = ['-g'] # 等价于 ctx.env['CFLAGS'] = ['-g']
- ctx.env.append_value('CFLAGS', ['-O2', '-Wall'])
- ctx.env.append_value('CXXFLAGS', ['-O3', '-g'])
- #环境变量的拷贝和保存和读取
- env_copy = ctx.env.derive() #浅拷贝
- node = ctx.path.make_node('save_env.txt') #创建文件节点
- env_copy.store(node.abspath()) #将环境变量拷贝到文件
- from waflib.ConfigSet import ConfigSet
- env2 = ConfigSet()
- env2.load(node.abspath()) #加载保存的环境变量
- print '------------------------------'
- print(node.read()) #打印出来
- print '------------------------------'
- def build(bld):
- print('++++ build %s' % bld.path.abspath())
- print('ENV_ARG1 = %s' % bld.env.ENV_ARG1)
- print('CC = %s' % bld.env.CC)
- bld.recurse('src')
执行:
$ waf configure build
Setting top to : /home/fcx/share/test/waf_learn/simple_test
Setting out to : /home/fcx/share/test/waf_learn/simple_test/build
-> configureing the project in /home/fcx/share/test/waf_learn/simple_test
-- the value of arg1 is False
-- the value of arg2 is false
Checking for program 'gcc' : /usr/bin/gcc
Checking for program 'abc' : not found
------------------------------
BINDIR = '/usr/local/bin'
CC = ['/usr/bin/gcc']
CFLAGS = ['-g', '-O2', '-Wall']
CXXFLAGS = ['-O3', '-g']
ENV_ARG1 = False
LIBDIR = '/usr/local/lib'
PREFIX = '/usr/local'
------------------------------
'configure' finished successfully (0.014s)
Waf: Entering directory `/home/fcx/share/test/waf_learn/simple_test/build'
++++ build /home/fcx/share/test/waf_learn/simple_test
ENV_ARG1 = False
CC = ['/usr/bin/gcc']
++++ build /home/fcx/share/test/waf_learn/simple_test/src
Waf: Leaving directory `/home/fcx/share/test/waf_learn/simple_test/build'
'build' finished successfully (0.018s)
七、BUILD 例子
主目录下的wscript脚本:
- #! /usr/bin/env python
- # encoding: utf-8
- APPNAME = 'waf_learn'
- VERSION = '1.0.0'
- top = '.'
- out = 'build'
- def options(ctx):
- # 设置命令行参数,及默认值
- ctx.add_option('--arg1', action='store', default=False, help='set argument 1')
- ctx.add_option('--arg2', action='store', default='false', help='set argument 2')
- def configure(ctx):
- print(' -> configureing the project in ' + ctx.path.abspath())
- print('-- the value of arg1 is %s' % ctx.options.arg1)
- print('-- the value of arg2 is %s' % ctx.options.arg2)
- # 将命令行参数赋值给环境变量
- ctx.env.ENV_ARG1 = ctx.options.arg1
- # 查找应用并赋值给环境变量: 实现 CC=XXX/gcc
- ctx.find_program('gcc', var='CC')
- ctx.find_program('abc', mandatory=False) #测试不能找到的情况
- # 为一个环境变量添加选项列表
- ctx.env.CFLAGS = ['-g'] # 等价于 ctx.env['CFLAGS'] = ['-g']
- ctx.env.append_value('CFLAGS', ['-O2', '-Wall'])
- ctx.env.append_value('CXXFLAGS', ['-O3', '-g'])
- #环境变量的拷贝和保存和读取
- env_copy = ctx.env.derive() #浅拷贝
- node = ctx.path.make_node('save_env.txt') #创建文件节点
- env_copy.store(node.abspath()) #将环境变量拷贝到文件
- from waflib.ConfigSet import ConfigSet
- env2 = ConfigSet()
- env2.load(node.abspath()) #加载保存的环境变量
- print '------------------------------'
- print(node.read()) #打印出来
- print '------------------------------'
- #定义在编译前执行的函数
- def build_before(ctx):
- print 'do something before building the project.'
- #定义在编译完成后执行的函数
- def build_after(ctx):
- print 'do something after building the project.'
- def build(bld):
- print('++++ build %s' % bld.path.abspath())
- print('ENV_ARG1 = %s' % bld.env.ENV_ARG1)
- print('CC = %s' % bld.env.CC)
- #动态创建任务: 将save_env.txt拷贝到build目录下另存为env.txt
- tg = bld(rule='cp ${SRC} ${TGT}', source='save_env.txt', target='env.txt')
- print 'type tg is %s' % type(tg)
- print 'post before: tg.tasks list is %s' % tg.tasks
- tg.post() #将任务入队
- print 'post after: tg.tasks list is %s' % tg.tasks
- bld.recurse('src')
- bld.add_pre_fun(build_before) #添加编译前需要执行的函数
- bld.add_post_fun(build_after) #添加编译后需要执行的函数
src目录下的wscript脚本:
- #! /usr/bin/env python
- # encoding: utf-8
- def configure(ctx):
- pass
- def build(bld):
- print('++++ build %s' % bld.path.abspath())
- bld(rule='touch ${TGT}', target='test.o')
- print('ENV_PREFIX = %s' % bld.env['PREFIX'])
- #只有执行waf install或uninstall 才执行
- #将build的文件安装到某路径下
- bld.install_files('/tmp/', 'test.o')
- bld.install_as('/tmp/abc.o', 'test.o')
- bld(rule='touch ${TGT}', target='test.so.1')
- #创建一个符号链接
- bld.symlink_as('/tmp/test.so', 'test.so.1')
执行: waf configure build install
Setting top to : /home/fcx/share/test/waf_learn/simple_test
Setting out to : /home/fcx/share/test/waf_learn/simple_test/build
-> configureing the project in /home/fcx/share/test/waf_learn/simple_test
-- the value of arg1 is False
-- the value of arg2 is false
Checking for program 'gcc' : /usr/bin/gcc
Checking for program 'abc' : not found
------------------------------
BINDIR = '/usr/local/bin'
CC = ['/usr/bin/gcc']
CFLAGS = ['-g', '-O2', '-Wall']
CXXFLAGS = ['-O3', '-g']
ENV_ARG1 = False
LIBDIR = '/usr/local/lib'
PREFIX = '/usr/local'
------------------------------
'configure' finished successfully (0.025s)
Waf: Entering directory `/home/fcx/share/test/waf_learn/simple_test/build'
++++ build /home/fcx/share/test/waf_learn/simple_test
ENV_ARG1 = False
CC = ['/usr/bin/gcc']
type tg is <class 'waflib.TaskGen.task_gen'>
post before: tg.tasks list is []
post after: tg.tasks list is [
{task 139906055718384: env.txt save_env.txt -> env.txt}]
++++ build /home/fcx/share/test/waf_learn/simple_test/src
ENV_PREFIX = /usr/local
do something before building the project.
Waf: Leaving directory `/home/fcx/share/test/waf_learn/simple_test/build'
do something after building the project.
'build' finished successfully (0.104s)
Waf: Entering directory `/home/fcx/share/test/waf_learn/simple_test/build'
++++ build /home/fcx/share/test/waf_learn/simple_test
ENV_ARG1 = False
CC = ['/usr/bin/gcc']
type tg is <class 'waflib.TaskGen.task_gen'>
post before: tg.tasks list is []
post after: tg.tasks list is [
{task 139906017850024: env.txt save_env.txt -> env.txt}]
++++ build /home/fcx/share/test/waf_learn/simple_test/src
ENV_PREFIX = /usr/local
do something before building the project.
+ install /tmp/test.o (from build/src/test.o)
+ install /tmp/abc.o (from build/src/test.o)
+ symlink /tmp/test.so (to test.so.1)
Waf: Leaving directory `/home/fcx/share/test/waf_learn/simple_test/build'
do something after building the project.
'install' finished successfully (0.016s)
在/tmp/目录下也会生成 test.o abc.o test.so文件。可以通过执行命令: waf list 查看生成的目标列表。
八、文件节点的概念
一个文件或目录称为一个节点
- def build(bld):
- #bld.path是当前wscript的路径
- print('++++ build %s' % bld.path.abspath())
- #打印当前目录下的内容
- print 'bld.path contents: %r' % bld.path.children
- #打印当前目录的父目录路径
- print 'bld.path parent: %s' % bld.path.parent.abspath()
- #在系统中搜索节点
- print bld.path.find_node('wscript')
- #在系统中搜索节点,如果没有则创建
- print bld.path.make_node('test.o')
- #在系统中搜索节点,找不到也不去创建
- print bld.path.search_node('test.oo')
- print 'ant_glob Test...'
- # ant_glob 用于递归列出文件和目录
- print bld.path.ant_glob('*.c') + bld.path.ant_glob('*.h') #打印当前目录下所有的.c和.h文件
- print bld.path.ant_glob(['test*', 'wscri*'])
- print bld.path.ant_glob(['test*', 'wscri*'], excl = ['*.bak']) #排除结尾是bak的文件
- print bld.path.parent.ant_glob('wscri*') #列出当前节点的父目录下的文件 这样写无效: bld.path.ant_glob('../wscri*')
- node = bld.path.find_node('wscript')
- print node.get_src() #打印wscript所在源文件目录
- print node.get_bld() #打印wscript所在目录的build目录
- nd = bld.path.make_node('test.txt')
- nd.write('hello world!') #往文件节点写数据
- print nd.read() #从文件节点读取数据
- print bld.path.listdir() #打印当前目录下的内容
- bld(rule='touch ${TGT}', target='test.o')
- print('ENV_PREFIX = %s' % bld.env['PREFIX'])
- #只有执行waf install或uninstall 才执行
- #将build的文件安装到某路径下
- bld.install_files('/tmp/', 'test.o')
- bld.install_as('/tmp/abc.o', 'test.o')
- bld(rule='touch ${TGT}', target='test.so.1')
- #创建一个符号链接
- bld.symlink_as('/tmp/test.so', 'test.so.1')
九、C或C++项目
- def options(opt):
- opt.load('compiler_c')
- def configure(conf):
- conf.load('compiler_c')
- def build(bld):
- #program: 目标是生成应用程序 app
- bld.program(source='main.c', target='app', use='myshlib mystlib')
- #stlib: 目标是生成静态库 mystlib.a
- bld.stlib(source='a.c', target='mystlib', use='myobjects')
- #shlib: 目标是生成动态库 myshlib.so
- bld.shlib(source='b.c', target='myshlib')
- #objects:目标是生成c.o
- bld.objects(source='c.c', target='myobjects')
Uselib variable | Attribute | Usage |
---|---|---|
LIB |
lib |
使用的共享库名 |
LIBPATH |
libpath |
使用的共享库路径 |
STLIB |
stlib |
使用的静态库名 |
STLIBPATH |
stlibpath |
使用的静态库路径 |
LINKFLAGS |
linkflags |
放在链接命令前面的链接参数 |
LDFLAGS |
ldflags |
放在链接命令末尾的链接参数 |
RPATH |
rpath |
在链接时硬编码为二进制文件的路径 |
CFLAGS |
cflags |
c文件的编译选项 |
CXXFLAGS |
cxxflags |
c++文件的编译选项 |
CPPFLAGS |
cppflags |
c++文件的编译选项放在编译命令的末尾 |
FCFLAGS |
fcflags |
list of Fortran compilation flags |
DFLAGS |
dflags |
list of compilation flags for d files |
INCLUDES |
includes |
头文件路径 |
CXXDEPS |
当发生变更时需要重新编译的依赖文件 |
|
CCDEPS |
同上for C |
|
LINKDEPS |
链接依赖 |
|
DEFINES |
defines |
list of defines in the form [‘key=value’, …] |
FRAMEWORK |
framework |
list of frameworks to use |
FRAMEWORKPATH |
frameworkpath |
list of framework paths to use |
ARCH |
arch |
list of architectures in the form [ppc, x86] |
十、例子总结
用waf编译了一个小工程:sendMessage, 代码请参考:
https://download.csdn.net/download/u010312436/10615769
waf帮助构建及编译系统相关推荐
- 学习笔记:waf帮助构建及编译系统
waf 是一个帮助构建和编译系统的框架. 一.下载waf安装包 下载安装包: https://waf.io/ 或者: $ curl -o waf-2.0.9.tar.bz2 https://w ...
- CCNET+MSBuild+SVN实时构建的优化总结
本文不是介绍如何使用CCNET+MSBuild+SVN构建自动编译系统,相关的内容可以从很多地方获取,可以再园子里搜一下. 随着我们的SVN库日益壮大,容量达到10G,几十G 甚至更大时,我们发现自动 ...
- Gartner 2018 年WAF魔力象限报告:云WAF持续增长,Bot管理与API安全拥有未来
Gartner 2018 年WAF魔力象限报告:云WAF持续增长,Bot管理与API安全拥有未来 来源 https://www.freebuf.com/articles/paper/184903.ht ...
- WAF是什么东西?!--- 1 waf的功能和用到的技术原理介绍
waf(Web应用防护系统) WAF很受欢迎,它是保护Web应用程序的复杂解决方案,涵盖了所有防护任务. Web应用程序开发人员可以在某些安全方面依赖WAF的原因. 尽管如此,WAF是可已被绕过的. ...
- Android编译系统的学习(三)
学习计划 了解编译系统的历史 了解各个历史的工具 make阶段编译过程 Soong阶段编译过程 ninja阶段编译过程 make阶段编译过程 安卓是一种基于Linux内核(不包含GNU组件)的自由及开 ...
- 主流waf非主流waf_通过黑客眼中的WAF
主流waf非主流waf Today we're going to talk about one of the modern security mechanism for web application ...
- Xash3d引擎简介以及构建
Xash3d 引擎 本文链接: https://blog.csdn.net/qq_30832915/article/details/115763393 1. 简介: GitHub仓库: https:/ ...
- Ardupilot源码编译(二)
最新参考:Ardupilot开发环境搭建(Ubuntu18.04,20190407) 目前Ardupilot的master版本需要用waf编译 waf 是一个帮助构建和编译系统的框架,采用pyth ...
- 入门 IT 行业,该具备哪些技能?
对于刚开始进入IT的新人来说,"必备技能"往往意味着一个长长的.标有重要度的学习列表,但是过长的列表通常会导致新人不知如何开始学习,压力倍增.本文尝试列举出最重要的几个技能,也期望 ...
最新文章
- shell脚本编程学习笔记(四)shell操作数据库
- Android中蓝牙的基本使用
- 基于ARM的linux嵌入式操作系统
- php 图片印章_PHP实现中文圆形印章特效_PHP
- linux新建用户,用户组,以及权限的分配(摘自博客园)
- Bootstrap 中: data-toggle 与 data-target 的作用
- 20171113_Python学习五周一次课
- html 下拉列表返回值,jquery 根据后台返回值来选中下拉框 option 值
- GDB调试时的参数设置
- JAVA实现文本翻译功能_java实现简单的英文文本单词翻译器功能示例
- MySQL区分大小写
- ArcGis空间分析学习:超市选址分析
- 网卡驱动收包代码分析之 page reuse
- Android微信分享之微信项目注册与申请
- 什么是北向接口和南向接口?
- 微信oauth2.0授权
- CS上线Linux--坑太多了
- 关于python数字的一种下划线奇怪写法
- 汇编语言-int指令
- win 7笔记本连接wifi不能输入密码解决办法(图文教程)