ament 代码规范
目标: 学习如何使用 ament_lint 及相关工具来识别和修复代码质量问题。
教程级别: 高级
预计耗时: 10 分钟
ament 系列 CLI 工具是一组专为 ROS 2 软件开发设计的 Python 工具。它们可以配合任何构建系统使用,其中 ament_cmake 子集专门简化基于 CMake 的开发流程。ament 还附带了一组 CLI 程序,帮助你编写符合 ROS 项目编码规范 的代码。善用这些工具可以大幅提升开发效率,确保你的 ROS 应用和核心代码符合编码规范。建议 ROS 开发者熟悉这些工具,并在提交 pull request 前运行一遍。
在常规的 ROS 2 安装过程中,你应该已经安装了 ament 相关包。
如果你需要安装 ROS 2,请参阅 安装指南。
Ament Lint CLI 工具
Section titled “Ament Lint CLI 工具”所有 ament lint 工具都采用相似的 CLI 调用方式:接收一个或多个目录/文件作为输入,分析这些文件后输出报告。它们都提供以下内置选项。如需获取某个 ament 工具最准确、最新的文档,请使用该工具的 --help 功能。
-h, --help- 显示帮助信息并退出。帮助信息通常是该工具最准确、最新的文档。--exclude [filename ...]- 要从分析中排除的文件名,支持通配符。--xunit-file XUNIT_FILE- 生成符合 xunit 标准的 XML 文件。这些文件最常被 IDE 和 CI 系统用来自动化地收集测试结果。
1 ament_copyright
Section titled “1 ament_copyright”ament_copyright CLI 可用于检查和更新 ROS 源代码中的版权声明,还能检查源代码中是否包含合适的许可证、版权年份和版权持有人信息。ament_copyright 以调用时所在的目录为根,递归遍历子目录并检查每个源文件。你只需切换到合适的根目录并运行该命令,就可以检查整个 ROS 包、工作空间、目录或单个源文件。此外,ament_copyright 还能自动为缺少版权和许可证信息的文件补上相应内容。
1.1 ament_copyright 参数
Section titled “1.1 ament_copyright 参数”默认情况下,ament_copyright 会遍历调用时所在的目录(包括子目录),报告所有缺少版权声明的文件。该程序接受一个可选参数,即要扫描的目录列表。例如,如果你只想扫描源文件和头文件中的版权声明,可以调用 ament_copyright ./src ./include。
1.2 ament_copyright 选项
Section titled “1.2 ament_copyright 选项”ament_copyright 支持以下选项:
--add-missing COPYRIGHT_NAME LICENSE- 使用传入的版权持有人和许可证,为缺少版权声明的文件添加版权声明和许可证信息。LICENSE参数指定要使用的许可证名称。可以通过调用ament_copyright --list-licenses获取所有可用许可证的完整列表。--add-copyright-year- 将当前年份添加到现有的版权声明中。--list-copyright-names- 列出已知的版权持有人名称。--list-licenses- 列出已知的许可证名称。--verbose- 显示所有文件,而不仅仅是存在错误或被修改的文件。
1.3 ament_copyright 示例
Section titled “1.3 ament_copyright 示例”要检查你的 ROS 包是否具有合适的版权和许可证文件,直接不带参数调用 ament_copyright 即可。加上 --verbose 选项会列出所有被检查的文件。
$ ament_copyright --verbosemy_package/src/new_file.cpp: could not find copyright noticemy_package/src/old_file.cpp: copyright=Open Source Robotics Foundation, Inc. (2023), license=apache2my_package/include/new_file.h: could not find copyright noticemy_package/include/old_file.h: copyright=Open Source Robotics Foundation, Inc. (2023), license=apache22 ament_cppcheck
Section titled “2 ament_cppcheck”ament_cppcheck 命令行工具用于对 C++ 源代码文件执行静态分析。静态分析 是指在不运行代码的情况下,自动审查源代码以发现可能在运行时引发问题的模式。ament_cppcheck 底层使用的 cppcheck 工具的某些版本可能较慢,因此在部分系统上 ament_cppcheck 可能会被禁用。如需启用,设置 AMENT_CPPCHECK_ALLOW_SLOW_VERSIONS 环境变量即可。
2.1 ament_cppcheck 参数
Section titled “2.1 ament_cppcheck 参数”默认情况下,ament_cppcheck 会遍历调用时所在的目录(包括子目录),报告源代码文件中所有潜在的问题。该程序接受一个可选参数,即要扫描的目录列表。例如,如果你只想扫描某个最近修改的文件,可以调用 ament_cppcheck ./src/my_cpp_file.cpp。
2.2 ament_cppcheck 选项
Section titled “2.2 ament_cppcheck 选项”ament_cppcheck 支持以下选项:
--libraries [LIBRARIES ...]- 除 C 和 C++ 标准库之外要加载的库配置。每个库以--library=<library_name>的形式传递给 cppcheck。--include_dirs [INCLUDE_DIRS ...]- 正在检查的 C/C++ 文件的包含目录。每个目录以-I <include_dir>的形式传递给 cppcheck(默认值:None)--cppcheck-version- 获取 cppcheck 版本,打印后退出。
2.3 ament_cppcheck 示例
Section titled “2.3 ament_cppcheck 示例”创建一个名为 example.cpp 的文件,内容为以下简单的 C++ 程序。
int main(){ char a[10]; a[10] = 0; return 0;}这个简单的程序越界访问了内存。在该文件所在目录中运行 ament_cppcheck 会产生以下结果:
$ ament_cppcheck[example.cpp:4]: (error: arrayIndexOutOfBounds) Array 'a[10]' accessed at index 10, which is out of bounds.3 ament_cpplint
Section titled “3 ament_cpplint”ament_cpplint 可用于根据 Google 代码风格指南 检查你的 C++ 代码,底层使用的是 cpplint。ament_cpplint 会扫描当前目录及子目录中的所有 C++ 头文件和源文件,对每个文件运行 CppLint 并输出结果。目前 ament_cpplint 无法自动修复发现的问题,如需自动修复格式问题,请参阅 ament_uncrustify。
3.1 ament_cpplint 参数
Section titled “3.1 ament_cpplint 参数”该程序接受一个可选参数,即要扫描的目录列表。例如,如果你只想扫描源文件和头文件,可以调用 ament_cpplint ./src ./include。
3.2 ament_cpplint 选项
Section titled “3.2 ament_cpplint 选项”--filters FILTER,FILTER,...- 以逗号分隔的类别过滤器列表。--linelength N- 最大行长度(默认值:100)。--root ROOT- cpplint 的 —root 选项。
3.3 ament_cpplint 示例
Section titled “3.3 ament_cpplint 示例”下面创建一个名为 example.cpp 的简单 C++ 程序,并故意加入几行违反编码规范的代码:
int main(){ int a = 10; int b = 10; int c = 0;/*<trailing whitespace>*/ if( a == b) {/*<tab>*/ c=a;}/*<trailing whitespace>*/ return 0;}对该文件运行 ament_cpplint 将报告以下错误:
example.cpp:0: No copyright message found. You should have a line: "Copyright [year] <Copyright Owner>" [legal/copyright] [5]example.cpp:6: Line ends in whitespace. Consider deleting these extra spaces. [whitespace/end_of_line] [4]example.cpp:6: Tab found; better to use spaces [whitespace/tab] [1]example.cpp:6: Line ends in whitespace. Consider deleting these extra spaces. [whitespace/end_of_line] [4]example.cpp:6: Missing spaces around = [whitespace/operators] [4]4 ament_flake8
Section titled “4 ament_flake8”Flake8 是一个用于 Python 代码检查和风格强制的工具。ament_flake8 命令行工具借助 Flake8 快速对 Python 源代码文件执行 lint 检查,帮助你发现 ROS Python 程序中的小错误和风格问题,例如行尾空格、代码行过长、函数参数间距不当等。请注意,flake8 和 ament_flake8 无法自动重新格式化代码来修复这些问题。
4.1 ament_flake8 参数
Section titled “4.1 ament_flake8 参数”该程序接受一个可选参数,即要扫描的目录列表。例如,如果你只想扫描工作空间中的某个包,可以直接在该包的工作目录中调用 ament_flake8,或者将目录路径传递给它。
4.2 ament_flake8 选项
Section titled “4.2 ament_flake8 选项”ament_flake8 支持以下选项:
--config path- 指定使用的配置文件。默认配置文件可以在安装目录的 site-packages 目录中找到。不建议更改默认设置。--linelength N- 手动设置最大行长度。
4.3 ament_flake8 示例
Section titled “4.3 ament_flake8 示例”创建一个名为 example.py 的文件,内容为以下简单的 Python 程序。
def uglyPythonFunction(a,b, c): if a != b: print("A does not match b") thisIsAVariableNameThatIsWayTooLongLongLong = 2 extra_long =(thisIsAVariableNameThatIsWayTooLongLongLong*thisIsAVariableNameThatIsWayTooLongLongLong ) return(c)对该文件运行 ament_flake8 将报告以下错误。
example.py:1:25: E231 missing whitespace after ','def uglyPythonFunction(a,b, c):
example.py:5:5: F841 local variable 'extra_long' is assigned to but never used extra_long =(thisIsAVariableNameThatIsWayTooLongLongLong*thisIsAVariableNameThatIsWayTooLongLongLong ) ^
example.py:5:17: E225 missing whitespace around operator extra_long =(thisIsAVariableNameThatIsWayTooLongLongLong*thisIsAVariableNameThatIsWayTooLongLongLong ) ^
example.py:5:100: E501 line too long (106 > 99 characters) extra_long =(thisIsAVariableNameThatIsWayTooLongLongLong*thisIsAVariableNameThatIsWayTooLongLongLong ) ^
example.py:5:105: E202 whitespace before ')' extra_long =(thisIsAVariableNameThatIsWayTooLongLongLong*thisIsAVariableNameThatIsWayTooLongLongLong ) ^
1 E202 whitespace before ')'1 E225 missing whitespace around operator1 E231 missing whitespace after ','1 E501 line too long (106 > 99 characters)1 F841 local variable 'extra_long' is assigned to but never used
1 files checked5 errors
'E'-type errors: 4'F'-type errors: 1
Checked files:
* example.py5 ament_uncrustify
Section titled “5 ament_uncrustify”Uncrustify 是一个 C++ lint 工具,类似于 ament_cpplint,但它的优势在于可以自动修复发现的问题!它可以帮助你发现和修复 C++ ROS 程序中的小错误和风格问题,例如行尾空格、代码行过长、函数参数间距不当等。
5.1 ament_uncrustify 参数
Section titled “5.1 ament_uncrustify 参数”该程序接受一个可选参数,即要扫描的目录列表。例如,如果你只想扫描工作空间中的某个包,可以直接在该包的工作目录中调用 ament_uncrustify,或者将目录路径传递给它。
5.2 ament_uncrustify 选项
Section titled “5.2 ament_uncrustify 选项”ament_uncrustify 支持以下选项:
-c CFG- 如果你想使用自己的设置,可以指定 Uncrustify 应使用的配置文件。建议使用默认配置。--linelength N- 最大行长度。--language- 取值为C、C++、CPP之一,以-l <language>的形式传递给 uncrustify,强制指定语言而不是根据文件扩展名自动选择。--reformat- 就地重新格式化文件,即修复遇到的格式错误。建议在运行ament_uncrustify时使用此选项,可以为你节省大量时间!
5.3 ament_uncrustify 示例
Section titled “5.3 ament_uncrustify 示例”回到之前那个名为 example.cpp 的简单 C++ 程序。
int main(){ int a = 10; int b = 10; int c = 0;<trailing whitespace> if( a == b)<trailing whitespace>{ <tab> c=a;}<trailing whitespace> return 0; }对该文件运行 ament_uncrustify example.cpp 会产生以下输出。
--- example.cpp+++ example.cpp.uncrustify@@ -1,9 +1,10 @@- int main()- {- int a = 10;- int b = 10;- int c = 0;<trailing whitespace>- if( a == b)<trailing whitespace>{- <tab> c=a;}<trailing whitespace>- return 0;- }+int main()+{+ int a = 10;+ int b = 10;+ int c = 0;+ if (a == b) {+ c = a;+ }+ return 0;+}1 files with code style divergence要将这些更改应用到文件中,我们可以使用 --reformat 选项运行 ament_uncrustify。使用此选项时,uncrustify 会就地应用所有更改,能帮你节省大量时间,尤其是在处理大型代码库时。
6 其他值得关注的 Ament 工具
Section titled “6 其他值得关注的 Ament 工具”ROS Desktop Full 附带了一些值得关注的 ament 开发工具,下面列出其中几个:
ament_lint_cmake- 根据 CMake 风格规范检查 CMake 文件。ament_xmllint- 使用 xmllint 检查 XML 标记,例如 XML launch 文件。ament_pep257- 根据 PEP 257 风格规范检查 Python 文档字符串。
ament 具有高度可扩展性,鼓励 ROS 用户构建和使用能够提升自身效率的 ament 工具。你可以使用 apt search 或在 ROS Index 上搜索 ament 来查找社区贡献的其他 ament lint 工具。