Skip to content

Respect --instrumentation_filter for Rust coverage#3998

Open
tamasvajk wants to merge 6 commits intobazelbuild:mainfrom
tamasvajk:coverage-instrumentation-filter
Open

Respect --instrumentation_filter for Rust coverage#3998
tamasvajk wants to merge 6 commits intobazelbuild:mainfrom
tamasvajk:coverage-instrumentation-filter

Conversation

@tamasvajk
Copy link
Copy Markdown
Contributor

@tamasvajk tamasvajk commented Apr 28, 2026

Summary

Respect --instrumentation_filter when instrumenting Rust targets for coverage, consistent with Bazel's recommended approach for rules.

Problem

Previously, all Rust targets were instrumented with -Cinstrument-coverage when running bazel coverage, regardless of --instrumentation_filter. This causes:

  • Third-party and vendored crate dependencies to be unnecessarily recompiled with coverage instrumentation, slowing down builds
  • Coverage reports to include noise from code the user doesn't care about

Changes

  1. rustc.bzl: Add ctx.coverage_instrumented() check, the standard Bazel API for respecting --instrumentation_filter. Only targets matching the filter get -Cinstrument-coverage.

  2. collect_coverage.rs: Handle zero .profraw files gracefully. When a test target is not instrumented (because it doesn't match the filter), no profraw files are produced. Previously this caused llvm-profdata merge to fail with "no input files specified". Now it writes an empty coverage file and exits successfully.

  3. .bazelrc: Add coverage --instrumentation_filter=^// so that all workspace targets are instrumented by default.

  4. .bazelci/presubmit.yml: Add --instrumentation_filter=^// to all CI coverage tasks.

Usage

The default --instrumentation_filter=^// instruments all workspace targets. Projects with vendored dependencies should narrow this:

# .bazelrc
coverage --instrumentation_filter=^//,-^//third_party

Note: This PR was largely AI-generated using Claude Code, with human review and guidance throughout.

@tamasvajk tamasvajk marked this pull request as draft April 28, 2026 16:34
@tamasvajk tamasvajk marked this pull request as ready for review April 28, 2026 16:59
Previously, all Rust targets were instrumented with
-Cinstrument-coverage when running `bazel coverage`, regardless of
--instrumentation_filter. This differs from how coverage works for
Java and C++ targets, where only targets matching the filter are
instrumented.

Add ctx.coverage_instrumented() check so that Rust coverage respects
the same filter, reducing unnecessary recompilation and keeping
coverage reports focused on the code under test.
@tamasvajk tamasvajk force-pushed the coverage-instrumentation-filter branch from 882a206 to a9530b0 Compare April 28, 2026 17:00
Without an explicit --instrumentation_filter, Bazel's default filter
may not match workspace targets, causing ctx.coverage_instrumented()
to return False and producing empty Rust coverage reports.

Add coverage --instrumentation_filter=^// to both .bazelrc and all
CI coverage tasks. Projects with vendored dependencies should narrow
this, e.g.: coverage --instrumentation_filter=^//,-^//third_party
@tamasvajk tamasvajk force-pushed the coverage-instrumentation-filter branch from a9530b0 to 26d2d7e Compare April 28, 2026 17:26
Tamas Vajk added 4 commits April 28, 2026 18:19
ctx.coverage_instrumented() returns False for test targets by design
(Bazel considers test sources not worth instrumenting). But Rust test
binaries statically link their dependencies, and the coverage runtime
only initializes if the binary itself is compiled with
-Cinstrument-coverage. Without this, test binaries produce no profraw
files and coverage collection fails with "no input files specified".

Always add -Cinstrument-coverage for test crates (crate_info.is_test)
when coverage is enabled, while still respecting the instrumentation
filter for library targets.
When a test target is not instrumented (e.g. due to
--instrumentation_filter), no .profraw files are produced. Previously
llvm-profdata merge would fail with "no input files specified".

Write an empty coverage file and exit successfully instead, so that
uninstrumented test targets don't break coverage collection.
The .bazelrc is inherited by sub-workspace CI tasks (cc_common_link,
bzlmod_repo_mapping, sys, pyo3) causing build/test failures. The flag
is already passed via coverage_flags in presubmit.yml for coverage tasks.
@tamasvajk tamasvajk force-pushed the coverage-instrumentation-filter branch from 8065153 to 077019a Compare April 28, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant