☰
Google Benchmark 版本发布流程全解析:版本提交、Git 标签与 Python Wheel 构建
2026/9/25 4:59:07 网站建设 项目流程
  • 性能测试

【免费下载链接】benchmark

A microbenchmark support library

项目地址:https://gitcode.com/gh_mirrors/benchmark5/benchmark
点击查看免费下载

本文基于 docs/releasing.md 中维护者定义的完整发布清单,逐环节拆解 Google Benchmark 项目从"验证构建"到"发布标签"再到"Python Wheel 自动构建"的整个版本发布链路,并结合 CMakeLists.txt、MODULE.bazel、pyproject.toml 等仓库文件说明每个步骤背后的工程原因。读完后,你将掌握一个同时维护 CMake、Bazel 双构建系统且附带 Python 绑定项目的标准发布操作,以及"为什么版本要提前写进配置文件""为什么 GitHub 的轻量标签必须改写成注释标签"这类关键细节。

一、发布前的总体准备

docs/releasing.md 定义的第一个前提是:确保当前处于main分支,并且已与远端 HEAD 完全同步,然后确认项目可以构建且测试能够运行。文档中给出了一个加速全量测试运行的实用技巧:

parallel -j0 exec ::: test/*_test

这条命令配合 GNUparallel以"全部可用核心"(-j0)并行执行test/目录下编译出的各个*_test测试二进制。对照仓库中的测试目录 test/,其中每个*_test.cc源文件(如 test/basic_test.cc、test/filter_test.cc 等)都会编译为一个独立的可执行程序,因此test/*_test恰好覆盖全部功能测试入口。文档明确这一手段"至少能确保所有测试都能通过"——这是发布动作的第一道质量门禁,任何一项测试失败都应阻塞后续流程。

二、准备发布说明(Release Notes)

发布说明的来源是"上一个版本标签到 HEAD 之间的提交列表",文档给出的命令为:

git log $(git describe --abbrev=0 --tags)..HEAD

其工作原理分两步:

  1. git describe --abbrev=0 --tags输出"距离 HEAD 最近的一个标签名",即上一个发布版本(例如v1.8.3);
  2. 外层的git log <上一个标签>..HEAD列出自该标签之后到当前 HEAD 的所有提交。

维护者随后从这份提交列表中"挑选最有意义的条目"(Pick the most interesting)写入发布说明。这一做法保证了 Release Notes 与实际交付的代码差异严格对应,不遗漏、不虚构。

三、关键版本提交:同步更新 CMake 与 Bazel 两处版本号

发布流程中最容易被忽略、但影响面最大的一步是:在创建发布之前,先创建最后一个提交,把保存在CMakeLists.txt和MODULE.bazel中的版本号更新为即将发布的版本。

3.1 两个必须同步的版本位置

文档原文示例:

project (benchmark VERSION 1.8.0 LANGUAGES CXX)
module(name = "com_github_google_benchmark", version="1.8.0")

对照当前仓库的实际内容,这两处分别位于:

  • CMakeLists.txt:project (benchmark VERSION 1.8.4 LANGUAGES CXX)
  • MODULE.bazel:module(name = "google_benchmark", version = "1.8.4")

两处分别服务不同的消费渠道:

  • CMakeLists.txt中的project(... VERSION ...)是 CMake 安装包的版本来源。下游通过find_package(benchmark REQUIRED)(见 README.md 中的 Usage with CMake 一节)导入库时,benchmark_VERSION就取自这里;
  • MODULE.bazel中的version是 Bazel bzlmod 体系的模块版本声明,Bazel 模块用户在锁定依赖版本时以此为准。根目录的 WORKSPACE.bzlmod 仅标记了 Bazel workspace 的根,真正的依赖与版本信息都集中在MODULE.bazel中。

文档特别解释了这一步的必要性:

This version will be used if benchmark is installed from the archive you'll be creating in the next step.

也就是说,从 GitHub Release 页面下载的是纯源码压缩包(不含.git目录),此时只能依赖配置文件里写死的版本号。仓库源码印证了这一机制:CMakeLists.txt 中有一段版本探测逻辑——构建时先通过GetGitVersion模块读取 git 标签得到GIT_VERSION;当探测不到(GIT_VERSION为占位值v0.0.0,典型场景就是从源码归档构建、没有 git 历史)时,回退使用project()命令中的benchmark_VERSION作为VERSION。随后代码还会对版本号做归一化处理(去掉v前缀、把vX.Y-<距离数>-<hash>形式的描述式版本转成X.Y.Z),最终用于派生库的SOVERSION:

# If no git version can be determined, use the version # from the project() command if ("${GIT_VERSION}" STREQUAL "v0.0.0") set(VERSION "v${benchmark_VERSION}") else() set(VERSION "${GIT_VERSION}") endif()

因此,如果发布前忘记提交这次版本更新,归档安装出来的库版本就会停留在上一个版本,属于典型的"发布事故"。这也是文档把版本提交安排在"创建 release"之前、并要求它是"最后一个提交"(one last commit)的原因。

3.2 操作要点小结

  1. 切换到main并同步到 HEAD;
  2. 确认构建与全部测试通过;
  3. 用git log $(git describe --abbrev=0 --tags)..HEAD起草发布说明;
  4. 提交版本号更新:同时修改CMakeLists.txt的project(... VERSION ...)与MODULE.bazel的module(... version = ...),两处数值必须一致;
  5. 进入标签与 Release 环节(下一节)。

四、创建 GitHub Release,并将轻量标签改写为注释标签

文档指出,通过 GitHub 界面创建 release 时,Git 层面实际产生的是一个轻量标签(lightweight tag)——它只是一个指向 commit 的普通引用,不携带标签者、时间戳和标签消息。为了保证后续工具链(尤其是基于标签的版本推导系统)能拿到完整元数据,需要把它改写为注释标签(annotated tag)。文档给出的完整命令序列:

git pull --tags git tag -a -f <tag> <tag> git push --force --tags origin

逐步解读:

  • git pull --tags:先把远端刚创建的轻量标签拉取到本地;
  • git tag -a -f <tag> <tag>:-a表示创建注释标签,-f表示强制覆盖已有的同名轻量标签。这里用"同名指向同名"的写法,等价于原地把轻量标签升级为注释标签(commit 指向不变,但引用对象由 commit 变为 tag 对象);
  • git push --force --tags origin:由于远端已存在同名轻量标签,普通推送会被拒绝,因此必须--force强推标签引用。

这一步不能省略,它直接关系到最后一步 Python Wheel 的版本推导是否正确——下一节会解释。

五、确认 "Build and upload Python wheels" 工作流完成

本仓库为 Python 提供了基于 nanobind 的绑定(见 bindings/python/google_benchmark/BUILD 中的nanobind_extension目标),并配套了发布到 PyPI 的自动化流程。docs/releasing.md的最后一项要求:

  1. 确认 "Build and upload Python wheels" 这一 GitHub Actions 工作流运行完成;如果它没有自动触发,需要手动运行;
  2. 关键注意点(文档原文以 IMPORTANT 标出):手动重新运行工作流时,务必在 GitHub Actions 页面的 "Run workflow" 选项卡中,选择刚创建的<tag>作为 workflow version,否则工作流会基于错误的提交/标签构建,产出的 Wheel 版本号将是错的。

这一"标签决定 Wheel 版本"的机制在仓库配置中可以找到直接证据:

  • pyproject.toml 声明dynamic = ["readme", "version"],即包版本是动态计算而非写死的;
  • pyproject.toml 的构建系统依赖setuptools-scm[toml],该工具正是从git 标签推导版本号的——这解释了为什么第四节的"轻量标签改注释标签"必不可少:setuptools-scm读取标签信息时依赖完整的标签元数据,且版本数值必须来自本次发布的确切标签;
  • 安装后,绑定包通过 bindings/python/google_benchmark/version.py 中的importlib.metadata.version("google-benchmark")对外暴露版本,因此工作流构建的 Wheel 版本号就是 PyPI 上用户看到的最终版本;
  • pyproject.toml 同时声明了requires-python = ">=3.8",classifiers覆盖 Python 3.8~3.12,Wheel 的构建与校验应以这些约束为前提。

验证环节完成后,一次发布才算真正结束:C/C++ 用户通过源码归档 +find_package/add_subdirectory消费新版本,Bazel 模块用户通过 bzlmod 锁定新版本,Python 用户通过 PyPI 安装新 Wheel,三条渠道的版本号完全一致。

六、发布检查清单(速查)

将 docs/releasing.md 的完整流程整理为可执行的检查清单:

步骤命令 / 操作说明
1. 分支确认git checkout main && git pull确保在 main 且同步到 HEAD
2. 构建与测试构建项目;parallel -j0 exec ::: test/*_test全部测试必须通过
3. 起草发布说明git log $(git describe --abbrev=0 --tags)..HEAD取上一标签到 HEAD 的提交列表,挑选关键条目
4. 版本提交更新 CMakeLists.txt 的project(... VERSION ...)与 MODULE.bazel 的version必须提交,且数值一致;供无 git 环境的归档安装使用
5. 创建 ReleaseGitHub 界面创建 release实际生成轻量标签
6. 升级为注释标签git pull --tags
git tag -a -f <tag> <tag>
git push --force --tags origin
保证标签元数据完整,供 setuptools-scm 等工具推导版本
7. Wheel 工作流确认 "Build and upload Python wheels" 运行完成手动重跑时必须在 "Run workflow" 中选择新<tag>作为 workflow version

七、适用前提与注意事项

  • 适用版本范围:当前仓库CMakeLists.txt与MODULE.bazel中的版本为1.8.4,文档示例中的1.8.0为撰写时的占位版本,实际操作时以"即将发布的下一个版本号"替换两处数值即可。
  • 版本探测机制的前提:CMakeLists.txt 中"git 标签优先、project()版本兜底"的双轨机制意味着:带完整 git 历史的克隆仓库构建时,版本由标签决定;只有归档/子模块等无标签场景才回落到project()版本。发布前提交版本号的收益主要体现在后者。
  • 强制推送的安全性:git push --force --tags仅影响标签引用(tag ref),不影响main分支的 commit 历史,但会覆盖远端同名标签,操作前应确认标签确实指向本次发布提交。
  • Bazel 消费方:模块名与版本以 MODULE.bazel 为准(google_benchmark,当前1.8.4),该文件还声明了bazel_skylib、rules_cc、googletest等构建依赖,发布时仅需改动其中的version字段,不应连带改动依赖声明。

八、总结

Google Benchmark 的发布流程看似只是几条命令,实则串联了三条版本消费渠道(CMake 归档安装、Bazel bzlmod、PyPI Wheel)和一套完整的质量门禁。其设计要点可以概括为:先验证(构建+全量测试)、再定版(双配置文件同步提交,保证归档可用)、后打标(注释标签保证元数据完整)、最后验渠道(Wheel 工作流绑定正确标签)。理解了GetGitVersion的兜底逻辑与setuptools-scm的标签驱动机制之后,文档中每一步"为什么必须这样做"就有了清晰的源码级依据。

  • 性能测试

【免费下载链接】benchmark

A microbenchmark support library

项目地址:https://gitcode.com/gh_mirrors/benchmark5/benchmark
点击查看免费下载
上一篇:Stable Diffusion WebUI Forge批量图像处理:效率提升10倍的秘诀
下一篇:imgui-rs高级功能探索:表格、拖拽、停靠等企业级特性

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询