BenchmarkDotNet 从源码构建完全指南:Visual Studio 与命令行双方案详解
【免费下载链接】BenchmarkDotNetPowerful .NET library for benchmarking项目地址: https://gitcode.com/gh_mirrors/be/BenchmarkDotNet
导读
本文讲解如何从源码构建 BenchmarkDotNet 这一 .NET 基准测试库。核心内容基于仓库 docs/articles/contributing/building.md 展开,并结合仓库根目录的 build.cmd、build/build.sh 以及build/BenchmarkDotNet.Build下的 Cake 构建工程源码,深入剖析构建系统的任务体系、依赖项与常用参数。读完本文,你将掌握两种官方推荐的构建方式:Visual Studio 图形界面构建与跨平台命令行构建,并能熟练使用build.cmd执行编译、测试、打包、文档生成、发布等各类构建任务。
构建方式总览
BenchmarkDotNet 仓库提供两条官方推荐的从源码构建路径:
- Visual Studio 方式:适合 Windows 上的交互式开发与调试,直接打开解决方案文件执行 Build。
- 命令行方式:基于 Cake(C# Make)的跨平台自动化构建,在 Windows、Linux、macOS 上使用同一套脚本与任务。
两种方式最终都依赖 .NET SDK 完成编译,命令行方式额外封装了依赖安装、任务编排与结果输出等自动化能力。
方式一:使用 Visual Studio 构建
环境准备
在开始前需要安装以下工具:
- Visual Studio 与 tests/BenchmarkDotNet.IntegrationTests.FSharp/BenchmarkDotNet.IntegrationTests.FSharp.fsproj。
- .NET 10 SDK 中确认,其指定了 SDK 版本
10.0.400且rollForward为disable,即要求精确匹配该版本。
构建步骤
工具就绪后,构建非常简单:
- 打开位于仓库根目录的解决方案文件BenchmarkDotNet.slnx(注意是
.slnx新型解决方案格式,不是传统的.sln)。 - 在 Visual Studio 中执行Build操作(
Ctrl+Shift+B或菜单 Build → Build Solution)即可完成编译。
解决方案同时被 build/BenchmarkDotNet.Build/Runners/BuildRunner.cs 中的DotNetBuild调用引用,命令行方式与 IDE 方式构建的是同一套工程。
方式二:命令行构建(Cake 自动化)
构建系统的定位
命令行构建基于 Cake(C# Make),这是一个跨平台的构建自动化系统,使用 C# DSL 描述构建流程,可完成代码编译、文件/目录复制、单元测试运行、压缩打包以及 NuGet 包生成等任务。
值得注意的是,当前仓库的构建工程采用的是Cake Frosting模式——构建逻辑本身就是一段 C# 程序。入口在 build/BenchmarkDotNet.Build/Program.cs:
Program.Main先通过 CommandLineParser 解析用户输入的任务名与参数;- 然后使用
CakeHost配合BuildContext运行对应的FrostingTask。
每个构建任务都是一个继承FrostingTask<BuildContext>的类,通过[TaskName]与[TaskDescription]特性声明任务名与描述,通过[IsDependentOn]声明任务间的依赖关系,通过实现IHelpProvider提供该任务的帮助信息。
启动脚本:build.cmd
在仓库根目录执行 build.cmd 即可启动构建。该脚本本身是一个跨平台分发器:
- 在 Windows 上,它调用 build/build.bat;
- 在 Linux/macOS 上,它调用 build/build.sh。
当不带任何参数执行时,脚本会打印帮助信息,列出所有可用构建任务。这是探索构建能力的第一步,也是排查参数错误时的好帮手。
跨平台前置依赖
构建脚本根据操作系统有不同的前置依赖要求:
Windows
- PowerShell 5 或更高版本
- MSBuild 15.1 或更高版本
- .NET Framework 4.6 或更高版本
Linux
- Mono 5 或更高版本
- fsharp 包
- 运行 .NET Core SDK 所需的系统包:
gettextlibcurl4-openssl-devlibicu-devlibssl-devlibunwind8
macOS
- Mono 5 或更高版本
- fsharp 包
- 最新版本的 OpenSSL
需要说明的是,文档中列出的 Mono、OpenSSL 等传统依赖主要是为了支持旧版 .NET Framework / F# 场景;现代 .NET 编译链路由脚本自动安装的 .NET SDK 承担。
build.sh 的自动化引导逻辑
在 Linux/macOS 上,build/build.sh 会完成 SDK 的自动化引导:
- 设置环境变量(跳过首次体验、关闭遥测、指定 HTTP 处理器);
- 若仓库根目录下不存在
.dotnet目录,则自动下载 dotnet-install.sh 指定的版本安装 SDK,同时额外安装 .NET 8 SDK(用于支持多目标框架测试); - 将本地安装的 SDK 加入
PATH与DOTNET_ROOT; - 最后以 Release 配置运行
dotnet run启动构建工程build/BenchmarkDotNet.Build/BenchmarkDotNet.Build.csproj,并把命令行参数透传进去。
这套引导逻辑保证了在全新机器上,即使尚未安装匹配版本的 .NET SDK,也能自动完成准备并进入构建流程。
构建任务清单与依赖关系
通过阅读 build/BenchmarkDotNet.Build/Program.cs 中的各个FrostingTask,可以整理出完整的任务清单。所有任务名与描述也会在build.cmd无参数执行时打印出来。
| 任务名 | 描述 | 关键依赖 |
|---|---|---|
build | 构建 BenchmarkDotNet.slnx 解决方案 | restore |
restore | 还原 NuGet 包 | pack-weaver |
pack-weaver | 打包 BenchmarkDotNet.Weaver(IL 织入器) | — |
unit-tests | 运行单元测试(快速) | build |
analyzer-tests | 运行分析器测试 | build |
in-tests-full | 使用 .NET Framework 4.7.2 运行集成测试(慢,仅 Windows) | build |
in-tests-core | 使用 .NET 10 运行集成测试(慢) | build |
all-tests | 运行全部单元、分析器与集成测试(慢) | unit-tests、analyzer-tests、in-tests-full、in-tests-core |
build-analyzers | 构建 BenchmarkDotNet.Analyzers | — |
move-analyzer-rules | 将已更新的分析器规则从未发布文件移至已发布文件 | — |
pack | 打包 NuGet 包 | build、build-analyzers |
install-wasm-tools | 安装 wasm-tools workload | — |
docs-fetch | 拉取更新变更日志文件 | — |
docs-generate | 生成辅助文档文件 | — |
docs-build | 构建最终文档 | docs-generate |
version-increment | 递增当前版本号 | — |
release | 发布新版本 | build、pack、docs-fetch、docs-generate、docs-build |
任务依赖关系在源码中以[IsDependentOn]特性声明,例如:
restore依赖pack-weaver——因为 Weaver 包的本地包必须先打出来,才能被解决方案还原引用;unit-tests/analyzer-tests依赖build——先编译再测试;pack同时依赖build与build-analyzers——打包主库与 Roslyn 分析器;release是链路上的最终任务,聚合了构建、打包与文档生成。
典型用法示例
# 查看帮助与全部任务列表(无参数执行) build.cmd # 查看某个任务的帮助 build.cmd build --help # 还原 + 构建解决方案(默认 Release 配置) build.cmd build # 以 Debug 配置构建 build.cmd build /p:Configuration=Debug # 运行快速单元测试 build.cmd unit-tests # 只执行目标任务本身,跳过其依赖任务 build.cmd unit-tests --exclusive # 打包 NuGet 包,并指定版本前缀与后缀 build.cmd pack /p:VersionPrefix=0.1.1729 /p:VersionSuffix=preview # 打包稳定版本(去掉 VersionSuffix) build.cmd pack --stable # 安装 wasm-tools workload(用于构建 WebAssembly 相关工程) build.cmd install-wasm-tools这些示例大多直接取自Program.cs中各个任务IHelpProvider.GetHelp()声明的Examples,是可以直接复制的真实用法。
常用命令行参数解析
构建脚本的参数解析逻辑位于 build/BenchmarkDotNet.Build/CommandLineParser.cs,支持的参数定义在 build/BenchmarkDotNet.Build/Options/KnownOptions.cs。解析器对任务名做了容错处理:忽略连字符且不区分大小写(例如unit-tests与unittests等价);-t/--target可显式指定任务;以/p:开头的参数会被转换为 MSBuild 属性传入 Cake。
全局参数
| 参数 | 别名 | 说明 |
|---|---|---|
--verbosity <VALUE> | -v | 控制输出信息量:Quiet / Minimal / Normal / Verbose / Diagnostic |
--exclusive | -e | 只执行目标任务本身,不执行其依赖任务 |
--help | -h | 打印帮助信息(全局帮助或某个任务的帮助) |
--stable | -s | 移除 MSBuild 设置中的 VersionSuffix,用于打包正式版 |
任务专属参数
| 参数 | 别名 | 适用任务 | 说明 |
|---|---|---|---|
--preview | -p | docs-fetch、docs-generate、docs-build | 文档变更日志中包含即将发布的版本 |
--depth <VALUE> | -d | docs-fetch | 需要重新生成变更日志的最近稳定版本数量,all表示全部,默认 0 |
--force-clone | -f | docs-fetch | 强制重新克隆变更日志仓库,删除已有目录 |
--next-version <VALUE> | -n | version-increment、release | 指定下一个版本号 |
--push | — | release | 指定后真正执行 GitHub 与 nuget.org 的推送 |
MSBuild 属性透传
所有任务都支持/p:<KEY>=<VALUE>语法将自定义属性透传给 MSBuild,例如:
build.cmd build /p:Configuration=Debug build.cmd pack /p:VersionPrefix=0.1.1729 /p:VersionSuffix=preview从源码看,pack任务还会自动附加--include-symbols、-p:SymbolPackageFormat=snupkg、-p:IsFullPack=true等参数,用于同时产出源码符号包(snupkg),并保证与版本相关属性的一致性。
环境变量
部分任务需要环境变量配合,尤其是发布相关任务:
GitHubToken:docs-fetch、release任务拉取/推送 GitHub 时使用;NuGetToken:release任务向 nuget.org 推送时使用。
测试任务背后的工程映射
测试任务的工程映射可以在 build/BenchmarkDotNet.Build/Runners/UnitTestRunner.cs 中看到:
| 任务 | 测试工程 |
|---|---|
unit-tests | tests/BenchmarkDotNet.Tests/BenchmarkDotNet.Tests.csproj 与 tests/BenchmarkDotNet.Exporters.Plotting.Tests/BenchmarkDotNet.Exporters.Plotting.Tests.csproj |
analyzer-tests | tests/BenchmarkDotNet.Analyzers.Tests/BenchmarkDotNet.Analyzers.Tests.csproj |
in-tests-full/in-tests-core | tests/BenchmarkDotNet.IntegrationTests/BenchmarkDotNet.IntegrationTests.csproj |
测试运行细节:
unit-tests按 Utils.GetTargetFrameworks 返回的目标框架列表逐框架执行;in-tests-full使用net472目标框架,且仅当构建运行在 Windows 上(ShouldRun中判断IsRunningOnWindows)才执行;in-tests-core使用net10.0目标框架;- 测试结果以 TRX 格式输出到仓库根目录的
TestResults目录,文件名形如linux(x64)-unit-net10.0.trx,同时控制台会输出 detailed 级别的日志,便于 CI 归档与排查。
如果你只想快速验证某个改动,优先运行unit-tests;完整回归请运行all-tests(耗时较长,且集成测试需要实际启动子进程运行基准,务必在性能稳定的机器上执行)。
打包与发布流程
pack:产出 NuGet 包
pack任务会先清空输出目录,然后对 src 下所有可打包工程逐一执行dotnet pack,最终产物输出到artifacts目录。打包范围包括:
- 主库 src/BenchmarkDotNet/BenchmarkDotNet.csproj
- 注解库 src/BenchmarkDotNet.Annotations/BenchmarkDotNet.Annotations.csproj
- Roslyn 分析器 src/BenchmarkDotNet.Analyzers/BenchmarkDotNet.Analyzers.csproj
- 代码修复器 src/BenchmarkDotNet.CodeFixers/BenchmarkDotNet.CodeFixers.csproj
- Windows 专属诊断器 src/BenchmarkDotNet.Diagnostics.Windows/BenchmarkDotNet.Diagnostics.Windows.csproj
- dotMemory / dotTrace 集成、TestAdapter、Weaver 等其余可打包工程
- 项目模板 templates/BenchmarkDotNet.Templates.csproj
主库打包时会附加-p:IsFullPack=true,并启用 snupkg 符号包输出。
release:一键发布
release任务串联了build、pack、docs-fetch、docs-generate、docs-build等前置任务,最终由 ReleaseRunner 执行发布。典型用法:
build.cmd release --stable --next-version 0.1.1729 --push其中--push表示真正执行 GitHub 与 nuget.org 推送(省略时仅演练流程),同时需要配置GitHubToken与NuGetToken环境变量。
常见问题与排障建议
1. 无参数运行 build.cmd 报错或没反应?无参数运行会直接打印帮助信息而不是执行构建,这是预期行为。真正构建需要显式指定任务名,例如build.cmd build。
2. 提示 SDK 版本不匹配?build/sdk/global.json 固定了 SDK 版本为10.0.400且禁止 rollForward。请安装对应版本的 .NET SDK,或使用build.sh让脚本自动下载安装到仓库内的.dotnet目录。
3. 任务名拼写不敏感但连字符很关键?解析器会忽略连字符与大小写差异,但为了可读性和帮助文档的一致性,建议按官方任务名书写。
4. 只想单独跑一个任务?使用--exclusive(-e)跳过依赖任务。例如只想编译而不想重新还原时,可尝试build.cmd build --exclusive,但请确保此前已执行过restore。
5. Linux 构建报缺少系统库?对照上文 Linux 前置依赖清单安装gettext、libcurl4-openssl-dev、libicu-dev、libssl-dev、libunwind8等包(具体包名随发行版略有差异)。
6. 查看某个任务支持哪些参数?执行build.cmd <任务名> --help,例如build.cmd pack --help,会打印该任务的描述、示例、专属参数与环境变量要求。
延伸阅读
- docs/articles/contributing/building.md:本文的原始依据文档;
- docs/articles/contributing/running-tests.md:测试运行详解;
- docs/articles/contributing/debugging.md:调试指南;
- docs/articles/contributing/documentation.md:文档贡献说明;
- tests/runCoreTests.sh 与 tests/runClassicTests.cmd:测试脚本的另一种快速入口。
【免费下载链接】BenchmarkDotNetPowerful .NET library for benchmarking项目地址: https://gitcode.com/gh_mirrors/be/BenchmarkDotNet
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考