Skip to content

Commit 8d45d41

Browse files
committed
Improve coverage builds and fix coverage reporting
1 parent d19e973 commit 8d45d41

File tree

18 files changed

+87
-55
lines changed

18 files changed

+87
-55
lines changed

.bazelrc

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,15 @@ build:v8-codegen-opt --per_file_copt=external/abseil-cpp@-O2
6868
# zlib and tcmalloc (for Linux) are also CPU-intensive, optimize them too.
6969
build:v8-codegen-opt --per_file_copt=external/tcmalloc@-O2
7070
build:v8-codegen-opt --per_file_copt=external/zlib@-O2
71+
# BoringSSL is CPU-intensive for crypto tests, optimize it too.
72+
build:v8-codegen-opt --per_file_copt=external/boringssl@-O2
73+
# simdutf is used for fast string encoding/decoding
74+
build:v8-codegen-opt --per_file_copt=external/+http+simdutf@-O2
7175
build:v8-codegen-opt-windows --per_file_copt=v8/src@/O2
7276
build:v8-codegen-opt-windows --per_file_copt=external/abseil-cpp@/O2
7377
build:v8-codegen-opt-windows --per_file_copt=external/zlib@/O2
78+
build:v8-codegen-opt-windows --per_file_copt=external/boringssl@/O2
79+
build:v8-codegen-opt-windows --per_file_copt=external/+http+simdutf@/O2
7480

7581
# In Google projects, exceptions are not used as a rule. Disabling them is more consistent with the
7682
# canonical V8 build and improves code size. Paths are adjusted for bzlmod mangling – V8 and ICU use
@@ -415,29 +421,59 @@ build:coverage --test_env=BAZEL_USE_LLVM_NATIVE_COVERAGE=1
415421
# GCOV is used by rules_cc to merge raw profile data (.profraw) into indexed profile data (.profdata)
416422
build:coverage --action_env=GCOV=llvm-profdata
417423
build:coverage --test_env=GCOV=llvm-profdata
424+
# COVERAGE_GCOV_PATH is passed through from the environment. Users must set this to the absolute path
425+
# of llvm-profdata (used by collect_cc_coverage.sh for merging .profraw files).
426+
# Example: export COVERAGE_GCOV_PATH=$(which llvm-profdata)
427+
build:coverage --action_env=COVERAGE_GCOV_PATH
428+
build:coverage --test_env=COVERAGE_GCOV_PATH
418429
# BAZEL_LLVM_COV is used by rules_cc to generate coverage reports from profile data
419430
build:coverage --action_env=BAZEL_LLVM_COV=llvm-cov
420431
build:coverage --test_env=BAZEL_LLVM_COV=llvm-cov
421-
# Enable optimizations to reduce coverage overhead while maintaining good coverage quality
422-
build:coverage --copt=-O2
423-
build:coverage --copt=-DNDEBUG
424-
build:coverage --combined_report=lcov
432+
# LLVM_COV is used by collect_cc_coverage.sh for generating LCOV output
433+
build:coverage --test_env=LLVM_COV=llvm-cov
425434
build:coverage --experimental_use_llvm_covmap
426435
build:coverage --experimental_generate_llvm_lcov
436+
# Ensure that we fetch coverage data from remote cache
427437
build:coverage --experimental_fetch_all_coverage_outputs
438+
build:coverage --experimental_split_coverage_postprocessing
439+
# Allow coverage outputs to be writable for post-processing
440+
build:coverage --experimental_writable_outputs
428441
build:coverage --collect_code_coverage
429-
build:coverage --instrumentation_filter="^//,-//external"
442+
# Only instrument source code, not tests or tools - significantly speeds up coverage builds
443+
build:coverage --instrumentation_filter="^//src/workerd[/:],^//src/rust[/:]"
430444
build:coverage --instrument_test_targets
445+
# Disable coverage instrumentation for external dependencies to speed up compilation.
446+
# Coverage for V8/external code is not useful for our purposes.
447+
# These flags negate -fprofile-instr-generate and -fcoverage-mapping set by rules_cc.
448+
build:coverage --per_file_copt=external/.*@-fno-profile-instr-generate,-fno-coverage-mapping
431449
# KJ uses _exit() by default which bypasses atexit handlers and prevents LLVM profile runtime
432450
# from writing coverage data. KJ_CLEAN_SHUTDOWN forces use of normal exit() instead.
433451
build:coverage --test_env=KJ_CLEAN_SHUTDOWN=1
452+
# Use -O1 for faster compilation - coverage builds don't need heavy optimization
453+
build:coverage --copt=-O1
454+
# External dependencies can use -O2 since they're not instrumented anyway
455+
build:coverage --config=v8-codegen-opt
456+
# Run coverage-related actions locally with sandboxing - remote execution doesn't support LLVM coverage well
457+
build:coverage --strategy=TestRunner=worker,sandboxed,local
458+
build:coverage --strategy=CoverageReport=worker,sandboxed,local
459+
build:coverage --strategy=CoveragePostprocessing=worker,sandboxed,local
460+
# Reduce debug info for faster compilation and smaller binaries
461+
build:coverage --copt=-g1
462+
# Use limited coverage mode for smaller binaries and faster execution (used by Chromium)
463+
build:coverage --copt=-mllvm
464+
build:coverage --copt=-limited-coverage-experimental=true
465+
# Disable gc-sections for faster linking (coverage doesn't need dead code elimination)
466+
build:coverage --linkopt=-Wl,--no-gc-sections
467+
# Disable test result caching to ensure fresh coverage data is generated
468+
coverage --nocache_test_results
434469
coverage --test_tag_filters=-off-by-default,-requires-fuzzilli,-requires-container-engine,-lint,-benchmark,-workerd-benchmark,-no-coverage
435470
# Coverage instrumentation slows down test execution, so extend timeouts
436471
# We disable enormous tests due to the slowdown (CI jobs have a 6h max duration)
437472
coverage --test_size_filters=-enormous
438-
coverage --test_timeout=60,240,240,240
473+
coverage --test_timeout=240,240,240,240
439474
coverage --build_tests_only
440475
coverage --config=coverage
476+
coverage --combined_report=lcov
441477

442478
# This config is defined internally and enabled on many machines.
443479
# Defining it as empty just so these machines can run build commands from the workerd repo

.github/actions/setup-runner/action.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ runs:
2323
libclang-rt-19-dev \
2424
llvm-19
2525
sudo ln -s /usr/bin/llvm-symbolizer-19 /usr/bin/llvm-symbolizer
26+
sudo ln -s /usr/bin/llvm-profdata-19 /usr/bin/llvm-profdata
27+
sudo ln -s /usr/bin/llvm-cov-19 /usr/bin/llvm-cov
2628
echo "build:linux --action_env=CC=/usr/lib/llvm-19/bin/clang" >> .bazelrc
2729
echo "build:linux --host_action_env=CC=/usr/lib/llvm-19/bin/clang" >> .bazelrc
2830
echo "build:linux --linkopt=--ld-path=/usr/lib/llvm-19/bin/ld.lld" >> .bazelrc

.github/workflows/_bazel.yml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,6 @@ jobs:
125125
run: |
126126
bazel --nowindows_enable_symlinks build ${{ inputs.extra_bazel_args }} --config=ci --profile build-win-workaround.bazel-profile.gz --remote_cache=https://bazel:${{ secrets.BAZEL_CACHE_KEY }}@bazel-remote-cache.devprod.cloudflare.dev //src/wpt:wpt-all@tsproject //src/node:node@tsproject //src/pyodide:pyodide_static@tsproject
127127
- name: Bazel build
128-
# timestamps are no longer being added here, the GitHub logs include timestamps (Use
129-
# 'Show timestamps' on the web interface)
130128
run: |
131129
bazel build --remote_cache=https://bazel:${{ secrets.BAZEL_CACHE_KEY }}@bazel-remote-cache.devprod.cloudflare.dev --config=ci ${{ inputs.extra_bazel_args }} //...
132130
- name: Build and load container images
@@ -142,23 +140,20 @@ jobs:
142140
if: inputs.run_tests
143141
run: |
144142
bazel test --remote_cache=https://bazel:${{ secrets.BAZEL_CACHE_KEY }}@bazel-remote-cache.devprod.cloudflare.dev --config=ci ${{ inputs.extra_bazel_args }} ${{ inputs.test_target }}
145-
- name: Setup LLVM tools for coverage
146-
if: inputs.run_coverage
147-
run: |
148-
sudo apt-get update && sudo apt-get install -y llvm
149-
sudo ln -sf /usr/bin/llvm-profdata /usr/local/bin/llvm-profdata
150-
sudo ln -sf /usr/bin/llvm-cov /usr/local/bin/llvm-cov
151143
- name: Bazel coverage
152144
if: inputs.run_coverage
153145
run: |
154-
bazel coverage --remote_cache=https://bazel:${{ secrets.BAZEL_CACHE_KEY }}@bazel-remote-cache.devprod.cloudflare.dev --config=ci --config=coverage ${{ inputs.extra_bazel_args }} ${{ inputs.test_target }}
146+
bazel coverage --remote_cache=https://bazel:${{ secrets.BAZEL_CACHE_KEY }}@bazel-remote-cache.devprod.cloudflare.dev --config=ci ${{ inputs.extra_bazel_args }} ${{ inputs.test_target }}
155147
- name: Upload coverage to Codecov
156148
if: inputs.run_coverage
157149
uses: codecov/codecov-action@v5
158150
with:
159-
files: ./bazel-out/_coverage/_coverage_report.dat
151+
# Use bazel info to get the actual output path, avoiding symlink issues
152+
files: ${{ github.workspace }}/bazel-out/_coverage/_coverage_report.dat
160153
fail_ci_if_error: true
161154
verbose: true
155+
disable_search: true
156+
root_dir: ${{ github.workspace }}
162157
env:
163158
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
164159
- name: Parse headers

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ jobs:
106106
suffix: 'coverage'
107107
# Use ci-linux-common instead of ci-linux to avoid overriding coverage test_tag_filters
108108
# (ci-linux sets test_tag_filters that would include container tests which require docker)
109-
extra_bazel_args: '--config=ci-test --config=ci-linux-common --config=ci-limit-storage'
109+
extra_bazel_args: '--config=ci-test --config=ci-linux-common --config=ci-limit-storage --config=coverage'
110110
upload_test_logs: true
111111
upload_binary: false
112112
build_container_images: false

build/fixtures/BUILD.bazel

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,6 @@
1-
exports_files(["kj_test.sh"])
1+
exports_files([
2+
"kj_test.sh",
3+
"wd_test.sh",
4+
"wd_test_sidecar.sh",
5+
"wd_test_snapshot.sh",
6+
])

build/fixtures/kj_test.sh

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
#!/bin/bash
22
set -euo pipefail
3-
"$@"
3+
4+
if [ -n "${COVERAGE_DIR:-}" ]; then
5+
export LLVM_PROFILE_FILE="$COVERAGE_DIR/%p-%m.profraw"
6+
fi
7+
8+
exec "$@"

build/kj_test.bzl

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,18 +50,20 @@ def kj_test(
5050

5151
sh_test(
5252
name = test_name + "@",
53-
size = size,
5453
srcs = ["//build/fixtures:kj_test.sh"],
55-
data = [cross_alias] + data,
56-
args = ["$(location " + cross_alias + ")"],
54+
args = ["$(location {})".format(cross_alias)],
55+
data = data + [cross_alias],
5756
tags = tags,
57+
size = size,
5858
)
59+
5960
sh_test(
6061
name = test_name + "@all-autogates",
61-
size = size,
62-
env = {"WORKERD_ALL_AUTOGATES": "1"},
6362
srcs = ["//build/fixtures:kj_test.sh"],
64-
data = [cross_alias] + data,
65-
args = ["$(location " + cross_alias + ")"],
66-
tags = tags,
63+
args = ["$(location {})".format(cross_alias)],
64+
data = data + [cross_alias],
65+
env = {"WORKERD_ALL_AUTOGATES": "1"},
66+
# Tag with no-coverage to reduce coverage CI time
67+
tags = tags + ["no-coverage"],
68+
size = size,
6769
)

build/wd_cc_binary.bzl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,5 @@ def wd_cc_binary(
4747
"@//build/config:prebuilt_binaries_arm64": "@//:bin.arm64/tmp/{}/{}.aarch64-linux-gnu".format(pkg, prebuilt_binary_name),
4848
"//conditions:default": name,
4949
}),
50-
# Propagate InstrumentedFilesInfo through the alias for coverage support
5150
testonly = kwargs.get("testonly", False),
5251
)

build/wd_rust_binary.bzl

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,6 @@ def wd_rust_binary(
5454
visibility = visibility,
5555
data = data,
5656
proc_macro_deps = proc_macro_deps,
57-
experimental_use_cc_common_link = select({
58-
"@platforms//os:windows": 0,
59-
"//conditions:default": 1,
60-
}),
6157
target_compatible_with = select({
6258
"@//build/config:no_build": ["@platforms//:incompatible"],
6359
"//conditions:default": [],
@@ -74,10 +70,6 @@ def wd_rust_binary(
7470
# our tests are usually very heavy and do not support concurrent invocation
7571
"RUST_TEST_THREADS": "1",
7672
},
77-
experimental_use_cc_common_link = select({
78-
"@platforms//os:windows": 0,
79-
"//conditions:default": 1,
80-
}),
8173
target_compatible_with = select({
8274
"@//build/config:no_build": ["@platforms//:incompatible"],
8375
"//conditions:default": [],

build/wd_rust_crate.bzl

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,6 @@ def wd_rust_crate(
148148
crate_features = crate_features,
149149
deps = test_deps,
150150
proc_macro_deps = test_proc_macro_deps,
151-
experimental_use_cc_common_link = select({
152-
"@platforms//os:windows": 0,
153-
"//conditions:default": 1,
154-
}),
155151
)
156152

157153
if len(proc_macro_deps) + len(cxx_bridge_srcs) > 0:

0 commit comments

Comments
 (0)