Prototype support for llvm coverage
https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
Closes #5036.
Usage with statically linked tests (works with clang 3.9 or later):
BAZEL_USE_LLVM_NATIVE_COVERAGE=1 GCOV=llvm-profdata-3.9 CC=clang-3.9 /tmp/bazel coverage --instrumentation_filter=src/main/cpp --dynamic_mode=off src/test/cpp:option_processor_test
(LLVM_COV_CMD="llvm-cov-3.9 show -format=html -output-dir=$(pwd)/report/ -instr-profile bazel-out/k8-fastbuild/testlogs/src/test/cpp/option_processor_test/coverage.dat bazel-out/k8-fastbuild/bin/src/test/cpp/option_processor_test" && cd bazel-os-bazel && $LLVM_COV_CMD)
Usage with dynamically linked tests (requires clang 4.0 or later):
BAZEL_USE_LLVM_NATIVE_COVERAGE=1 GCOV=llvm-profdata-4.0 CC=clang-4.0 bazel coverage --instrumentation_filter=src/main/cpp src/test/cpp:option_processor_test
(LLVM_COV_CMD="llvm-cov-4.0 show -format=html -output-dir=$(pwd)/report/ -instr-profile bazel-out/k8-fastbuild/testlogs/src/test/cpp/option_processor_test/coverage.dat bazel-out/k8-fastbuild/bin/src/test/cpp/option_processor_test $(cat bazel-out/k8-fastbuild/bin/src/test/cpp/option_processor_test.runfiles_manifest | cut -d' ' -f 2 | egrep "\.so$" | xargs -n 1 -I xxx echo -n "-object xxx ")" && cd bazel-os-bazel && $LLVM_COV_CMD)
PiperOrigin-RevId: 194357292
diff --git a/tools/cpp/cc_configure.bzl b/tools/cpp/cc_configure.bzl
index cf12126..88c16cc 100644
--- a/tools/cpp/cc_configure.bzl
+++ b/tools/cpp/cc_configure.bzl
@@ -53,6 +53,7 @@
"BAZEL_TARGET_LIBC",
"BAZEL_TARGET_SYSTEM",
"BAZEL_USE_CPP_ONLY_TOOLCHAIN",
+ "BAZEL_USE_LLVM_NATIVE_COVERAGE",
"BAZEL_VC",
"BAZEL_VS",
"CC",
@@ -64,9 +65,9 @@
"GCOV",
"HOMEBREW_RUBY_PATH",
"NO_WHOLE_ARCHIVE_OPTION",
+ "SYSTEMROOT",
"USE_DYNAMIC_CRT",
"USE_MSVC_WRAPPER",
- "SYSTEMROOT",
"VS90COMNTOOLS",
"VS100COMNTOOLS",
"VS110COMNTOOLS",
diff --git a/tools/cpp/unix_cc_configure.bzl b/tools/cpp/unix_cc_configure.bzl
index e57d66d..b53346e 100644
--- a/tools/cpp/unix_cc_configure.bzl
+++ b/tools/cpp/unix_cc_configure.bzl
@@ -343,8 +343,13 @@
return ""
-def _coverage_feature(darwin):
- if darwin:
+def _coverage_feature(repository_ctx, darwin):
+ use_llvm_cov = "1" == get_env_var(
+ repository_ctx,
+ "BAZEL_USE_LLVM_NATIVE_COVERAGE",
+ default="0",
+ enable_warning=False)
+ if darwin or use_llvm_cov:
compile_flags = """flag_group {
flag: '-fprofile-instr-generate'
flag: '-fcoverage-mapping'
@@ -459,7 +464,7 @@
"%{opt_content}": _build_crosstool(opt_content, " "),
"%{dbg_content}": _build_crosstool(dbg_content, " "),
"%{cxx_builtin_include_directory}": "",
- "%{coverage}": _coverage_feature(darwin),
+ "%{coverage}": _coverage_feature(repository_ctx, darwin),
"%{msvc_env_tmp}": "",
"%{msvc_env_path}": "",
"%{msvc_env_include}": "",
diff --git a/tools/test/collect_coverage.sh b/tools/test/collect_coverage.sh
index b9579ca..143696a 100755
--- a/tools/test/collect_coverage.sh
+++ b/tools/test/collect_coverage.sh
@@ -88,6 +88,7 @@
if [[ "$COVERAGE_LEGACY_MODE" ]]; then
export GCOV_PREFIX_STRIP=3
export GCOV_PREFIX="${COVERAGE_DIR}"
+ export LLVM_PROFILE_FILE="${COVERAGE_DIR}/%h-%p-%m.profraw"
fi
cd "$TEST_SRCDIR/$TEST_WORKSPACE"
@@ -107,11 +108,17 @@
cd $ROOT
-# If LCOV_MERGER is not set, use the legacy, awful, C++-only method to convert
-# coverage files.
-# NB: This is here just so that we don't regress. Do not add support for new
-# coverage features here. Implement it instead properly in LcovMerger.
-if [[ "$COVERAGE_LEGACY_MODE" ]]; then
+USES_LLVM_COV=
+if stat --printf='' "${COVERAGE_DIR}"/*.profraw 2>/dev/null; then
+ USES_LLVM_COV=1
+fi
+
+if [[ "$USES_LLVM_COV" ]]; then
+ "${COVERAGE_GCOV_PATH}" merge -output "${COVERAGE_OUTPUT_FILE}" "${COVERAGE_DIR}"/*.profraw
+ exit $TEST_STATUS
+
+# If LCOV_MERGER is not set, use the legacy C++-only method to convert coverage files.
+elif [[ "$COVERAGE_LEGACY_MODE" ]]; then
cat "${COVERAGE_MANIFEST}" | grep ".gcno$" | while read path; do
mkdir -p "${COVERAGE_DIR}/$(dirname ${path})"
cp "${ROOT}/${path}" "${COVERAGE_DIR}/${path}"