Skip to content

Commit 57dee2e

Browse files
committed
update: new post in ArduPilot.
1 parent 89e1647 commit 57dee2e

1 file changed

Lines changed: 119 additions & 0 deletions

File tree

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
---
2+
layout: post
3+
title: ArduPilot Waf 交叉编译第三方库
4+
category: "ArduPilot"
5+
date: 2025-09-06
6+
---
7+
8+
9+
环境 + 版本
10+
11+
* `WSL2 Ubuntu 20.04.6 LTS`
12+
* `Ardupilot v4.6.0-dev`
13+
* 交叉编译链 `arm-none-eabi-g++ (GNU Arm Embedded Toolchain 10-2020-q4-major) 10.2.1 20201103 (release)`
14+
15+
Target:在Ardupilot中搭载Json格式的决策树模型,且**使用第三方库来解析以Json格式字符串存储的模型**,并交叉编译为 Pixhawk 2.4.8 适用的固件
16+
17+
> 本文在编译过程中尝试调用第三方库解析json文件时,交叉编译链`arm-none-eabi-g++`并不支持文件读取等相关函数,因此通过宏定义的方式禁用了一部分第三方库的功能,并使用硬编码的方式在ardupilot中存储json格式模型
18+
19+
## Background
20+
21+
Waf 是使用 Python 脚本`wscript`定义构建流程。
22+
23+
运行 Waf 命令,`./waf configure build`,会调用 `wscript` 中的函数,其核心函数包括:
24+
25+
- `options(ctx)`:定义命令行选项。
26+
- `configure(ctx)`:检查编译环境、设置编译器、库路径等。
27+
- `build(ctx)`:定义编译目标和规则。
28+
29+
在Ardupilot中,当调用Waf进行固件`--board`编译时,实际调用的是对应硬件相关的交叉编译链,可以通过命令回显查看到具体的编译工具链
30+
31+
````bash
32+
$ ./waf configure --board fmuv3
33+
...
34+
Checking for 'g++' (C++ compiler) : /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-g++
35+
Checking for 'gcc' (C compiler) : /opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-gcc
36+
...
37+
````
38+
39+
因此,若需要编译链接第三方库时,应该将相关的库文件路径也给到工具链,或者将第三方库核心头文件导入Ardupilot项目文件夹中
40+
41+
> 当Ardupilot/waf编译SITL时,调用的是本地系统的编译工具链g++,ta能够自动根据环境变量,找到本地系统安装好的第三方库文件,因此和交叉编译时不同
42+
43+
## Method
44+
45+
### 修改Waf编译配置脚本
46+
47+
虽然Ardupilot/waf给了 `--libdir` 的参数指令,但**该指令在交叉编译时似乎无效**
48+
49+
````bash
50+
Linux boards configure options:
51+
--prefix=PREFIX installation prefix [default: '/usr/']
52+
--destdir=DESTDIR installation root [default: '']
53+
--bindir=BINDIR bindir
54+
--libdir=LIBDIR libdir
55+
````
56+
57+
**实际有效的方式**是在`./waf configure`后加上`CXXFLAGS=""`
58+
59+
````bash
60+
./waf configure --board=xxx CXXFLAGS="-I/usr/local/include"
61+
````
62+
63+
> 我这里因为只涉及到头文件的包含,并不需要指定共享库等等,但可以通过相同的方法将编译命令输入
64+
65+
还有更为麻烦的方式,由于 ardupilot/waf 在 configure 后**会生成对应固件的编译配置python脚本**,如使用
66+
67+
````bash
68+
./waf configure --board=fmuv3
69+
````
70+
71+
在项目根目录下会生成 `./build/c4che/fmuv3_cache.py`,该文件中写明在进行编译时,会传入的各种编译命令,如
72+
73+
> 所有固件的配置命令`./waf configure --board=XXX`执行后,均会生成对应的python编译配置脚本 `XXX_cache.py`,包括SITL
74+
75+
````python
76+
...
77+
CFLAGS = ['-ffunction-sections', ...]
78+
CFLAGS_MACBUNDLE = ['-fPIC']
79+
...
80+
COMPILER_CC = 'gcc'
81+
COMPILER_CXX = 'g++'
82+
...
83+
CXX = ['/opt/gcc-arm-none-eabi-10-2020-q4-major/bin/arm-none-eabi-g++']
84+
CXXFLAGS = ['-Werror=implicit-fallthrough', ...]
85+
CXXFLAGS_MACBUNDLE = ['-fPIC']
86+
...
87+
````
88+
89+
可以在这里在相应字段中加入自定义参数,如更换编译链,将 `CXX` 字段改为 `your_complier`
90+
91+
并且可以通过该文件的字段观察,确定在`./waf configure`后可以传入什么样的参数,比如这里,我们可以在终端命令中达到相同的效果
92+
93+
````
94+
./waf configure --board=fmuv3 CXX=your_complier
95+
````
96+
97+
### 修改交叉编译链的Include路径
98+
99+
通过`./waf configure`的相关回显可以确定编译链的选定,进一步找到编译链的include路径
100+
101+
````bash
102+
arm-none-eabi-g++ -v -E -x c++ /dev/null 2>&1 | grep "include"
103+
````
104+
105+
该命令是指定编译器使用C++语言,对空输入文件`/dev/null`进行预处理编译,并详细输出过程,这一过程中会显示编译器的搜索路径
106+
107+
之后的 `2>&1 | grep "include"`是为了获取到这一输出并从中寻找相关字段,最终确定编译链的include路径
108+
109+
在include路径中,复制第三方库即可
110+
111+
### 修改Ardupilot library
112+
113+
将第三方库文件调用到的相关核心函数文件,复制进入自定义Ardupilot中需要调用到的cpp同一文件夹下
114+
115+
并在文件中指定 `#include "thrid_party.h"`即可
116+
117+
## Reference
118+
119+
https://blog.csdn.net/lida2003/article/details/135167962

0 commit comments

Comments
 (0)