Skip to content

Enable code coverage on windows for C++ using clang.#26594

Draft
KrishnaM256 wants to merge 11 commits intobazelbuild:masterfrom
KrishnaM256:master
Draft

Enable code coverage on windows for C++ using clang.#26594
KrishnaM256 wants to merge 11 commits intobazelbuild:masterfrom
KrishnaM256:master

Conversation

@KrishnaM256
Copy link
Copy Markdown

@KrishnaM256 KrishnaM256 commented Jul 21, 2025

Summary

When running bazel coverage on Windows, users often encounter errors as described in #18839 and #15835, including the %1 is not a valid Win32 application. message.

This PR resolves those issues by:

  • Adding a fallback mechanism to correctly locate the coverage script.
  • Introducing a .bat wrapper for the collect_coverage.sh script, which addresses the Win32 application error.

With these changes, seamless C++ code coverage collection on Windows using Clang is now enabled.


Why is this needed?

These improvements allow Bazel to collect and generate code coverage reports inside _cc_coverage.dat file located at COVERAGE_DIR directory for C++ targets on Windows using Clang, streamlining the workflow and reducing manual troubleshooting for users on this platform.

Closes #15835 and #6374.


Implementation Details

  • Follow the official Windows troubleshooting guide and set the BAZEL_SH environment variable as recommended.

  • Add the following flags to your .bazelrc to configure coverage collection with LLVM tools:

    build --experimental_generate_llvm_lcov
    test --test_env=BAZEL_SH
    test --test_env=LLVM_PROFDATA="C:/Program Files/LLVM/bin/llvm-profdata.exe"
    test --test_env=LLVM_COV="C:/Program Files/LLVM/bin/llvm-cov.exe"
    test --test_env=GCOV_COVERAGE=0
    coverage --experimental_fetch_all_coverage_outputs
    
  • Ensure that:

    • The Windows environment variable BAZEL_SH is set to the path of your shell (e.g., MSYS2 or Git Bash).
    • Paths to llvm-profdata.exe and llvm-cov.exe are correct for your setup.

Additional Notes

  • After applying these changes, running bazel coverage on C++ targets with Clang on Windows should work as expected, and coverage reports should be generated without manual intervention.
  • See #15835 for additional context and user reports related to these issues.

@KrishnaM256 KrishnaM256 marked this pull request as ready for review July 21, 2025 10:35
@KrishnaM256 KrishnaM256 requested review from a team and lberki as code owners July 21, 2025 10:35
@KrishnaM256 KrishnaM256 requested review from mai93 and removed request for a team July 21, 2025 10:35
@github-actions github-actions bot added team-Configurability platforms, toolchains, cquery, select(), config transitions awaiting-review PR is awaiting review from an assigned reviewer labels Jul 21, 2025
@KrishnaM256 KrishnaM256 marked this pull request as draft July 21, 2025 10:35
.value(labelCache.get(toolsRepository + "//tools/test:collect_coverage")))
.value(labelCache.get(toolsRepository +
(OS.getCurrent() == OS.WINDOWS ?
"//tools/test:collect_coverage_wrapper" :
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be cleaner to keep the same label here and instead make it an alias with a select on @platforms//os:windows in the BUILD file.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the suggestion! That sounds like a cleaner approach. I’ll update the PR to use an alias with a select statement in the BUILD file as recommended.

:: ==============================================================================
@echo off
setlocal
%BAZEL_SH% "%~dp0collect_coverage.sh" %*
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of crafting a custom wrapper, could you try making the collect_coverage target an sh_binary instead of a filegroup? That rule already has the necessary logic to create a launcher binary on Windows which honors BAZEL_SH etc.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switching the collect_coverage target to an sh_binary makes sense, and I agree it would simplify the setup on Windows. I’ll update the PR to use sh_binary instead of a filegroup and test to ensure that it works as expected with BAZEL_SH.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I switch from filegroup to sh_binary, I encounter the following error due to the requirement that the target must produce exactly one file:
'@bazel_tools//tools/test:collect_coverage' must produce a single file because of the singleArtifact() check.

If I remove or comment out the singleArtifact() line, Bazel crashes with a NullPointerException further down in the build.

Given these constraints, would you recommend using an alias instead, or is there another preferred approach to work around this limitation?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For additional context:

  • When collect_coverage is a filegroup, building //tools/test:collect_coverage outputs only tools/test/collect_coverage.sh.
  • When I change it to an sh_binary, building the same target produces:
    • tools/test/collect_coverage.sh
    • bazel-out/x64_windows-fastbuild/bin/tools/test/collect_coverage
    • bazel-out/x64_windows-fastbuild/bin/tools/test/collect_coverage.exe

It seems like the multiple outputs from sh_binary are conflicting with the single file requirement

}

(void)result->Absolutize(cwd);
if (!IsReadableFile(*result)) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fallback shouldn't be necessary - could you share the error you see if you don't add it?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can refer to issues #18839 and #15835 for more details—I encounter the exact same error: The system cannot find the file specified. Let me know if you need any additional context!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you address the other comments and add an integration test that runs on Windows (you could also just drop the no-windows tag on the existing coverage tests), I can look into the root cause of the failure without this fallback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the guidance! I’ll address the other comments and update the PR to include an integration test that runs on Windows. Once that’s done, I’ll let you know so you can investigate the root cause of the failure without the fallback.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @fmeum, I’ve removed the fallback, could you please review the changes and let me know if there are any other modifications needed?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I started a parallel PR that adds support for multiple files in collect_coverage. There's still one issue left that I need to debug, but once that's done, you should be able to base your PR on it.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh nice, that’s great!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR now passes CI and includes an updated integration test that you can use as the basis for getting the others to pass.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Great to hear the PR passes CI. I’ll use the updated integration test as a reference to get the remaining tests passing.

@KrishnaM256 KrishnaM256 requested a review from fmeum July 22, 2025 11:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-review PR is awaiting review from an assigned reviewer team-Configurability platforms, toolchains, cquery, select(), config transitions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bazel coverage fails on windows because test_wrapper cannot find "collect_coverage.sh"

2 participants