-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Description
Description of the problem / feature request:
When a cc_test transitively depends on a cc_binary with linkshared = True, the latter is added to the list of runtime objects to collect coverage for. However, if e.g. the dependency on the shared library goes through a java_binary's resource attribute, the shared library will not be available in the cc_test's runfiles, which causes LLVM-backed coverage collection to not produce any C++ coverage reports for the entire test.
Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.
$ touch WORKSPACE
$ cat << EOF > BUILD
cc_test(
name = "main",
srcs = ["main.cpp"],
data = [":jar"],
)
java_binary(
name = "jar",
resources = [":shared_lib"],
create_executable = False,
)
cc_binary(
name = "shared_lib",
linkshared = True,
)
EOF
$ cat << EOF > main.cpp
#include <iostream>
int main(int argc, char const *argv[])
{
if (argc < 5) {
std::cout << "Hello World!" << std::endl;
}
}
EOF
$ cat << EOF > .bazelrc
# Standard setup of llvm-cov coverage.
coverage --repo_env=CC=clang
coverage --repo_env=BAZEL_USE_LLVM_NATIVE_COVERAGE=1
coverage --repo_env=GCOV=llvm-profdata
coverage --combined_report=lcov
coverage --experimental_use_llvm_covmap
coverage --experimental_generate_llvm_lcov
# Simplifies the reproducer.
coverage --instrument_test_targets
EOF
$ bazel coverage //:main
...
WARNING: There was no coverage found.
INFO: LCOV coverage report is located at /home/fhenneke/.cache/bazel/_bazel_fhenneke/7e105330b418afcd95502d6a63e09121/execroot/__main__/bazel-out/_coverage/_coverage_report.dat
and execpath is bazel-out/_coverage/_coverage_report.dat
Target //:main up-to-date:
bazel-bin/main
INFO: Elapsed time: 0.769s, Critical Path: 0.59s
INFO: 2 processes: 2 linux-sandbox.
INFO: Build completed successfully, 2 total actions
//:main PASSED in 0.4s
Executed 1 out of 1 test: 1 test passes.
INFO: Build completed successfully, 2 total actions
$ cat bazel-out/_coverage/_coverage_report.dat
<empty file>
$ bazel coverage //:main --test_env=VERBOSE_COVERAGE=1 --test_output=streamed -t-
...
+ /usr/bin/llvm-cov export -instr-profile /home/fhenneke/.cache/bazel/_bazel_fhenneke/7e105330b418afcd95502d6a63e09121/sandbox/linux-sandbox/29/execroot/__main__/_coverage/main/test/_cc_coverage.dat.data -format=lcov '-ignore-filename-regex=.*external/.+' -ignore-filename-regex=/tmp/.+ -object /home/fhenneke/.cache/bazel/_bazel_fhenneke/7e105330b418afcd95502d6a63e09121/sandbox/linux-sandbox/29/execroot/__main__/bazel-out/k8-fastbuild/bin/main.runfiles/__main__/main -object /home/fhenneke/.cache/bazel/_bazel_fhenneke/7e105330b418afcd95502d6a63e09121/sandbox/linux-sandbox/29/execroot/__main__/bazel-out/k8-fastbuild/bin/main.runfiles/__main__/libshared_lib.so -object /home/fhenneke/.cache/bazel/_bazel_fhenneke/7e105330b418afcd95502d6a63e09121/sandbox/linux-sandbox/29/execroot/__main__/bazel-out/k8-fastbuild/bin/main.runfiles/__main__/libshared_lib.so
+ sed s#/proc/self/cwd/##
error: /home/fhenneke/.cache/bazel/_bazel_fhenneke/7e105330b418afcd95502d6a63e09121/sandbox/linux-sandbox/29/execroot/__main__/bazel-out/k8-fastbuild/bin/main.runfiles/__main__/main, /home/fhenneke/.cache/bazel/_bazel_fhenneke/7e105330b418afcd95502d6a63e09121/sandbox/linux-sandbox/29/execroot/__main__/bazel-out/k8-fastbuild/bin/main.runfiles/__main__/libshared_lib.so, /home/fhenneke/.cache/bazel/_bazel_fhenneke/7e105330b418afcd95502d6a63e09121/sandbox/linux-sandbox/29/execroot/__main__/bazel-out/k8-fastbuild/bin/main.runfiles/__main__/libshared_lib.so: Failed to load coverage: No such file or directory
...Repeating the commands without the data dependency on :jar shows that coverage is correctly collected in that case.
What operating system are you running Bazel on?
Linux
What's the output of bazel info release?
5.1.0, but also applies to current HEAD
Have you found anything relevant by searching the web?
I created a potential fix at #15118.
Any other information, logs, or outputs that you want to share?
While this particular example is synthetic, the scenario in which this issue causes coverage collection to fail is common: JNI libraries, perhaps even built for multiple architectures, are often wrapped in jars and extracted at runtime (AFAIK, Bazel itself does this). The same problem also applies to other situations, e.g. when an artifact is copied to a different location by an intermediate rule and only included in the runfiles at that new location.