Skip to content

coverage: QNX on-target coverage through the score_coverage gcov backend - #626

Merged
4og merged 28 commits into
mainfrom
dcalavrezo_qnx_coverage
Oct 12, 2026
Merged

4og merged 28 commits into
mainfrom
dcalavrezo_qnx_coverage

Conversation

@dcalavrezo-qorix

@dcalavrezo-qorix dcalavrezo-qorix commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Uses the score_coverage 0.4.0 registry release (release notes), which adds the gcov backend for QNX on-target coverage (0.3.0), the required instrumentation filter (0.3.1) and the per-platform scope (0.4.0).

What

QNX on-target coverage for the C++ tests, through the gcov backend of score_coverage:

  • tests run in QEMU via score_qnx_unit_tests (run_under_qnx), which brings the .gcda counters back;
  • Bazel's own per-test collector turns them into LCOV;
  • score_coverage's gcov reporter applies the coverage scope, adds 0 % baselines from the .gcno notes, and produces the same report archive as the Linux run (HTML via gcovr, LCOV, unmapped_files.txt, justifications, gate).

Changes:

  • MODULE.bazel: score_coverage 0.2.0 → 0.4.0;
  • tools/coverage/BUILD: gcov_reporter_wrapper (backend = "gcov", QCC's gcov), tagged manual so bazel build //... on a Linux host does not fetch the QNX SDP;
  • tools/coverage/coverage.bazelrc: coverage:qnx_cov config (QNX build config, run_under_qnx, Bazel's lcov_merger, gcov reporter, --instrument_test_targets, C++ only);
  • .github/workflows/coverage_report_qnx.yml (new, the pattern of build_qnx.yml): pull_request_target with the workflow-approval environment gate for fork PRs; job qnx-coverage-report (QNX SDP + QEMU/KVM setup, bazel coverage --config=qnx_cov, generate_coverage_html --platform qnx), artifact baselibs_cpp_coverage_report_qnx. coverage_report.yml keeps the Linux job. Because pull_request_target uses the base branch's definition, the new workflow runs on this PR only through a TEMPORARY push trigger for the branch, removed before merge.

The Linux job is unchanged.

Validation

The QNX job produced a complete report on this branch: 615 files in the index, every link resolves, 81.6 % raw line coverage. unmapped_files.txt lists 50 Rust sources as not-instrumented (rustc emits no gcov counters; they are measured by the Linux run), 128 files as no-data (mostly headers vendored from external repositories, which Bazel's collector drops on this backend), 107 declaration-only headers and 78 compiled-without-code units, as on Linux.

Per file, the QNX numbers differ from the Linux report of the same tree by design: gcov counts fewer lines (no unused inline functions, no closing braces), so totals differ while no file is missing. The two reports are compared per file, not merged.

Tracking: eclipse-score/tooling#427 (track 1).

Update: bumped to 0.3.1, which requires the explicit --instrumentation_filter=^//score[/:] this branch sets. Bazel guesses the filter from the packages of the test targets; libraries tested from a test subpackage were otherwise compiled without counters or, on QNX, lost their counters (score/os showed 13 % instead of 80 % in the first QNX report). See the 0.3.1 release notes.

Scope per platform (eclipse-score/coverage_tool#23, fixed in #24). coverage_scope_qnx names the QNX platform; Linux-only roots (incl. all Rust) and QNX-only roots sit behind a select(). Validated on run 37473583990: 56 score/os/qnx files in the QNX report (0 before), no score/os/linux file (16 at 0 % before), 89.3 % lines over 684 files. MODULE.bazel now uses the 0.4.0 release, which contains #24 (the temporary git_override is gone).

@github-actions github-actions Bot added bazel Bazel and Starlark build files ci CI related changes labels Sep 28, 2026
QCC is GCC-based, so QNX coverage uses gcov counters: the tests run in
QEMU through score_qnx_unit_tests (run_under_qnx), which brings the
.gcda files back; Bazel's own per-test collector turns them into LCOV;
score_coverage's gcov reporter (eclipse-score/coverage_tool PR #10)
produces the same report as the Linux run.

- tools/coverage/BUILD: gcov_reporter_wrapper with backend = "gcov"
  and the QCC package's gcov.
- coverage.bazelrc: coverage:qnx_cov on top of bl-x86_64-qnx (run_under,
  C++ tests only, Bazel's lcov_merger, the gcov reporter,
  --instrument_test_targets).
- coverage_report_qnx.yml: the QNX build workflow's setup steps (SDP,
  credential helper, QEMU, KVM) followed by bazel coverage and
  generate_coverage_html --platform qnx; the artifact is uploaded as
  baselibs_cpp_coverage_report_qnx.

VALIDATION ONLY: MODULE.bazel carries a git_override to the
coverage_tool branch; it is replaced by the 0.3.0 registry release once
that is published. Rust sources are listed as not-instrumented in the
QNX report and measured by the Linux run.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

Documentation preview for this pull request is available at:
pr-626: https://eclipse-score.github.io/baselibs/pr-626/

A wildcard build on a Linux host without QNX credentials must not fetch
the QNX SDP package the reporter depends on; --coverage_report_generator
names the target explicitly.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
@dcalavrezo-qorix

Copy link
Copy Markdown
Contributor Author

First real QNX run, job https://github.com/eclipse-score/baselibs/actions/runs/36388596870/job/108819220167 (bl-x86_64-qnx, 278 tests in QEMU): artifact baselibs_cpp_coverage_report_qnx has 615 files, 616 index links all opening, raw line coverage 81.59 % (gcov semantics; the Linux/LLVM report of the same tree is 87.76 %). unmapped_files.txt: 50 Rust sources not-instrumented, 128 no-data (the vendored flatbuffers headers among them, as documented for this backend), 107 declaration-only, 78 compiled-without-code. Baseline from 668 gcno files covers 160 files no test executed.

The gcov backend for QNX on-target coverage is released. Pin the
release commit until the registry entry (bazel_registry PR #519) is
merged, then drop the override.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
The release is in the S-CORE Bazel registry; drop the temporary
git_override that pinned the release commit.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Bazel derives the default --instrumentation_filter from the packages of
the test targets and strips only a trailing /tests to reach the code
under test. Our tests live in test/ subpackages, so libraries such as
//score/os were outside the guessed filter; the gcov collector then
dropped their counters and the QNX report showed them at 0 % (13 % for
score/os against 80 % on Linux). Instrument everything under //score.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
0.3.1 requires the explicit --instrumentation_filter this branch already
sets, and warns when a report shows the pattern of a library tested from
a test/ subpackage without data.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
@dcalavrezo-qorix dcalavrezo-qorix changed the title coverage: QNX on-target coverage through the score_coverage gcov backend coverage: QNX on-target coverage through the score_coverage gcov backend Sep 29, 2026
@dcalavrezo-qorix

Copy link
Copy Markdown
Contributor Author

@4og @fbaeuerle could you review this one, please? It moves the coverage pipeline to the qualified score_coverage 0.3.1 (rollout tracked in eclipse-score/score#3258). The before/after comparison of the coverage data is in the description and CI is green. This one also adds QNX on-target coverage; the QNX job's report (649 files, 92 % lines) is linked in the description. Thanks!

Comment thread .github/workflows/coverage_report.yml Outdated
# in QEMU through score_qnx_unit_tests, which brings the .gcda counters
# back. Same-repository branches only: the QNX secrets are not exposed to
# forks on pull_request events.
qnx-coverage-report:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The generated HTML report completely misses qnx-only targets from this folder https://github.com/eclipse-score/baselibs/tree/main/score/os/qnx
Instead it includes files from score/os/linux which have zero coverage.

I'd expect that both linux and qnx coverage tools produce data only for the code that can be compiled on those platform.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You are right, and thanks for spotting it: this is a tool limitation, not a baselibs problem. Bazel builds --coverage_report_generator in the exec configuration (BaseRuleClasses.coverageReportGeneratorAttribute with ExecutionTransitionFactory), so the scope aspect resolves every select() for the host platform. On the QNX run that means: the Linux variants are in the allowlist and show 0 % from the host baseline, the QNX variants are not in the allowlist at all. The allowlist is identical for both jobs (978 files). The platform-independent code, the vast majority, is measured correctly from the real QNX run.

Tracked as eclipse-score/coverage_tool#23 with the fix: an explicit target platform on the scope (transition on --platforms), one scope per platform, planned as 0.4.0. Two ways to handle this PR: merge now with the limitation stated in the description and the manual, and the QNX report gets the platform-specific files right with 0.4.0; or hold the PR until 0.4.0. Your call; I lean towards merging, since the Linux report and the whole pipeline are unaffected and the QNX job already gives the shared code.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Fixed in the tool (eclipse-score/coverage_tool#24, pinned here temporarily) and validated on this branch, run 37473583990:

QNX before QNX now Linux
score/os/qnx/ files in the report 0 56 (7 with data, the rest 0 % or declaration-only) 0
score/os/linux/ files in the report 16 at 0 % 0 15
allowlist 978 (identical to Linux) 976 (QNX-specific) 978
whole report 92.2 % lines, 649 files 89.3 % lines, 684 files 88.6 %, 655 files

The scope is now evaluated for the run's platform: coverage_scope_qnx names the QNX platform, and the Linux-only / QNX-only roots sit behind a select(). Rust roots are Linux-only as well (crate_universe marks the crates incompatible with QNX, and gcov cannot measure Rust). Three tool-side fixes came out of the validation: the platform scope must be manual, an incompatible root silently skips every test (now documented with the diagnostic), and the select() in the scope's deps needed the transition on the rule itself. The git override is replaced by the 0.4.0 release before merge.

Comment thread .github/workflows/coverage_report.yml Outdated
# back. Same-repository branches only: the QNX secrets are not exposed to
# forks on pull_request events.
qnx-coverage-report:
name: Coverage bl-x86_64-qnx (gcov, on target)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The bl-x86_64-qnx got recently renamed to score-qnx-x86_64

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done in f9349a0 (branch also merged with main).

Comment thread .github/workflows/coverage_report.yml Outdated
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
runs-on: ubuntu-24.04
steps:
- uses: eclipse-score/more-disk-space@3fac5780033e636b114cf69e891dc19d640855c2 # v1.1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The part below looks identical to https://github.com/eclipse-score/cicd-workflows/blob/main/.github/workflows/qnx-build.yml Can it be somehow reused?

Additionally, this job will be failing in forks due to pull_request trigger

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

It is the same setup, yes. The reusable qnx-build.yml runs bazel build and optionally bazel test; it has no hook for bazel coverage plus the report step, so I could not call it as is. Two options: extend cicd-workflows with a bazel-command input (build/test/coverage) and a post-step hook, then switch this job over; or keep the inline steps until that exists. I would do the extension as a follow-up rather than block this PR, if that is fine with you.

Forks: the job already carries if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository, so it is skipped for fork PRs instead of failing; same-repository branches get the secrets.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Changed to the pattern of build_qnx.yml: the QNX coverage job moved to its own workflow, coverage_report_qnx.yml, on pull_request_target with the workflow-approval environment gate for fork PRs (same-repository PRs, pushes to main and the merge queue run directly), and it checks out the PR head explicitly. coverage_report.yml keeps the Linux job only. Reusing qnx-build.yml directly is still not possible because it has no coverage mode; the step list here is the one it uses plus the two coverage steps, and I'd propose a bazel-command input there as a follow-up so both repos can share it.

Note on validation: pull_request_target runs the base branch's workflow definition, so the new file cannot run on this PR before it is merged; the branch carries a TEMPORARY push trigger for its own name to exercise it, which I remove before merge.

Comment thread tools/coverage/coverage.bazelrc Outdated
# into LCOV; score_coverage's gcov reporter produces the report. Rust sources
# are listed as not-instrumented here and measured by the Linux run.
# ---------------------------------------------------------------------------
coverage:qnx_cov --config=bl-x86_64-qnx

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
coverage:qnx_cov --config=bl-x86_64-qnx
coverage:qnx_cov --config=score-qnx-x86_64

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Applied in f9349a0.

main renamed bl-x86_64-qnx to score-qnx-x86_64. The QNX job needs the SDP
secrets, which forks do not get, so it runs for branches of this
repository only.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Scope per platform: coverage_scope_qnx names the QNX platform and the
gcov reporter uses it; the Linux-only and QNX-only roots sit behind a
select(). score_coverage pinned to the PR commit until 0.4.0 is
released.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
@dcalavrezo-qorix
dcalavrezo-qorix force-pushed the dcalavrezo_qnx_coverage branch from b9268f4 to c9428d0 Compare October 6, 2026 12:32
Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
@dcalavrezo-qorix
dcalavrezo-qorix force-pushed the dcalavrezo_qnx_coverage branch from c9428d0 to a1a29eb Compare October 6, 2026 12:34
Wildcard builds on a Linux host analysed coverage_scope_qnx for the QNX
platform without the QNX toolchains registered and failed toolchain
resolution; the gcov reporter carries the same tag for the same reason.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Bazel's dependency chain for the incompatible QNX scope ended at the
cxx.rs crate foldhash, which crate_universe marks incompatible with every
platform outside rules_rust's triple list (x86_64-pc-nto-qnx800 is not
in it). One incompatible root made the scope, the report generator and
therefore every QNX test incompatible: 284 tests skipped, no report.
Rust roots and the C++ wrappers linking Rust now live in the Linux-only
list; the gcov backend cannot measure Rust anyway. Diagnostic step
removed.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Analysed locally with a stand-in cc toolchain for the QNX platform:
//score/os/utils:tcp_keep_alive requires the sdp_7.1.0 constraint and
made the scope incompatible with the 8.0 platform; five QNX libraries
were not visible to //tools/coverage. Diagnostic step removed.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
@github-actions github-actions Bot added the comp-osal Related to score/os component label Oct 6, 2026
Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Same pattern as build_qnx.yml: the QNX SDP secrets are needed, so the
job moves to its own workflow on pull_request_target. Fork PRs run it
after a maintainer approves through the workflow-approval environment;
same-repository PRs, pushes to main and the merge queue run directly.
The PR head is checked out explicitly. coverage_report.yml keeps the
Linux job only.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
…the QNX workflow

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Validated on the branch (run 37595023830): approval skipped for the
same-repository branch, 278 tests executed, report produced.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
The overlapping-range failure was fixed on main (6bba68b) and the test
is enabled in the QNX x86_64 job (b720a2e); drop it from the coverage
run's exclusions.

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>

# Conflicts:
#	tools/coverage/BUILD
Replaces the temporary git_override on the coverage_tool#24 commit with
the registry release that contains it (scope evaluated for the run's
platform).

Signed-off-by: Dan Calavrezo <195309321+dcalavrezo-qorix@users.noreply.github.com>
@github-project-automation github-project-automation Bot moved this from In Progress to On Hold in BAS - Baselibs FT Oct 12, 2026
@4og
4og added this pull request to the merge queue Oct 12, 2026
Merged via the queue into main with commit e828190 Oct 12, 2026
27 checks passed
@4og
4og deleted the dcalavrezo_qnx_coverage branch October 12, 2026 15:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bazel Bazel and Starlark build files ci CI related changes comp-osal Related to score/os component

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants