From e779323859fa6f39b7b8f6ec62089f9bc59037e5 Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Thu, 11 Jun 2026 16:26:04 +0100 Subject: [PATCH 01/10] add Rust bindings --- .github/workflows/test_bindings.yml | 21 ++++++++- .gitignore | 4 ++ CMakeLists.txt | 1 + MODULE.bazel | 1 + bindings/rust/Cargo.toml | 13 ++++++ bindings/rust/build.rs | 26 +++++++++++ bindings/rust/src/ffi.rs | 21 +++++++++ bindings/rust/src/lib.rs | 66 +++++++++++++++++++++++++++ bindings/rust/src/rust_api.cc | 27 +++++++++++ bindings/rust/src/rust_api.h | 14 ++++++ bindings/rust/tests/test_benchmark.rs | 16 +++++++ docs/releasing.md | 7 ++- 12 files changed, 214 insertions(+), 3 deletions(-) create mode 100644 bindings/rust/Cargo.toml create mode 100644 bindings/rust/build.rs create mode 100644 bindings/rust/src/ffi.rs create mode 100644 bindings/rust/src/lib.rs create mode 100644 bindings/rust/src/rust_api.cc create mode 100644 bindings/rust/src/rust_api.h create mode 100644 bindings/rust/tests/test_benchmark.rs diff --git a/.github/workflows/test_bindings.yml b/.github/workflows/test_bindings.yml index 3cf8064475..bd4bfff218 100644 --- a/.github/workflows/test_bindings.yml +++ b/.github/workflows/test_bindings.yml @@ -14,7 +14,7 @@ permissions: jobs: python_bindings: - name: Test GBM Python ${{ matrix.python-version }} bindings on ${{ matrix.os }} + name: Test Python ${{ matrix.python-version }} bindings on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -30,7 +30,24 @@ jobs: uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: ${{ matrix.python-version }} - - name: Install GBM Python bindings on ${{ matrix.os }} + - name: Install Python bindings on ${{ matrix.os }} run: python -m pip install . - name: Run example on ${{ matrix.os }} under Python ${{ matrix.python-version }} run: python bindings/python/google_benchmark/example.py + + rust_bindings: + name: Test Rust bindings on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ ubuntu-latest, macos-latest, windows-latest ] + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + fetch-depth: 0 + - name: Install Rust toolchain + uses: dtolnay/rust-toolchain@stable + - name: Run Rust tests + run: cargo test + working-directory: bindings/rust diff --git a/.gitignore b/.gitignore index bc0c14acd7..0adefece94 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,7 @@ CMakeSettings.json dist/ *.egg-info* uv.lock + +# Rust build stuff +/bindings/rust/target/ +/bindings/rust/Cargo.lock diff --git a/CMakeLists.txt b/CMakeLists.txt index d27698adc8..f08a86e40e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ option(BENCHMARK_ENABLE_GTEST_TESTS "Enable building the unit tests which depend option(BENCHMARK_USE_BUNDLED_GTEST "Use bundled GoogleTest. If disabled, the find_package(GTest) will be used." ON) option(BENCHMARK_ENABLE_LIBPFM "Enable performance counters provided by libpfm" OFF) +option(BENCHMARK_ENABLE_RUST_BINDINGS "Enable testing of the Rust bindings" OFF) # Export only public symbols set(CMAKE_CXX_VISIBILITY_PRESET hidden) diff --git a/MODULE.bazel b/MODULE.bazel index ad3df4a4f5..1bfeff2ef3 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -12,6 +12,7 @@ bazel_dep(name = "googletest", version = "1.14.0", dev_dependency = True, repo_n bazel_dep(name = "libpfm", version = "4.11.0.bcr.1") + # Register a toolchain for Python 3.9 to be able to build numpy. Python # versions >=3.10 are problematic. # A second reason for this is to be able to build Python hermetically instead diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml new file mode 100644 index 0000000000..a3960a7a41 --- /dev/null +++ b/bindings/rust/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "benchmark-rs" +version = "1.9.5" +edition = "2021" +description = "Rust bindings for google/benchmark" +license = "Apache-2.0" + +[dependencies] +cxx = "1.0" + +[build-dependencies] +cmake = "0.1" +cxx-build = "1.0" diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs new file mode 100644 index 0000000000..25c88eeb72 --- /dev/null +++ b/bindings/rust/build.rs @@ -0,0 +1,26 @@ +fn main() { + let dst = cmake::Config::new("../../") + .define("BENCHMARK_ENABLE_TESTING", "OFF") + .define("BENCHMARK_ENABLE_LTO", "OFF") + .define("BENCHMARK_ENABLE_WERROR", "OFF") + .build_target("benchmark") + .build(); + + println!("cargo:rustc-link-search=native={}/build/src", dst.display()); + println!("cargo:rustc-link-search=native={}/build/src/Debug", dst.display()); + println!("cargo:rustc-link-search=native={}/build/src/Release", dst.display()); + println!("cargo:rustc-link-lib=static=benchmark"); + + cxx_build::bridge("src/ffi.rs") + .file("src/rust_api.cc") + .include("../../include") + .include("src") + .std("c++17") + .compile("benchmark_rust_ffi"); + + println!("cargo:rerun-if-changed=src/ffi.rs"); + println!("cargo:rerun-if-changed=src/rust_api.cc"); + println!("cargo:rerun-if-changed=src/rust_api.h"); + println!("cargo:rerun-if-changed=../../src/"); + println!("cargo:rerun-if-changed=../../include/"); +} diff --git a/bindings/rust/src/ffi.rs b/bindings/rust/src/ffi.rs new file mode 100644 index 0000000000..d8ad766d9e --- /dev/null +++ b/bindings/rust/src/ffi.rs @@ -0,0 +1,21 @@ +#[cxx::bridge] +pub mod ffi { + #[namespace = "benchmark"] + unsafe extern "C++" { + include!("benchmark/benchmark.h"); + + type State; + + fn KeepRunning(self: Pin<&mut State>) -> bool; + fn RunSpecifiedBenchmarks() -> usize; + } + + #[namespace = "benchmark::rust_api"] + unsafe extern "C++" { + include!("rust_api.h"); + + unsafe fn SkipWithError(state: Pin<&mut State>, msg: &str); + unsafe fn RegisterBenchmark(name: &str, func: fn(Pin<&mut State>)); + unsafe fn Initialize(argc: *mut i32, argv: usize); + } +} diff --git a/bindings/rust/src/lib.rs b/bindings/rust/src/lib.rs new file mode 100644 index 0000000000..b13c7ecf67 --- /dev/null +++ b/bindings/rust/src/lib.rs @@ -0,0 +1,66 @@ +pub mod ffi; + +use std::ffi::CString; +use std::os::raw::c_char; +use std::pin::Pin; + +pub struct State<'a> { + #[doc(hidden)] + pub inner: Pin<&'a mut ffi::ffi::State>, +} + +impl<'a> State<'a> { + /// Returns true if the benchmark should continue running. + /// + /// **Note:** `keep_running()` currently has a small per-iteration overhead due to the FFI boundary. + /// In the future, this could be optimized using `KeepRunningBatch` under the hood. + #[inline] + pub fn keep_running(&mut self) -> bool { + self.inner.as_mut().KeepRunning() + } + + pub fn skip_with_error(&mut self, msg: &str) { + unsafe { + ffi::ffi::SkipWithError(self.inner.as_mut(), msg); + } + } +} + +/// Initialize the benchmark library. +/// This should be called before `run_specified_benchmarks`. +pub fn initialize(args: &Vec) { + let mut c_args: Vec = args.iter() + .map(|arg| CString::new(arg.as_str()).unwrap()) + .collect(); + + let mut c_ptrs: Vec<*mut c_char> = c_args.iter_mut() + .map(|c| c.as_ptr() as *mut c_char) + .collect(); + + let mut argc = c_ptrs.len() as i32; + let argv = c_ptrs.as_mut_ptr(); + + unsafe { + ffi::ffi::Initialize(&mut argc as *mut _, argv as usize); + } +} + +#[macro_export] +macro_rules! register_benchmark { + ($name:expr, $func:path) => { + { + fn trampoline(mut state: std::pin::Pin<&mut $crate::ffi::ffi::State>) { + let mut wrapped = $crate::State { inner: state.as_mut() }; + $func(&mut wrapped); + } + unsafe { + $crate::ffi::ffi::RegisterBenchmark($name, trampoline); + } + } + }; +} + +/// Run all registered benchmarks. +pub fn run_specified_benchmarks() -> usize { + ffi::ffi::RunSpecifiedBenchmarks() +} diff --git a/bindings/rust/src/rust_api.cc b/bindings/rust/src/rust_api.cc new file mode 100644 index 0000000000..48a3e3f0cc --- /dev/null +++ b/bindings/rust/src/rust_api.cc @@ -0,0 +1,27 @@ +#include "rust_api.h" + +#include + +namespace benchmark { +namespace rust_api { + +void RegisterBenchmark(rust::Str name, rust::Fn func); +void Initialize(int* argc, size_t argv); +void SkipWithError(benchmark::State& state, rust::Str msg); + +void RegisterBenchmark(rust::Str name, rust::Fn func) { + ::benchmark::RegisterBenchmark(std::string(name).c_str(), [func](benchmark::State& st) { + func(st); + }); +} + +void Initialize(int* argc, size_t argv) { + ::benchmark::Initialize(argc, (char**)argv); +} + +void SkipWithError(benchmark::State& state, rust::Str msg) { + state.SkipWithError(std::string(msg).c_str()); +} + +} // namespace rust_api +} // namespace benchmark diff --git a/bindings/rust/src/rust_api.h b/bindings/rust/src/rust_api.h new file mode 100644 index 0000000000..ea7cf4a343 --- /dev/null +++ b/bindings/rust/src/rust_api.h @@ -0,0 +1,14 @@ +#pragma once + +#include "benchmark/benchmark.h" +#include "rust/cxx.h" + +namespace benchmark { +namespace rust_api { + +void RegisterBenchmark(rust::Str name, rust::Fn func); +void Initialize(int* argc, size_t argv); +void SkipWithError(benchmark::State& state, rust::Str msg); + +} // namespace rust_api +} // namespace benchmark diff --git a/bindings/rust/tests/test_benchmark.rs b/bindings/rust/tests/test_benchmark.rs new file mode 100644 index 0000000000..5a50c4893f --- /dev/null +++ b/bindings/rust/tests/test_benchmark.rs @@ -0,0 +1,16 @@ +use benchmark_rs::{initialize, register_benchmark, run_specified_benchmarks, State}; + +fn my_benchmark(state: &mut State) { + while state.keep_running() { + // do nothing + } +} + +#[test] +fn test_bindings() { + let args = vec!["--benchmark_format=console".to_string(), "--benchmark_min_time=0.01".to_string()]; + initialize(&args); + register_benchmark!("BM_MyBenchmark", my_benchmark); + let count = run_specified_benchmarks(); + assert!(count > 0); +} diff --git a/docs/releasing.md b/docs/releasing.md index ab664a8640..a58dacd8e5 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -9,7 +9,7 @@ commits between the last annotated tag and HEAD * Pick the most interesting. * Create one last commit that updates the version saved in `CMakeLists.txt`, `MODULE.bazel`, - and `bindings/python/google_benchmark/__init__.py` to the release version you're creating. + `bindings/python/google_benchmark/__init__.py`, and `bindings/rust/Cargo.toml` to the release version you're creating. (This version will be used if benchmark is installed from the archive you'll be creating in the next step.) @@ -28,6 +28,11 @@ module(name = "com_github_google_benchmark", version="1.9.0") __version__ = "1.9.0" ``` +```toml +# bindings/rust/Cargo.toml +version = "1.9.0" +``` + * Create a release through github's interface * Note this will create a lightweight tag. * Update this to an annotated tag: From 8a725142afcf837cfe23e25b57b1fc71b67b3791 Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Thu, 11 Jun 2026 16:28:09 +0100 Subject: [PATCH 02/10] clang-format --- bindings/rust/src/rust_api.cc | 13 ++++++------- bindings/rust/src/rust_api.h | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/bindings/rust/src/rust_api.cc b/bindings/rust/src/rust_api.cc index 48a3e3f0cc..5efc5fac69 100644 --- a/bindings/rust/src/rust_api.cc +++ b/bindings/rust/src/rust_api.cc @@ -10,18 +10,17 @@ void Initialize(int* argc, size_t argv); void SkipWithError(benchmark::State& state, rust::Str msg); void RegisterBenchmark(rust::Str name, rust::Fn func) { - ::benchmark::RegisterBenchmark(std::string(name).c_str(), [func](benchmark::State& st) { - func(st); - }); + ::benchmark::RegisterBenchmark(std::string(name).c_str(), + [func](benchmark::State& st) { func(st); }); } void Initialize(int* argc, size_t argv) { - ::benchmark::Initialize(argc, (char**)argv); + ::benchmark::Initialize(argc, (char**)argv); } void SkipWithError(benchmark::State& state, rust::Str msg) { - state.SkipWithError(std::string(msg).c_str()); + state.SkipWithError(std::string(msg).c_str()); } -} // namespace rust_api -} // namespace benchmark +} // namespace rust_api +} // namespace benchmark diff --git a/bindings/rust/src/rust_api.h b/bindings/rust/src/rust_api.h index ea7cf4a343..17ccd0fd53 100644 --- a/bindings/rust/src/rust_api.h +++ b/bindings/rust/src/rust_api.h @@ -10,5 +10,5 @@ void RegisterBenchmark(rust::Str name, rust::Fn func); void Initialize(int* argc, size_t argv); void SkipWithError(benchmark::State& state, rust::Str msg); -} // namespace rust_api -} // namespace benchmark +} // namespace rust_api +} // namespace benchmark From d2d00e8880ec37d9b58ad6f9c642dd5b280b581f Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Thu, 11 Jun 2026 16:31:50 +0100 Subject: [PATCH 03/10] pre-commit fix --- MODULE.bazel | 1 - 1 file changed, 1 deletion(-) diff --git a/MODULE.bazel b/MODULE.bazel index 1bfeff2ef3..ad3df4a4f5 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -12,7 +12,6 @@ bazel_dep(name = "googletest", version = "1.14.0", dev_dependency = True, repo_n bazel_dep(name = "libpfm", version = "4.11.0.bcr.1") - # Register a toolchain for Python 3.9 to be able to build numpy. Python # versions >=3.10 are problematic. # A second reason for this is to be able to build Python hermetically instead From 7a9443f5d68f2cf43e1e8add49a16535c20db6cd Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Thu, 11 Jun 2026 16:34:09 +0100 Subject: [PATCH 04/10] windows static builds --- bindings/rust/build.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index 25c88eeb72..943e1117f7 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -16,8 +16,13 @@ fn main() { .include("../../include") .include("src") .std("c++17") + .define("BENCHMARK_STATIC_DEFINE", None) .compile("benchmark_rust_ffi"); + if cfg!(target_os = "windows") { + println!("cargo:rustc-link-lib=shlwapi"); + } + println!("cargo:rerun-if-changed=src/ffi.rs"); println!("cargo:rerun-if-changed=src/rust_api.cc"); println!("cargo:rerun-if-changed=src/rust_api.h"); From 232b878e1fa866e21031898a852c2919a24f5b86 Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Thu, 11 Jun 2026 16:38:21 +0100 Subject: [PATCH 05/10] Rust prefers MD on windows --- bindings/rust/build.rs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/bindings/rust/build.rs b/bindings/rust/build.rs index 943e1117f7..02a2f1a14e 100644 --- a/bindings/rust/build.rs +++ b/bindings/rust/build.rs @@ -1,10 +1,19 @@ fn main() { - let dst = cmake::Config::new("../../") + let mut config = cmake::Config::new("../../"); + config .define("BENCHMARK_ENABLE_TESTING", "OFF") .define("BENCHMARK_ENABLE_LTO", "OFF") .define("BENCHMARK_ENABLE_WERROR", "OFF") - .build_target("benchmark") - .build(); + .build_target("benchmark"); + + // Rust defaults to the Release CRT (/MD) on Windows even in Debug mode. + // Force CMake to use the Release profile so `google/benchmark` uses `/MD`, + // avoiding a mismatch with `cxx_build` (which uses `/MD`). + if cfg!(target_os = "windows") { + config.profile("Release"); + } + + let dst = config.build(); println!("cargo:rustc-link-search=native={}/build/src", dst.display()); println!("cargo:rustc-link-search=native={}/build/src/Debug", dst.display()); From 7415e87ad1f50ee3ac1f3017ed03abc4561b2fa3 Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Fri, 12 Jun 2026 12:46:52 +0100 Subject: [PATCH 06/10] check in lock file to avoid source poisoning --- .gitignore | 1 - bindings/rust/Cargo.lock | 301 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 bindings/rust/Cargo.lock diff --git a/.gitignore b/.gitignore index 0adefece94..53704eba79 100644 --- a/.gitignore +++ b/.gitignore @@ -70,4 +70,3 @@ uv.lock # Rust build stuff /bindings/rust/target/ -/bindings/rust/Cargo.lock diff --git a/bindings/rust/Cargo.lock b/bindings/rust/Cargo.lock new file mode 100644 index 0000000000..ed3fde5ec4 --- /dev/null +++ b/bindings/rust/Cargo.lock @@ -0,0 +1,301 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "benchmark-rs" +version = "1.9.5" +dependencies = [ + "cmake", + "cxx", + "cxx-build", +] + +[[package]] +name = "cc" +version = "1.2.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "clap" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +dependencies = [ + "clap_builder", +] + +[[package]] +name = "clap_builder" +version = "4.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +dependencies = [ + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_lex" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" + +[[package]] +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] + +[[package]] +name = "codespan-reporting" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +dependencies = [ + "serde", + "termcolor", + "unicode-width", +] + +[[package]] +name = "cxx" +version = "1.0.194" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "747d8437319e3a2f43d93b341c137927ca70c0f5dabeea7a005a73665e247c7e" +dependencies = [ + "cc", + "cxx-build", + "cxxbridge-cmd", + "cxxbridge-flags", + "cxxbridge-macro", + "foldhash", + "link-cplusplus", +] + +[[package]] +name = "cxx-build" +version = "1.0.194" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0f4697d190a142477b16aef7da8a99bfdc41e7e8b1687583c0d23a79c7afc1e" +dependencies = [ + "cc", + "codespan-reporting", + "indexmap", + "proc-macro2", + "quote", + "scratch", + "syn", +] + +[[package]] +name = "cxxbridge-cmd" +version = "1.0.194" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0956799fa8678d4c50eed028f2de1c0552ae183c76e976cf7ca8c4e36a7c328" +dependencies = [ + "clap", + "codespan-reporting", + "indexmap", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cxxbridge-flags" +version = "1.0.194" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23384a836ab4f0ad98ace7e3955ad2de39de42378ab487dc28d3990392cb283a" + +[[package]] +name = "cxxbridge-macro" +version = "1.0.194" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6acc6b5822b9526adfb4fc377b67128fdd60aac757cc4a741a6278603f763cf" +dependencies = [ + "indexmap", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "link-cplusplus" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f78c730aaa7d0b9336a299029ea49f9ee53b0ed06e9202e8cb7db9bae7b8c82" +dependencies = [ + "cc", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "scratch" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d68f2ec51b097e4c1a75b681a8bec621909b5e91f15bb7b840c4f2f7b01148b2" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] From d328ed96ffc364ad88adc1665164b1bd716e2eb5 Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Fri, 12 Jun 2026 12:47:20 +0100 Subject: [PATCH 07/10] use a rust crate name that isn't taken --- bindings/rust/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/rust/Cargo.toml b/bindings/rust/Cargo.toml index a3960a7a41..0a6dda959a 100644 --- a/bindings/rust/Cargo.toml +++ b/bindings/rust/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "benchmark-rs" +name = "google-benchmark-rs" version = "1.9.5" edition = "2021" description = "Rust bindings for google/benchmark" From 8630bb84927d792f00a89cde8fc1ce29aa23fb40 Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Fri, 12 Jun 2026 12:52:26 +0100 Subject: [PATCH 08/10] add CMake target for running Rust binding tests and integrate into CI --- .github/workflows/test_bindings.yml | 9 ++++++++- test/CMakeLists.txt | 9 +++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test_bindings.yml b/.github/workflows/test_bindings.yml index bd4bfff218..fa58f65edb 100644 --- a/.github/workflows/test_bindings.yml +++ b/.github/workflows/test_bindings.yml @@ -48,6 +48,13 @@ jobs: fetch-depth: 0 - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - - name: Run Rust tests + - name: Install Ninja (macOS) + if: runner.os == 'macOS' + run: brew install ninja + - name: Run Rust tests natively via Cargo run: cargo test working-directory: bindings/rust + - name: Run Rust tests via CMake target + run: | + cmake -S . -B build -DBENCHMARK_ENABLE_RUST_BINDINGS=ON + cmake --build build --target test_rust_bindings diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 374c09fa3f..588b463f59 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -326,3 +326,12 @@ if (${CMAKE_BUILD_TYPE_LOWER} MATCHES "coverage") " --coverage flag: ${CXX_FLAG_COVERAGE_MESSAGE}") endif() endif() + +if (BENCHMARK_ENABLE_RUST_BINDINGS) + find_program(CARGO_EXECUTABLE cargo REQUIRED) + add_custom_target(test_rust_bindings ALL + COMMAND ${CARGO_EXECUTABLE} test + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/bindings/rust + COMMENT "Running Rust bindings tests" + ) +endif() From 8276ed589e711c6daf0e19430332f47cad2f0e51 Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Fri, 12 Jun 2026 14:10:04 +0100 Subject: [PATCH 09/10] complete crate rename --- bindings/rust/tests/test_benchmark.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/rust/tests/test_benchmark.rs b/bindings/rust/tests/test_benchmark.rs index 5a50c4893f..025846b654 100644 --- a/bindings/rust/tests/test_benchmark.rs +++ b/bindings/rust/tests/test_benchmark.rs @@ -1,4 +1,4 @@ -use benchmark_rs::{initialize, register_benchmark, run_specified_benchmarks, State}; +use google_benchmark_rs::{initialize, register_benchmark, run_specified_benchmarks, State}; fn my_benchmark(state: &mut State) { while state.keep_running() { From 81006b3d649afda2fb197de3529e61050f7f1f3a Mon Sep 17 00:00:00 2001 From: Dominic Hamon Date: Fri, 12 Jun 2026 14:18:34 +0100 Subject: [PATCH 10/10] enable test dependency downloads in Rust bindings CI --- .github/workflows/test_bindings.yml | 2 +- bindings/rust/Cargo.lock | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test_bindings.yml b/.github/workflows/test_bindings.yml index fa58f65edb..e8639f2b78 100644 --- a/.github/workflows/test_bindings.yml +++ b/.github/workflows/test_bindings.yml @@ -56,5 +56,5 @@ jobs: working-directory: bindings/rust - name: Run Rust tests via CMake target run: | - cmake -S . -B build -DBENCHMARK_ENABLE_RUST_BINDINGS=ON + cmake -S . -B build -DBENCHMARK_ENABLE_RUST_BINDINGS=ON -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON cmake --build build --target test_rust_bindings diff --git a/bindings/rust/Cargo.lock b/bindings/rust/Cargo.lock index ed3fde5ec4..c0ed48717e 100644 --- a/bindings/rust/Cargo.lock +++ b/bindings/rust/Cargo.lock @@ -8,15 +8,6 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" -[[package]] -name = "benchmark-rs" -version = "1.9.5" -dependencies = [ - "cmake", - "cxx", - "cxx-build", -] - [[package]] name = "cc" version = "1.2.63" @@ -153,6 +144,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" +[[package]] +name = "google-benchmark-rs" +version = "1.9.5" +dependencies = [ + "cmake", + "cxx", + "cxx-build", +] + [[package]] name = "hashbrown" version = "0.17.1"