- 开发工具
- Lint
- 静态分析
- 硬件开发
【免费下载链接】verible
Verible is a suite of SystemVerilog developer tools, including a parser, style-linter, formatter and language server
Verible 是 Chips Alliance 维护的 SystemVerilog 开发者工具集(解析器、风格检查器、格式化工具与语言服务器),其 doc/development.md 是面向贡献者与二次开发者的开发资源文档,汇总了源码搜索导航、clangd 编译数据库构建、clang-tidy 缓存检查与before-submit.sh提交前检查流水线等核心开发辅助手段。本文以该文档为主线,结合仓库中.github/bin/下的实际脚本实现与 MODULE.bazel、shell.nix 等构建配置,完整讲解在 Verible 中建立高效的本地开发工作流的每一步,读完后你可以独立搭建导航环境、理解代码组织约定,并在提交 PR 前复现 CI 的全部本地检查。
一、搜索与导航 Verible 源码
doc/development.md 的开篇建议:熟悉这个代码库需要时间,善用搜索索引。文档给出了三条导航路径:
- 在线搜索镜像:项目维护了一个按代码搜索索引过的源码镜像(cs.opensource.google 上的 verible 镜像),适合全局关键字检索与历史浏览;
- 自建 Kythe 索引:如果需要离线跨引用导航(查找引用、跳转定义),可以按照 doc/indexing.md 的说明,用 Kythe 的 C++ 提取器对 Bazel 构建目标做编译抽取、生成 GraphStore 并启动 Web UI。仓库根目录还提供了 kythe-browse.sh,它针对SystemVerilog 源码(而非 C++ 源码)执行同样的流程:先构建
//verible/verilog/tools/kythe:all,再用verible-verilog-kythe-extractor抽取 Kythe facts,经entrystream、write_entries、write_tables后由http_server在localhost:8080提供浏览(端口可用环境变量BROWSE_PORT覆盖)。 - 编辑器导航(推荐日常使用):让编辑器使用
clangd语言服务器,并先生成它所需的编译数据库:
.github/bin/make-compilation-db.sh编译数据库是如何生成的
阅读 make-compilation-db.sh 可以看清这条命令背后的完整流程:
- 构建所需的 Bazel 与 bant 工具链可通过环境变量
BAZEL和get-bant-path.sh定位,bant 作为开发依赖声明在 MODULE.bazel 中(bazel_dep(name = "bant", version = "0.3.6", dev_dependency = True)); - 脚本会先对 MODULE.bazel 声明的外部依赖逐个执行
bazel fetch(abseil-cpp、nlohmann_json、protobuf、re2、rules_flex、zlib、googletest),确保外部源码全部落地; - 接着用 bant 列出并构建所有
genrule与cc_proto_library目标(list-targets -g "genrule|cc_proto_library" -m -c3 ...),使生成文件在依赖分析中可见; - 由于 bant 尚不能区分逐文件的编译参数,脚本选择不生成
compile_commands.json,而是用bant compile-flags -o compile_flags.txt生成更简单的统一编译参数文件,这对各类工具都更易消化; - 最后补一个已知缺口:bant 尚看不到 toolchain 内部的 flex 依赖,脚本会扫描
bazel-out/../../../external/*flex*/src/FlexLexer.h并把对应-I目录追加进compile_flags.txt。
因此该脚本的产物是项目根目录下的compile_flags.txt,供 clangd 及后文的 clang-tidy 缓存脚本共同消费。
二、保持代码整洁的自动化工具
带缓存的 clang-tidy 检查
文档指出:有了编译数据库后,可以运行 clang-tidy 检查器:
.github/bin/run-clang-tidy-cached.cc并特别提醒:首次运行会花较长时间,但结果会被缓存。
从 run-clang-tidy-cached.cc 的实现看,这是一个自包含的 C++17 程序——文件开头的#if 0段让它可以直接当 shell 脚本执行,首次运行时用c++ -std=c++17就地编译自己再运行。其缓存与增量机制值得拆解:
- 内容寻址缓存:每个源文件的 clang-tidy 输出按
hash(文件内容)命名存入~/.cache/clang-tidy/下的项目缓存目录(Verible 的缓存前缀配置为verible_,见 run-clang-tidy-cached.cc#L121-L130 中的kConfig)。文件内容不变则直接复用缓存; - 头文件变更联动:若开启了
revisit_if_any_include_changes(默认开启),源文件的指纹会与其#include头文件的内容哈希异或——foo.cc本身没改,但bar.h改了,foo.cc仍会被重新检查,从而发现“依赖头文件行为”的隐患; - 构建环境变更重查:
toplevel_build_file配置为MODULE.bazel,当MODULE.bazel或编译数据库的时间戳比某条已缓存的告警更新时,会重新审视该文件(依赖变化可能改变 tidy 结论); - 项目定制:Verible 的
kConfig排除了.git/、.github/、vscode/目录以及tree-operations_test、symbol-table_test这两个处理非常慢的测试文件,并标记is_bazel_project = true,使报告中的路径能规范化回项目根目录; - 并行与配置:
CLANG_TIDY_JOBS控制并行任务数(默认取硬件并发度);环境变量CLANG_TIDY、CLANG_TIDY_CONFIG、CACHE_DIR可分别覆盖 tidy 二进制、配置文件与缓存目录。tidy 的配置本身来自仓库根目录的 .clang-tidy; - 输出:明细报告与按 check 汇总的计数报告分别写入缓存目录的
verible_clang-tidy.out与verible_clang-tidy.summary符号链接,无告警时直接打印 “No clang-tidy complaints.”。
文件头部注释中还给出了典型的高级用法示例——只跑某个检查并自动修复:
run-clang-tidy-cached.cc --checks="-*,modernize-use-override" --fix脚本运行前提是项目根目录存在compile_commands.json或compile_flags.txt(即先跑过 make-compilation-db.sh),否则它会在 run-clang-tidy-cached.cc#L595-L604 处直接报错退出。
提交前一站式检查:before-submit.sh
文档建议:在创建 Pull Request 之前运行下面这个脚本,看看有没有遗漏(CI 也能兜底,但本地先跑一遍体验更好):
.github/bin/before-submit.sh并说明它内部也会跑 clang-tidy,因此首次运行同样较慢。通读 before-submit.sh 可以看到它实际串联了7 个阶段,且支持--skip-clang-tidy、--skip-cpp-std两个开关跳过耗时步骤:
- 构建 bant(通过
get-bant-path.sh),它是后续编译数据库与构建清理的基础; - 刷新编译数据库:直接调用 make-compilation-db.sh,这一步同时保证外部依赖全部拉取,为构建清理做好准备(before-submit.sh#L41-L49);
- 运行 build cleaner:
bant dwyu,清理无用依赖与代码结构问题; - 全量测试:
bazel test -c opt --test_summary=terse ...; - 多语言标准回归:分别用
-std=c++20与-std=c++23重跑全部测试,保证代码不只在新标准下能编译(before-submit.sh#L58-L65); - clang-tidy(带缓存),然后
- 格式化 + 潜在问题检查:依次调用 run-format.sh 与 check-potential-problems.sh。
两个子脚本各自也值得展开:
run-format.sh:对仓库内所有*.h/*.cc(排除third_party/、external_libs/、.github/)执行clang-format -i。格式基准是 CONTRIBUTING.md 声明的 Google C++ 风格,仓库的 .clang-format 在 Google 基础上做了唯一一处定制——指针/引用一律右对齐(PointerAlignment: Right)。若装有buildifier,还会顺手格式化 MODULE.bazel 与所有BUILD、*.bzl文件。
check-potential-problems.sh是一组“防止误引入坏习惯”的静态 grep 检查,规则包括(见 check-potential-problems.sh#L22-L114):
- 统一使用
std::string_view,禁止absl::string_view及其 BUILD 依赖; status_macros.h只能在.cc编译单元中使用,不得出现在头文件里(避免污染全局命名空间);verible/common下禁止出现verilog::命名空间——这是保证 common 层语言无关的关键约束;#include必须写完全限定路径(如#include "verible/common/..."),不允许#include "foo.h"这类相对写法;- C++ 文件命名用连字符分隔、下划线仅用于
_test后缀(例如foo-bar_test.cc),测试文件必须以_test结尾; - MODULE.bazel 中禁止引入
rules_python(会破坏平台无关的静态构建策略); - 禁止使用
std::regex(慢且依赖异常),改用 RE2; - 禁止使用
.bazelversion,要求仓库兼容当前所有活跃的 Bazel 版本。
风格与测试的配套约定
结合 CONTRIBUTING.md,本地开发还应注意:提交前对改动文件执行clang-format --style=file -i <files>;每项改动应附带防回归的测试(以单元测试为主),项目也欢迎纯测试用例的贡献。检查覆盖率可运行:
MODE=coverage .github/bin/build-and-test.sh .github/bin/generate-coverage-html.sh报告位于coverage-html/index.html。
三、阅读代码的经验提示
doc/development.md 的 “Tips” 部分给出了两条长期有效的建议,文档中保留了原文表述:
- 读测试代码:大多数
.h和.cc文件都配有_test.cc单元测试,而且测试“永远不会过时”——因为 CI 保证它们始终通过。从测试读起,是理解一个模块行为最可靠的入口; - 找示例:挖掘 git 历史,沿着 blame/annotation 看特定代码行何时被修改;寻找相关的已关闭 issue,以及解决它们的提交。
四、代码组织:每个目录的 README 是入口
文档 “Code Organization” 一节指出:源码树的每个目录都带有一个简短的 README.md 描述其内容,并给出三大顶层划分:
- verible/common:所有语言无关的库与工具。按 verible/common/README.md 的目录摘要,包含
util(通用算法与数据结构)、strings(纯字符串操作)、lexer(产生 token 流的词法器接口与适配器)、parser(从 token 构建语法树的解析器接口与适配器)、text(源码结构表示:token、行、树等)、analysis(文本结构上的分析与查询设施)、formatting(可复用的格式化操作); - verible/verilog:SystemVerilog 相关的库与工具。按 verible/verilog/README.md,可独立安装的工具都组织在
tools/下(syntax、lint、formatter、ls、diff、project、obfuscator、preprocessor、kythe 等),其余目录都是支撑库; - external_libs:部分外部库依赖。按 external_libs/README.md 的说明,首选方式是通过 Bazel 工作区声明外部依赖(当前即 MODULE.bazel),只有在工作流无法良好支持时才在此目录存放库的拷贝。
需要注意,第四部分中的“common 语言无关”约定不是纸面承诺,而是由 check-potential-problems.sh 在提交前检查中强制执行的——这体现了 Verible 用脚本固化架构约束的工程习惯。
五、深入子主题的文档地图
doc/development.md 本身是一个“枢纽文档”,它把四个子主题导向更深入的专项指南,这里按仓库现状逐一说明:
- Verilog 前端:doc/parser_design.md 描述了词法/解析器设计——Flex 生成词法器但与 Bison 生成的解析器完全解耦(
yyparse()并不直接调用yylex()),中间经过 contextualizer(消歧 token 的多重解释,简化 LR 语法)与 filter(把 token 流过滤成视图,如隐藏注释以便解析)两个环节;解析器用 LALR(1) 生成,其语法非常规地显式处理预处理构造、指令与宏,从而能对“有限但实用”的未预处理代码子集工作,并构建捕获所有非注释 token 的具体语法树(CST)。对应源码位于 verible/verilog/parser(verilog.lex与verilog.y); - 分析器(Lint 规则):doc/style_lint.md 是风格检查器的开发者指南,说明三类分析基类——
LineLintRule(逐行)、TokenStreamLintRule(逐 token)、SyntaxTreeLintRule(语法树,绝大多数 SystemVerilog 规则属于此类)——以及树分析工具与规则实现方法,规则实现集中在 verible/verilog/analysis/checkers; - 格式化工具:doc/formatter.md 讲解 formatter 的工作原理与调试方法(注意:development.md 原文此处链接拼写为
foramtter.md,仓库中实际文件为formatter.md); - 转换(Transformers):development.md 中该小节当前为空占位,暂无深入文档;
- Kythe 索引:doc/indexing.md 覆盖从下载 Kythe 工具集、构建 Web 前端,到用
--experimental_action_listener=:extract_cxx抽取编译事实、生成 GraphStore 与 serving tables 的完整流程,文中也提醒:如果只是想本地改代码,不必索引,直接调用.github/bin/make-compilation-db.sh生成编译数据库即可。
六、适用前提:本地构建环境
上述工作流默认在能完成构建的环境中运行,按 README.md 的开发者章节与仓库配置,适用前提包括:
- 需要 Bazel 构建系统与 C++20 兼容编译器;Nix 用户可以直接在仓库内
nix-shell,shell.nix 提供了 bazel_8、clang-tidy/clang-format 工具链(并通过CLANG_TIDY、CLANG_FORMAT环境变量注入版本),以及 lcov、buildifier、flex/bison 等开发辅助; - 常规构建命令为
bazel build -c opt //...;若 flex/bison 生成工具遇到编译问题,可加--//bazel:use_local_flex_bison使用本地工具链; - 需要静态链接产物时可用
bazel build -c opt --config=create_static_linked_executables //...(改用 bfd 链接器)。
小结
Verible 的 doc/development.md 用一页文档搭建起了贡献者的工作流骨架:在线索引 + clangd 编译数据库负责看懂代码,带缓存的 clang-tidy 与before-submit.sh负责守住质量(测试、多标准回归、格式化、架构约束检查一应俱全),目录 README 与四份专项文档(parser_design.md、style_lint.md、formatter.md、indexing.md) 则负责深入各子系统。配合 CONTRIBUTING.md 的沟通、代码评审与测试要求,这份开发资源文档与.github/bin/下的脚本共同构成了在本地完整复现 CI 检查的开发闭环。
- 开发工具
- Lint
- 静态分析
- 硬件开发
【免费下载链接】verible
Verible is a suite of SystemVerilog developer tools, including a parser, style-linter, formatter and language server
相关推荐
GRM-Gemma2-2B-sftreg部署最佳实践:CPU/GPU/NPU环境配置全攻略
GRM Gemma2 2B sftreg部署最佳实践:CPU/GPU/NPU环境配置全攻略 想要高效部署GRM Gemma2 2B sftreg奖励模型吗?🎯
Zvec 向量数据库贡献指南:从源码编译、测试到提交 PR 的完整开发者流程
Zvec 向量数据库贡献指南:从源码编译、测试到提交 PR 的完整开发者流程 Zvec 是一个内嵌式(in process)向量数据库:以 C++17 实现核心
向量数据库数据库嵌入式数据库Verible 贡献指南:代码风格、测试覆盖与提交前验证全流程
Verible 贡献指南:代码风格、测试覆盖与提交前验证全流程 Verible 是一个 SystemVerilog 开发者工具集(解析器、风格检查器、格式化工具
开发工具Lint静态分析硬件开发
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考