ardupilot waf 学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lixiaoweimashixiao/article/details/83544096

目录

摘要



本节主要学习ardupilot的waf命令。Ardupilot正逐渐从make的构建系统转向waf。下面的说明应该足以让您建立Ardupilot,但您也可以阅读更多关于构建系统在WAF图书。WAF应该总是从Ardupilot的根目录调用。不同于基于make的构建,WAF有一个配置步骤来选择要使用的板(默认为SITL)。



1.简介



1.关于构建系统



随着软件越来越复杂,功能越来越丰富,软件的创建过程也越来越复杂。从软件项目的基本需求来看,复杂性是自然产生的:

  1. 可用的软件(应用程序)是机器可读的,但通常不是人类可读的。
  2. 因此,人类可读的输入数据称为源代码被编译器或存档器转换为可再分配的软件。
  3. 源代码通常被分解为相互依赖的单元,如独立管理的文件、模块、类和函数
  4. 这些单元是版本控制的,它们的演化是通过版本控制软件控制的。
  5. 附加过程从源代码生成附加数据,例如测试和静态分析结果。
  6. 源代码处理耗时且容易出错,因此在附加软件的帮助下自动化。

虽然编译器有时试图提供完整的构建自动化,但它们通常局限于非常特定的特征。例如,Java编译器(Javac)可以同时构建一个完整的源代码树,但另一个编译器则需要生成存档文件(JAR)。文本编辑器和集成开发环境(IDE,如Xcode或Eclipse)可以提供构建自动化特性,但是它们的用户界面最擅长编辑软件,而不是运行构建Git等版本控制系统最适合于管理最终用户文件,**但是通常不适合调用编译器和运行脚本。**虽然编排解决方案(Jenkins,Teamcity)有时被理解为构建系统,但它们通常无法自己构建软件:它们需要构建脚本,并构建在其构建代理(Maven,Make等)上执行的软件。


因此,我们认为构建软件是一种独特的软件开发活动,需要一套独特的工具。术语“构建系统”通常用来表示这样的软件,我们认为应该区分两个定义:
A.它是一种帮助软件项目中的过程自动化的软件,并且它特别旨在处理源代码。
B.这是总体的工具集所需的过程在一个特定的软件项目工作:编译器,编译脚本、业务流程软件,版本控制系统,等等。
WAF匹配该文档其余部分中使用的第一个定义。



2.WAF结构



构建系统通常绑定到它们所属的特定框架。例如,VisualStudio项目通常需要MSBug和angul.js项目通常需要NPM。这样的解决方案通常集中在非常特定的特性上,并且在处理其他语言或不同项目时通常受到限制。例如,Ant(Ant是Java的生成工具,是Apache的核心项目; Ant类似于Unix中的Make工具)更适合于管理Java项目,但比构建简单的C项目更不方便。由于编程语言和解决方案不断演进,因此不可能为每样东西都创建理想的构建系统,因此在框架专门化和通用性之间存在权衡。

建立系统旨在解决的问题还有一个共同的子集:

  • 将编译器和脚本作为不同的进程运行
  • 仅在必要时通过记录“什么已经改变”来运行进程
  • 出于效率原因并行运行进程
  • 促进软件测试的执行,例如配置测试
  • 为典型编译器和工具配置提供支持

WAF实现了上述功能,并提供了一个框架,以扩展其功能,必要时。与其他框架相比,它的主要区别在于它的设计:

  1. WAF只需要Python,不依赖于附加的软件或库。
  2. WAF没有定义一种新的语言,它完全是用可重用的Python模块编写的。
  3. WAF不依赖代码生成器(MaFrimes)来实现高效和可扩展的构建。
  4. WAF目标定义为将目标定义与运行命令分离的对象。


3.本书的目的



本书主要针对Waf构建系统的新用户和高级用户,其目的是通过实例展示Waf构建系统的使用,描述Waf扩展系统,并提供Waf内部结构的概述。

我们也知道构建系统正在被重新发明,所以我们希望构建系统编写人员能够从这个文档中得到启发,以重用现有的模式和技术。

这些章节按照难度排序,从Waf和Python的基本用法开始,逐步深入到最复杂的主题。因此建议按顺序阅读章节。在开始阅读之前,可以从WAF分布中查看示例开始。



2.下载和初始化



2.1.获取waf文件



2.1.1.如何下载waf



发布文件可以从主站点从镜像下载,而源可以从GitLab获得。下载和大多数项目提交与项目公钥一起签署:

WAF可执行文件包含一个嵌入的签名,可以通过脚本来验证:

$ curl -o waf https://waf.io/waf-2.0.12
$ python verify-sig.py waf

源分发为其存档提供签名文件:

$ curl -o waf-2.0.12.tar.bz2 https://waf.io/waf-2.0.12.tar.bz2
$ curl -o waf-2.0.12.tar.bz2.asc https://waf.io/waf-2.0.12.tar.bz2.asc
$ gpg --verify waf-2.0.12.tar.bz2.asc

ps:这里建议直接在ubuntu使用命令下载
大多数项目提交都用相同的公钥签名:

$ git clone https://gitlab.com/ita1024/waf.git
$ cd waf/
$ git show --show-signature
commit b73ccba03cd5f34b40a36e1d60b6a082a04cd563
gpg: Signature made sam. 16 jul. 2017 17:31:19 CEST
gpg:                using RSA key 0x49B4C67C05277AAA
...

在这里插入图片描述

在这里插入图片描述



2.1.2.如何运行waf



可执行文件可以直接通过Python解释器运行,如CPython 2.5到3.5、pypy/jython >=2.5。它将自己的库压缩为文件中的二进制流。在执行时,该库被解压缩为文件目录中的隐藏文件夹(当删除时重新创建)。该方案允许不同的WAF版本从相同的文件夹和不同的Python解释器版本下执行:

$ python waf --help
$ ls -ld .waf*
.waf-2.0.12-2c924e3f453eb715218b9cc852291170

不需要安装,但是Python解释器必须具有bzip2解压缩器的特性;如果缺少这个模块,那么可能需要从源代码构建Waf(参见下一节)。包含WAF文件的文件夹也必须是可写的,以便WAF文件可以解压它的库。

如果不满足上述条件,另一种方法是将环境变量WAFDIR指向包含名为waflib的目录的文件夹。虽然这个waflib文件夹可以作为项目源文件的一部分提供,但是文件不能同时在Python 2和Python 3中运行,因此通常不鼓励这样做。

下面的图表描述了如何发现WAFLIB目录:
在这里插入图片描述


2.1.3.权限和别名


由于WAF文件是Python脚本,所以通常通过调用Python来执行它:

python waf

用这个命令编译飞控
waf 直接编译

在类UNIX系统中,设置可执行权限通常更方便,并且避免每次调用Python:

$ chmod 755 waf
$ ./waf --version
waf 2.0.12 (54dc13ba5f51bfe2ae277451ec5ac1d0a91c7aaf)

如果命令行解释器支持别名,建议设置一个而不是重新键入命令:

$ alias waf=$PWD/waf
$ waf --version
waf 2.0.12 (54dc13ba5f51bfe2ae277451ec5ac1d0a91c7aaf)

为了方便,在Windows系统上,提供了一个waf.bat文件来检测Python应用程序的存在。它假定它驻留在与WAF文件相同的文件夹中。




2.2定制与再分配



2.2.1如何构建WAF可执行文件



构建WAF需要一个Python解释器,版本号在2.6~3.5范围内。然后对源代码进行处理以支持Python 2.5。

$ curl -o waf-2.0.12.tar.bz2 https://waf.io/waf-2.0.12.tar.bz2
$ tar xjvf waf-2.0.12.tar.bz2
$ cd waf-2.0.12
$ ./waf-light
Configuring the project
Setting top to                           : /home/user/waf
Setting out to                           : /home/user/waf/build
Checking for program 'python'            : /usr/bin/python
Waf: Entering directory `/waf-2.0.12/build'
[1/1] Creating waf
Waf: Leaving directory `/waf-2.0.12/build'
'build' finished successfully (0.726s)

对于旧的Python解释器,可以使用GZIP压缩而不是BZIP2创建WAF文件

$ python waf-light --zip-type=gz

后面省略翻译。。。。。



2.2.2.如何提供自定义初始化器



提供初始化的扩展也可用于在常规执行之前执行自定义函数。假设当前目录中存在一个名为aba.Py的文件:

def foo():
        from waflib.Context import WAFVERSION
        print("This is Waf %s" % WAFVERSION)

下面将创建一个自定义WAF文件,该文件将在调用WAF库之前导入并执行函数foo

$ python waf-light --make-waf --tools=msvs,$PWD/aba.py
   --prelude=$'\tfrom waflib.extras import aba\n\taba.foo()'
$ ./waf --help
This is Waf 2.0.12
[...]

还可以添加返回语句;请查阅waf-light的内容以了解更多关于这个的内容,或者考虑构建系统工具包中的示例,这些示例说明了如何创建从Waf派生的构建系统。


2.2.3.许可与再分配



包含在waf文件(waf-light和waflib下的所有文件)中的文件是在BSD许可下发布的,BSD许可在下面叙述:

重新分配和使用源和二进制形式,必须满足下面条件,就可以进行修改

满足:

1.源代码的重新分发必须保留上述版权注意,这一条件清单和以下免责声明。
2.以二进制形式重新分发必须复制上述版权请注意,此条件清单及以下免责声明
分发的文件和/或其他材料。
3.作者的姓名不得用于背书或推销产品。未经事先书面许可而从该软件派生。
后面省略。。。。。。。



3.项目和命令



因为Waf文件是用于构建项目的通用实用程序,所以项目特定的细节最好保存在项目源代码所在的文件中,并进行版本控制。这些文件是用Python编程语言编写的模块,名为WScript。虽然它们可以包含任何Python代码,但WAF可以使用它们中定义的特定函数和类。下一部分将探索一个特别有用的概念,称为函数命令。



3.1.1命令行概述



Waf通常运行在称为终端或shell的命令行解释器中;有三种主要方法将数据传递给Waf进程以告诉它执行某些操作:

$ CFLAGS=-O3 1 waf distclean configure 2 -j1 --help 3

1.CFLAGS参数是一个环境变量,它用于以不受约束的方式提供任意数据的进程。
2.WAF被指示运行这两个命令,称为DistClean和configure;并按照这个特定的顺序进行配置。命令在WAF文件之后传递,并且不包含NOR字符或字符。
3. j1和–help元素是命令行选项;它们是可选的,它们在参数列表中的位置或顺序并不重要。



3.1.2 waf 命令映射Python函数



Waf命令假定在相应的命令功能函数,这个函数是在项目的文件夹wscript文件中定义了相应的命令函数。它们以单个上下文参数作为输入,不必返回任何特定值,如以下示例:

#! /usr/bin/env python
# encoding: utf-8

def hello(ctx):
    print('hello world')

调用命令指示WAF调用函数Hello:

$ waf hello
 hello world
'hello' finished successfully (0.001s)

上下文对象允许跨脚本的数据共享,其使用将在下面的章节中进行描述。


3.1.3 waf 命令可以链接


如前所述,命令是按照命令行定义的顺序执行的。因此,WScript文件可以在同一个WScript文件中提供任意数量的命令:

def ping(ctx):
    print(' ping! %d' % id(ctx))

def pong(ctx):
    print(' pong! %d' % id(ctx))

这样的命令可以在命令行上重复调用不止一次:

$ waf ping pong ping ping
 ping! 140704847272272
'ping' finished successfully (0.001s)
 pong! 140704847271376
'pong' finished successfully (0.001s)
 ping! 140704847272336
'ping' finished successfully (0.001s)
 ping! 140704847272528
'ping' finished successfully (0.001s)

当发生错误时,执行被中断,并且不再调用其他命令。
注意:命令函数在调用时传递一个新的上下文对象;该对象的类是命令特定的:Configure Context for configure、Build Context for build、OptionContext for.、以及Context for任何其他命令。

3.1.4. 基本的项目结构

虽然waf项目必须包含顶级wscript文件,但是内容可以被分割成若干个子项目文件。现在我们将在一个小项目上说明这个概念:

$ tree
|-- src
|   `-- wscript
`-- wscript

顶级wscript中的命令通过调用名为recurse(递归),来实现调用子项目wscript文件中相同的命令:

def ping(ctx):
        print('→ ping from ' + ctx.path.abspath())
        ctx.recurse('src')

下面是SRC/wscript的内容

def ping(ctx):
        print('→ ping from ' + ctx.path.abspath())

执行后,结果将是:

$ cd /tmp/execution_recurse

$ waf ping
→ ping from /tmp/execution_recurse
→ ping from /tmp/execution_recurse/src
'ping' finished successfully (0.002s)

$ cd src

$ waf ping
→ ping from /tmp/execution_recurse/src
'ping' finished successfully (0.001s)

注意:该递归方法,并且属性路径可在所有waf上下文类上可用,以便所有waf命令都可以使用它们。

猜你喜欢

转载自blog.csdn.net/lixiaoweimashixiao/article/details/83544096