From 89789e6f45fc0a0f6f720b0ed50f2bbd9237ac94 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 5 Feb 2026 10:43:26 -0700 Subject: [PATCH 01/79] Enable coverage options for project in superbuild --- .github/workflows/therock-ci-linux.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index d498e94d861e..fbeb0c7b3cec 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -102,6 +102,14 @@ jobs: extra_cmake_options: "-DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" BUILD_DIR: build run: | + set -euo pipefail + EXTRA_OPTS="-DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" + PROJECT_KEY="$(echo "${{inputs.project_to_test }}" | tr '[:lower:]' '[:upper:]')" + if [[ "${{ inputs.test_type }}" == "coverage" ]]; then + EXTRA_OPTS="${EXTRA_OPTS} -D${PROJECT_KEY_UPPER}_ENABLE_COVERAGE=ON" + echo "Coverage enabled for ${PROJECT_KEY_UPPER}: ${EXTRA_OPTS}" + fi + export extra_cmake_options="${EXTRA_OPTS}" python3 TheRock/build_tools/github_actions/build_configure.py - name: Build therock-archives and therock-dist From b7559cc7416ef6bbbab0e1d51d14e75bd9809429 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 9 Feb 2026 14:28:09 -0700 Subject: [PATCH 02/79] Add an example code coverage work flow --- .github/workflows/therock-ci-linux.yml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index fbeb0c7b3cec..a089f66a1a7c 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -161,6 +161,7 @@ jobs: therock-test-linux: name: Test (${{ inputs.amdgpu_families }}) + if: ${{ inputs.test_type != 'coverage' }} needs: [therock-build-linux] # TODO(TheRock#3288): Re-enable gfx950-dcgpu runners once we get more capacity if: ${{ inputs.amdgpu_families != 'gfx950-dcgpu' }} @@ -172,3 +173,20 @@ jobs: platform: "linux" test_type: ${{ inputs.test_type }} secrets: inherit + + therock-test-coverage: + name: Code Coverage + if: ${{ inputs.test_type != 'coverage' }} + needs: [therock-build-linux] + - name: Run project coverage + shell: bash + run: | + BUILD_DIR="/build/TheRock/rocm-libraries/${{ inputs.project_to_test }}/build" + cmake --build "${BUILD_DIR}" --target coverage || make -C "${BUILD_DIR}" coverage + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + files: ${{ env.REPORTS }} + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + secrets: inherit From bb786316261acd1de7b3776d5f089ce9a11d2979 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 9 Feb 2026 14:40:09 -0700 Subject: [PATCH 03/79] Add coverage step in CI --- .github/workflows/therock-ci.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/therock-ci.yml b/.github/workflows/therock-ci.yml index 3eca8b89cda8..324f77bad253 100644 --- a/.github/workflows/therock-ci.yml +++ b/.github/workflows/therock-ci.yml @@ -178,6 +178,28 @@ jobs: test_runs_on: ${{ matrix.target_bundle.test_machine }} build_runs_on: ${{ needs.setup.outputs.windows_build_runs_on }} + therock-ci-coverage: + name: Coverage (${{ matrix.projects.project_to_test }} | ${{ matrix.target_bundle.amdgpu_family }}) + permissions: + contents: read + id-token: write + needs: setup + if: ${{ needs.setup.outputs.linux_projects != '[]' }} + strategy: + fail-fast: false + matrix: + projects: ${{ fromJSON(needs.setup.outputs.linux_projects) }} + target_bundle: ${{ fromJSON(needs.setup.outputs.linux_package_targets) }} + uses: ./.github/workflows/therock-ci-linux.yml + secrets: inherit + with: + cmake_options: ${{ matrix.projects.cmake_options }} + project_to_test: ${{ matrix.projects.project_to_test }} + test_type: coverage + amdgpu_families: ${{ matrix.target_bundle.amdgpu_family }} + test_runs_on: ${{ matrix.target_bundle.test_machine }} + + therock_ci_summary: name: TheRock CI Summary if: always() @@ -185,6 +207,7 @@ jobs: - setup - therock-ci-linux - therock-ci-windows + - therock-ci-coverage runs-on: ubuntu-24.04 steps: - name: Output failed jobs From 905ff4d8be4100bfa103aa9da8d40e628b948bf9 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 9 Feb 2026 15:01:04 -0700 Subject: [PATCH 04/79] remove whitespace --- .github/workflows/therock-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/therock-ci.yml b/.github/workflows/therock-ci.yml index 324f77bad253..8ef8117aa409 100644 --- a/.github/workflows/therock-ci.yml +++ b/.github/workflows/therock-ci.yml @@ -199,7 +199,6 @@ jobs: amdgpu_families: ${{ matrix.target_bundle.amdgpu_family }} test_runs_on: ${{ matrix.target_bundle.test_machine }} - therock_ci_summary: name: TheRock CI Summary if: always() From ebec3d2dcceade35ad54aa194b04fb5dae033fcb Mon Sep 17 00:00:00 2001 From: John Robbins Date: Fri, 6 Mar 2026 13:44:40 -0700 Subject: [PATCH 05/79] Rename back to projects_to_test (plural) --- .github/workflows/therock-ci-linux.yml | 5 +++-- .github/workflows/therock-ci.yml | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index a089f66a1a7c..9599d97ccb57 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -104,7 +104,7 @@ jobs: run: | set -euo pipefail EXTRA_OPTS="-DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" - PROJECT_KEY="$(echo "${{inputs.project_to_test }}" | tr '[:lower:]' '[:upper:]')" + PROJECT_KEY="$(echo "${{inputs.projects_to_test }}" | tr '[:lower:]' '[:upper:]')" if [[ "${{ inputs.test_type }}" == "coverage" ]]; then EXTRA_OPTS="${EXTRA_OPTS} -D${PROJECT_KEY_UPPER}_ENABLE_COVERAGE=ON" echo "Coverage enabled for ${PROJECT_KEY_UPPER}: ${EXTRA_OPTS}" @@ -181,8 +181,9 @@ jobs: - name: Run project coverage shell: bash run: | - BUILD_DIR="/build/TheRock/rocm-libraries/${{ inputs.project_to_test }}/build" + BUILD_DIR="/build/TheRock/rocm-libraries/${{ inputs.projects_to_test }}/build" cmake --build "${BUILD_DIR}" --target coverage || make -C "${BUILD_DIR}" coverage + - name: Upload coverage to Codecov uses: codecov/codecov-action@v4 with: diff --git a/.github/workflows/therock-ci.yml b/.github/workflows/therock-ci.yml index 8ef8117aa409..ac8418a75c53 100644 --- a/.github/workflows/therock-ci.yml +++ b/.github/workflows/therock-ci.yml @@ -179,7 +179,7 @@ jobs: build_runs_on: ${{ needs.setup.outputs.windows_build_runs_on }} therock-ci-coverage: - name: Coverage (${{ matrix.projects.project_to_test }} | ${{ matrix.target_bundle.amdgpu_family }}) + name: Coverage (${{ matrix.projects.projects_to_test }} | ${{ matrix.target_bundle.amdgpu_family }}) permissions: contents: read id-token: write @@ -194,7 +194,7 @@ jobs: secrets: inherit with: cmake_options: ${{ matrix.projects.cmake_options }} - project_to_test: ${{ matrix.projects.project_to_test }} + projects_to_test: ${{ matrix.projects.projects_to_test }} test_type: coverage amdgpu_families: ${{ matrix.target_bundle.amdgpu_family }} test_runs_on: ${{ matrix.target_bundle.test_machine }} From 5c0ece0233f527b016d6be4e234d79889be8bcbf Mon Sep 17 00:00:00 2001 From: John Robbins Date: Fri, 6 Mar 2026 15:43:57 -0700 Subject: [PATCH 06/79] fix coverage-test syntax --- .github/workflows/therock-ci-linux.yml | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index 9599d97ccb57..e3b167ffb609 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -161,10 +161,8 @@ jobs: therock-test-linux: name: Test (${{ inputs.amdgpu_families }}) - if: ${{ inputs.test_type != 'coverage' }} + if: ${{ inputs.test_type != 'coverage' && inputs.amdgpu_families != 'gfx950-dcgpu' }} needs: [therock-build-linux] - # TODO(TheRock#3288): Re-enable gfx950-dcgpu runners once we get more capacity - if: ${{ inputs.amdgpu_families != 'gfx950-dcgpu' }} uses: ./.github/workflows/therock-test-packages.yml with: projects_to_test: ${{ inputs.projects_to_test }} @@ -176,13 +174,9 @@ jobs: therock-test-coverage: name: Code Coverage - if: ${{ inputs.test_type != 'coverage' }} + if: ${{ inputs.test_type == 'coverage' }} needs: [therock-build-linux] - - name: Run project coverage - shell: bash - run: | - BUILD_DIR="/build/TheRock/rocm-libraries/${{ inputs.projects_to_test }}/build" - cmake --build "${BUILD_DIR}" --target coverage || make -C "${BUILD_DIR}" coverage + runs-on: ubuntu-latest - name: Upload coverage to Codecov uses: codecov/codecov-action@v4 @@ -191,3 +185,16 @@ jobs: fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} secrets: inherit + steps: + - name: Run project coverage + shell: bash + run: | + BUILD_DIR="/build/TheRock/rocm-libraries/${{ inputs.projects_to_test }}/build" + cmake --build "${BUILD_DIR}" --target coverage || make -C "${BUILD_DIR}" coverage + + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v4 + with: + files: ${{ env.REPORTS }} + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} From 4ade6c6324bcb0613f49acd4ce96c9d9a0651a45 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Fri, 6 Mar 2026 16:39:16 -0700 Subject: [PATCH 07/79] Fix keyname --- .github/workflows/therock-ci-linux.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index e3b167ffb609..b3256a40f9d6 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -106,8 +106,8 @@ jobs: EXTRA_OPTS="-DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" PROJECT_KEY="$(echo "${{inputs.projects_to_test }}" | tr '[:lower:]' '[:upper:]')" if [[ "${{ inputs.test_type }}" == "coverage" ]]; then - EXTRA_OPTS="${EXTRA_OPTS} -D${PROJECT_KEY_UPPER}_ENABLE_COVERAGE=ON" - echo "Coverage enabled for ${PROJECT_KEY_UPPER}: ${EXTRA_OPTS}" + EXTRA_OPTS="${EXTRA_OPTS} -D${PROJECT_KEY}_ENABLE_COVERAGE=ON" + echo "Coverage enabled for ${PROJECT_KEY}: ${EXTRA_OPTS}" fi export extra_cmake_options="${EXTRA_OPTS}" python3 TheRock/build_tools/github_actions/build_configure.py @@ -174,7 +174,7 @@ jobs: therock-test-coverage: name: Code Coverage - if: ${{ inputs.test_type == 'coverage' }} + if: ${{ inputs.test_type == 'coverage' && inputs.amdgpu_families != 'gfx950-dcgpu'}} needs: [therock-build-linux] runs-on: ubuntu-latest From 5b538ad887e5b329f7605e95edd686840c4674d4 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 10:02:12 -0600 Subject: [PATCH 08/79] [codecov] fix codecov flow --- .github/workflows/therock-ci-linux.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index b3256a40f9d6..8e47cd588054 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -177,14 +177,6 @@ jobs: if: ${{ inputs.test_type == 'coverage' && inputs.amdgpu_families != 'gfx950-dcgpu'}} needs: [therock-build-linux] runs-on: ubuntu-latest - - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - with: - files: ${{ env.REPORTS }} - fail_ci_if_error: true - token: ${{ secrets.CODECOV_TOKEN }} - secrets: inherit steps: - name: Run project coverage shell: bash From ba9a805aa8286478f122237458c3bb18647ab7de Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 10:05:00 -0600 Subject: [PATCH 09/79] [hipdnn] remove redundant -fcoverage-mapping from link options --- projects/hipdnn/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/hipdnn/CMakeLists.txt b/projects/hipdnn/CMakeLists.txt index 4a6cfb8635f6..8df9fb960aa0 100644 --- a/projects/hipdnn/CMakeLists.txt +++ b/projects/hipdnn/CMakeLists.txt @@ -208,7 +208,7 @@ set(EXTRA_LINK_OPTIONS) if(HIPDNN_ENABLE_COVERAGE) message(VERBOSE "Enabling compile flags for coverage-mapping") list(PREPEND EXTRA_COMPILE_OPTIONS -fprofile-instr-generate -fcoverage-mapping) - list(PREPEND EXTRA_LINK_OPTIONS -fprofile-instr-generate -fcoverage-mapping) + list(PREPEND EXTRA_LINK_OPTIONS -fprofile-instr-generate) endif() list( From e0333a79d1dcf626e9800e4d214c66926149c0ef Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 10:36:10 -0600 Subject: [PATCH 10/79] add a script to configure coverage jobs The current therock_configure_ci.py doesn't have a clean way to only configure the project that has changed, and not other components that the changed component has been grouped together with. For code coverage reports, it does not make sense to even test downstream components. --- .github/scripts/therock_configure_coverage.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 .github/scripts/therock_configure_coverage.py diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py new file mode 100644 index 000000000000..7b57b08ff024 --- /dev/null +++ b/.github/scripts/therock_configure_coverage.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +import json +import logging +import os +from pathlib import Path + +from therock_matrix import collect_projects_to_run +from pr_detect_changed_subtrees import get_valid_prefixes, find_matched_subtrees +from config_loader import load_repo_config +from therock_configure_ci import get_modified_paths # reuse existing helper + +logging.basicConfig(level=logging.INFO) +SCRIPT_DIR = Path(__file__).resolve().parent + +def get_changed_subtrees_only(): + repo_config_path = SCRIPT_DIR / ".." / "repos-config.json" + config = load_repo_config(str(repo_config_path)) + valid_prefixes = get_valid_prefixes(config) + + base_ref = os.environ.get("BASE_REF", "HEAD^") + modified_paths = get_modified_paths(base_ref) + + matched_subtrees = find_matched_subtrees(modified_paths, valid_prefixes) + return matched_subtrees + +def main(): + subtrees = get_changed_subtrees_only() + projects = collect_projects_to_run(subtrees) + + output = { + "linux_projects_coverage": json.dumps(projects), + } + github_output = os.environ.get("GITHUB_OUTPUT") + if github_output: + with open(github_output, "a") as f: + for k, v in output.items(): + f.write(f"{k}={v}\n") + else: + logging.warning("GITHUB_OUTPUT not set; printing to stdout instead") + print(json.dumps(output)) + +if __name__ == "__main__": + main() + From c85cf3b43f278f525952b692855edcd553ee30fa Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 11:32:23 -0600 Subject: [PATCH 11/79] integrate therock_configure_coverage.py with coverage workflow --- .github/workflows/therock-ci.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci.yml b/.github/workflows/therock-ci.yml index ac8418a75c53..ae70c67ac341 100644 --- a/.github/workflows/therock-ci.yml +++ b/.github/workflows/therock-ci.yml @@ -50,6 +50,7 @@ jobs: test_type: ${{ steps.linux_projects.outputs.test_type }} linux_package_targets: ${{ steps.configure_linux.outputs.package_targets }} windows_package_targets: ${{ steps.configure_windows.outputs.package_targets }} + linux_projects_coverage: ${{ steps.linux_projects_coverage.outputs.linux_projects_coverage }} steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -97,6 +98,13 @@ jobs: run: | python .github/scripts/therock_configure_ci.py + - name: Determine Linux projects for coverage (changed subtrees only) + id: linux_projects_coverage + env: + PLATFORM: "linux" + run: | + python .github/scripts/therock_configure_coverage.py + - name: Determine Windows projects to run id: windows_projects env: @@ -184,11 +192,12 @@ jobs: contents: read id-token: write needs: setup - if: ${{ needs.setup.outputs.linux_projects != '[]' }} + # Only run if there are coverage projects (changed subtrees) + if: ${{ needs.setup.outputs.linux_projects_coverage != '[]' }} strategy: fail-fast: false matrix: - projects: ${{ fromJSON(needs.setup.outputs.linux_projects) }} + projects: ${{ fromJSON(needs.setup.outputs.linux_projects_coverage) }} target_bundle: ${{ fromJSON(needs.setup.outputs.linux_package_targets) }} uses: ./.github/workflows/therock-ci-linux.yml secrets: inherit From 5d8ce940bf659c46f8d295839306ebb465cdf73c Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 12:37:31 -0600 Subject: [PATCH 12/79] produce the project name for coverage --- .github/scripts/therock_configure_coverage.py | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 7b57b08ff024..6927cb64aadf 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -4,7 +4,7 @@ import os from pathlib import Path -from therock_matrix import collect_projects_to_run +from therock_matrix import collect_projects_to_run, subtree_to_project_map from pr_detect_changed_subtrees import get_valid_prefixes, find_matched_subtrees from config_loader import load_repo_config from therock_configure_ci import get_modified_paths # reuse existing helper @@ -12,6 +12,7 @@ logging.basicConfig(level=logging.INFO) SCRIPT_DIR = Path(__file__).resolve().parent + def get_changed_subtrees_only(): repo_config_path = SCRIPT_DIR / ".." / "repos-config.json" config = load_repo_config(str(repo_config_path)) @@ -23,10 +24,31 @@ def get_changed_subtrees_only(): matched_subtrees = find_matched_subtrees(modified_paths, valid_prefixes) return matched_subtrees + def main(): subtrees = get_changed_subtrees_only() + + changed_project_keys = set() + for subtree in subtrees: + if subtree in subtree_to_project_map: + changed_project_keys.add(subtree_to_project_map[subtree]) + projects = collect_projects_to_run(subtrees) + for proj in projects: + pts_list = [p for p in proj.get("projects_to_test", "").split(",") if p] + + #TODO: We don't want a default + primary = pts_list[0] if pts_list else "" + + #TODO: There's a better way than iterating and comparing to projects_to_test + for p in pts_list: + if p in changed_project_keys: + primary = p + break + + proj["project_name"] = primary.upper() + output = { "linux_projects_coverage": json.dumps(projects), } @@ -39,6 +61,7 @@ def main(): logging.warning("GITHUB_OUTPUT not set; printing to stdout instead") print(json.dumps(output)) + if __name__ == "__main__": main() From 9de4309c29e968c278b66d8b9623f2e168854e37 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 12:46:30 -0600 Subject: [PATCH 13/79] configure project separately for code coverage --- .github/workflows/therock-ci-linux.yml | 22 ++++++++++++++-------- .github/workflows/therock-ci.yml | 2 +- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index 8e47cd588054..ddeec1a9ee59 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -13,6 +13,8 @@ on: type: string projects_to_test: type: string + project_name: + type: string test_type: type: string amdgpu_families: @@ -22,6 +24,7 @@ on: build_runs_on: type: string + permissions: contents: read @@ -96,20 +99,23 @@ jobs: ./TheRock/build_tools/fetch_sources.py --jobs 12 --no-include-rocm-libraries --no-include-ml-frameworks ${{ contains(inputs.cmake_options, 'THEROCK_ENABLE_IREE_LIBS=ON') && '--include-iree-libs' || '' }} - name: Configure Projects + if: "${{ inputs.test_type }}" != "coverage" }} env: amdgpu_families: ${{ env.AMDGPU_FAMILIES }} package_version: ADHOCBUILD extra_cmake_options: "-DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" BUILD_DIR: build run: | - set -euo pipefail - EXTRA_OPTS="-DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" - PROJECT_KEY="$(echo "${{inputs.projects_to_test }}" | tr '[:lower:]' '[:upper:]')" - if [[ "${{ inputs.test_type }}" == "coverage" ]]; then - EXTRA_OPTS="${EXTRA_OPTS} -D${PROJECT_KEY}_ENABLE_COVERAGE=ON" - echo "Coverage enabled for ${PROJECT_KEY}: ${EXTRA_OPTS}" - fi - export extra_cmake_options="${EXTRA_OPTS}" + python3 TheRock/build_tools/github_actions/build_configure.py + + - name: Configure Projects + if: "${{ inputs.test_type }}" == "coverage" }} + env: + amdgpu_families: ${{ env.AMDGPU_FAMILIES }} + package_version: ADHOCBUILD + extra_cmake_options: "-D{{ inputs.project_name }}_ENABLE_COVERAGE -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" + BUILD_DIR: build + run: | python3 TheRock/build_tools/github_actions/build_configure.py - name: Build therock-archives and therock-dist diff --git a/.github/workflows/therock-ci.yml b/.github/workflows/therock-ci.yml index ae70c67ac341..47f884d59f6f 100644 --- a/.github/workflows/therock-ci.yml +++ b/.github/workflows/therock-ci.yml @@ -192,7 +192,6 @@ jobs: contents: read id-token: write needs: setup - # Only run if there are coverage projects (changed subtrees) if: ${{ needs.setup.outputs.linux_projects_coverage != '[]' }} strategy: fail-fast: false @@ -204,6 +203,7 @@ jobs: with: cmake_options: ${{ matrix.projects.cmake_options }} projects_to_test: ${{ matrix.projects.projects_to_test }} + project_name: ${{ matrix.projects.project_name }} test_type: coverage amdgpu_families: ${{ matrix.target_bundle.amdgpu_family }} test_runs_on: ${{ matrix.target_bundle.test_machine }} From 499a3ee8f449cd8fd9040d5db3a2f443e05448f5 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 12:48:39 -0600 Subject: [PATCH 14/79] consume project_name in test step as well --- .github/workflows/therock-ci-linux.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index ddeec1a9ee59..fffb0f704356 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -187,12 +187,13 @@ jobs: - name: Run project coverage shell: bash run: | - BUILD_DIR="/build/TheRock/rocm-libraries/${{ inputs.projects_to_test }}/build" + BUILD_DIR="/build/TheRock/rocm-libraries/${{ inputs.project_name }}/build" + echo "Running coverage for ${{ inputs.project_name }} in ${BUILD_DIR}" cmake --build "${BUILD_DIR}" --target coverage || make -C "${BUILD_DIR}" coverage - - name: Upload coverage to Codecov uses: codecov/codecov-action@v4 with: files: ${{ env.REPORTS }} fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} + From 58cf9ea945ee540661d9d052bc492bba73f9a071 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 13:22:38 -0600 Subject: [PATCH 15/79] handle linting --- .github/scripts/therock_configure_coverage.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 6927cb64aadf..7d28a148b176 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -38,10 +38,10 @@ def main(): for proj in projects: pts_list = [p for p in proj.get("projects_to_test", "").split(",") if p] - #TODO: We don't want a default + # TODO: We don't want a default primary = pts_list[0] if pts_list else "" - #TODO: There's a better way than iterating and comparing to projects_to_test + # TODO: There's a better way than iterating and comparing to projects_to_test for p in pts_list: if p in changed_project_keys: primary = p @@ -64,4 +64,3 @@ def main(): if __name__ == "__main__": main() - From 9f02fb082414ae8cf82dda854b00f7b889910d5d Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 13:34:48 -0600 Subject: [PATCH 16/79] fix linting --- .github/workflows/therock-ci-linux.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index fffb0f704356..55e03b20d3f8 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -99,24 +99,22 @@ jobs: ./TheRock/build_tools/fetch_sources.py --jobs 12 --no-include-rocm-libraries --no-include-ml-frameworks ${{ contains(inputs.cmake_options, 'THEROCK_ENABLE_IREE_LIBS=ON') && '--include-iree-libs' || '' }} - name: Configure Projects - if: "${{ inputs.test_type }}" != "coverage" }} + if: {{ "${{ inputs.test_type }}" != "coverage" }} env: amdgpu_families: ${{ env.AMDGPU_FAMILIES }} package_version: ADHOCBUILD extra_cmake_options: "-DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" BUILD_DIR: build - run: | - python3 TheRock/build_tools/github_actions/build_configure.py + run: python3 TheRock/build_tools/github_actions/build_configure.py - name: Configure Projects - if: "${{ inputs.test_type }}" == "coverage" }} + if: {{ "${{ inputs.test_type }}" == "coverage" }} env: amdgpu_families: ${{ env.AMDGPU_FAMILIES }} package_version: ADHOCBUILD extra_cmake_options: "-D{{ inputs.project_name }}_ENABLE_COVERAGE -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" BUILD_DIR: build - run: | - python3 TheRock/build_tools/github_actions/build_configure.py + run: python3 TheRock/build_tools/github_actions/build_configure.py - name: Build therock-archives and therock-dist run: cmake --build TheRock/build --target therock-archives therock-dist -- -k 0 From b096f305abfed58d94ec22505d151f9bc7850517 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 13:50:07 -0600 Subject: [PATCH 17/79] fix lint --- .github/workflows/therock-ci-linux.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index 55e03b20d3f8..cb01e8e64fc9 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -99,7 +99,7 @@ jobs: ./TheRock/build_tools/fetch_sources.py --jobs 12 --no-include-rocm-libraries --no-include-ml-frameworks ${{ contains(inputs.cmake_options, 'THEROCK_ENABLE_IREE_LIBS=ON') && '--include-iree-libs' || '' }} - name: Configure Projects - if: {{ "${{ inputs.test_type }}" != "coverage" }} + if: ${{ inputs.test_type != 'coverage' }} env: amdgpu_families: ${{ env.AMDGPU_FAMILIES }} package_version: ADHOCBUILD @@ -108,14 +108,15 @@ jobs: run: python3 TheRock/build_tools/github_actions/build_configure.py - name: Configure Projects - if: {{ "${{ inputs.test_type }}" == "coverage" }} + if: ${{ inputs.test_type == 'coverage' }} env: amdgpu_families: ${{ env.AMDGPU_FAMILIES }} package_version: ADHOCBUILD - extra_cmake_options: "-D{{ inputs.project_name }}_ENABLE_COVERAGE -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" + extra_cmake_options: "-D${{ inputs.project_name }}_ENABLE_COVERAGE -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" BUILD_DIR: build run: python3 TheRock/build_tools/github_actions/build_configure.py + - name: Build therock-archives and therock-dist run: cmake --build TheRock/build --target therock-archives therock-dist -- -k 0 From 2921e9e4a2404c6ef036bb2e50043a284f996439 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 14:05:06 -0600 Subject: [PATCH 18/79] fix lint --- .github/workflows/therock-ci-linux.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index cb01e8e64fc9..748a96a07f61 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -195,4 +195,3 @@ jobs: files: ${{ env.REPORTS }} fail_ci_if_error: true token: ${{ secrets.CODECOV_TOKEN }} - From 9bbe49c9edf21d9adca48210a6097f3f12c7f135 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 2 Apr 2026 14:29:20 -0600 Subject: [PATCH 19/79] set enable_coverage to ON --- .github/workflows/therock-ci-linux.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index 748a96a07f61..104715e50065 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -112,7 +112,7 @@ jobs: env: amdgpu_families: ${{ env.AMDGPU_FAMILIES }} package_version: ADHOCBUILD - extra_cmake_options: "-D${{ inputs.project_name }}_ENABLE_COVERAGE -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" + extra_cmake_options: "-D${{ inputs.project_name }}_ENABLE_COVERAGE=ON -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" BUILD_DIR: build run: python3 TheRock/build_tools/github_actions/build_configure.py From 8c0af6d08ca529bc4eb3d1f70ee2c076d3374471 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 9 Apr 2026 15:32:04 -0600 Subject: [PATCH 20/79] Have coverage as a standalone test matrix --- .github/workflows/therock-ci-coverage.yml | 90 +++++++++++++++++++++++ .github/workflows/therock-ci-linux.yml | 36 +-------- .github/workflows/therock-ci.yml | 15 ++-- 3 files changed, 99 insertions(+), 42 deletions(-) create mode 100644 .github/workflows/therock-ci-coverage.yml diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml new file mode 100644 index 000000000000..06cb1273da3e --- /dev/null +++ b/.github/workflows/therock-ci-coverage.yml @@ -0,0 +1,90 @@ +name: TheRock CI Linux Coverage + +on: + workflow_call: + inputs: + cmake_options: + type: string + project_name: + type: string + amdgpu_families: + type: string + test_runs_on: + type: string + +permissions: + contents: read + +jobs: + therock-coverage-linux: + name: Coverage (${{ inputs.project_name }} | ${{ inputs.amdgpu_families }}) + runs-on: azure-linux-scale-rocm + container: + image: ghcr.io/rocm/therock_build_manylinux_x86_64@sha256:4443d9d710b9471e8ef658d509358bd92602498e67161b9280474bce0bb0decd + options: -v /runner/config:/home/awsconfig/ + env: + AMDGPU_FAMILIES: ${{ inputs.amdgpu_families }} + CACHE_DIR: ${{ github.workspace }}/.container-cache + CCACHE_CONFIGPATH: ${{ github.workspace }}/.ccache/ccache.conf + TEATIME_FORCE_INTERACTIVE: 0 + AWS_SHARED_CREDENTIALS_FILE: /home/awsconfig/credentials.ini + steps: + - name: "Checking out repository for rocm-libraries" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Checkout TheRock repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: "ROCm/TheRock" + path: TheRock + ref: 0f3a983528f2d097d89691d9f9c05d602b3f4aba + + - name: Install python deps + run: | + pip install -r TheRock/requirements.txt + + - name: Adjust git config + run: | + git config --global --add safe.directory $PWD + git config fetch.parallel 10 + + - name: Setup ccache + run: | + ./TheRock/build_tools/setup_ccache.py \ + --config-preset "github-oss-presubmit" \ + --dir "$(dirname $CCACHE_CONFIGPATH)" \ + --local-path "$CACHE_DIR/ccache" + + - name: Runner health status + run: | + ./TheRock/build_tools/health_status.py + + - name: Pull DVC files for rocm-libraries # LOGNAME details here https://github.com/ROCm/rocm-libraries/pull/1617 + run: | + if command -v dvc &> /dev/null; then + echo "dvc detected" + else + echo "Warning, dvc not detected!" + fi + LOGNAME=github-runner dvc pull -v + + - name: Fetch sources + timeout-minutes: 30 + run: | + ./TheRock/build_tools/fetch_sources.py --jobs 12 --no-include-rocm-libraries --no-include-ml-frameworks + + - name: Configure coverage build + env: + amdgpu_families: ${{ env.AMDGPU_FAMILIES }} + package_version: ADHOCBUILD + extra_cmake_options: >- + -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ + -D${{ inputs.project_name }}_ENABLE_COVERAGE=ON + ${{ inputs.cmake_options }} + BUILD_DIR: build-coverage + run: | + python3 TheRock/build_tools/github_actions/build_configure.py + + - name: Build coverage + run: | + cmake --build TheRock/build-coverage --target coverage diff --git a/.github/workflows/therock-ci-linux.yml b/.github/workflows/therock-ci-linux.yml index 104715e50065..b0b78fb50296 100644 --- a/.github/workflows/therock-ci-linux.yml +++ b/.github/workflows/therock-ci-linux.yml @@ -13,8 +13,6 @@ on: type: string projects_to_test: type: string - project_name: - type: string test_type: type: string amdgpu_families: @@ -99,23 +97,13 @@ jobs: ./TheRock/build_tools/fetch_sources.py --jobs 12 --no-include-rocm-libraries --no-include-ml-frameworks ${{ contains(inputs.cmake_options, 'THEROCK_ENABLE_IREE_LIBS=ON') && '--include-iree-libs' || '' }} - name: Configure Projects - if: ${{ inputs.test_type != 'coverage' }} env: amdgpu_families: ${{ env.AMDGPU_FAMILIES }} package_version: ADHOCBUILD extra_cmake_options: "-DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" BUILD_DIR: build - run: python3 TheRock/build_tools/github_actions/build_configure.py - - - name: Configure Projects - if: ${{ inputs.test_type == 'coverage' }} - env: - amdgpu_families: ${{ env.AMDGPU_FAMILIES }} - package_version: ADHOCBUILD - extra_cmake_options: "-D${{ inputs.project_name }}_ENABLE_COVERAGE=ON -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ ${{ inputs.cmake_options }}" - BUILD_DIR: build - run: python3 TheRock/build_tools/github_actions/build_configure.py - + run: | + python3 TheRock/build_tools/github_actions/build_configure.py - name: Build therock-archives and therock-dist run: cmake --build TheRock/build --target therock-archives therock-dist -- -k 0 @@ -166,7 +154,6 @@ jobs: therock-test-linux: name: Test (${{ inputs.amdgpu_families }}) - if: ${{ inputs.test_type != 'coverage' && inputs.amdgpu_families != 'gfx950-dcgpu' }} needs: [therock-build-linux] uses: ./.github/workflows/therock-test-packages.yml with: @@ -176,22 +163,3 @@ jobs: platform: "linux" test_type: ${{ inputs.test_type }} secrets: inherit - - therock-test-coverage: - name: Code Coverage - if: ${{ inputs.test_type == 'coverage' && inputs.amdgpu_families != 'gfx950-dcgpu'}} - needs: [therock-build-linux] - runs-on: ubuntu-latest - steps: - - name: Run project coverage - shell: bash - run: | - BUILD_DIR="/build/TheRock/rocm-libraries/${{ inputs.project_name }}/build" - echo "Running coverage for ${{ inputs.project_name }} in ${BUILD_DIR}" - cmake --build "${BUILD_DIR}" --target coverage || make -C "${BUILD_DIR}" coverage - - name: Upload coverage to Codecov - uses: codecov/codecov-action@v4 - with: - files: ${{ env.REPORTS }} - fail_ci_if_error: true - token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/therock-ci.yml b/.github/workflows/therock-ci.yml index 47f884d59f6f..0ab5bef4f1a3 100644 --- a/.github/workflows/therock-ci.yml +++ b/.github/workflows/therock-ci.yml @@ -50,7 +50,7 @@ jobs: test_type: ${{ steps.linux_projects.outputs.test_type }} linux_package_targets: ${{ steps.configure_linux.outputs.package_targets }} windows_package_targets: ${{ steps.configure_windows.outputs.package_targets }} - linux_projects_coverage: ${{ steps.linux_projects_coverage.outputs.linux_projects_coverage }} + coverage_projects: ${{ steps.coverage_projects.outputs.coverage_projects }} steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -99,7 +99,7 @@ jobs: python .github/scripts/therock_configure_ci.py - name: Determine Linux projects for coverage (changed subtrees only) - id: linux_projects_coverage + id: coverage_projects env: PLATFORM: "linux" run: | @@ -187,27 +187,26 @@ jobs: build_runs_on: ${{ needs.setup.outputs.windows_build_runs_on }} therock-ci-coverage: - name: Coverage (${{ matrix.projects.projects_to_test }} | ${{ matrix.target_bundle.amdgpu_family }}) + name: Coverage (${{ matrix.projects.project_name }} | ${{ matrix.target_bundle.amdgpu_family }}) permissions: contents: read id-token: write needs: setup - if: ${{ needs.setup.outputs.linux_projects_coverage != '[]' }} + if: ${{ needs.setup.outputs.coverage_projects != '[]' }} strategy: fail-fast: false matrix: - projects: ${{ fromJSON(needs.setup.outputs.linux_projects_coverage) }} + projects: ${{ fromJSON(needs.setup.outputs.coverage_projects) }} target_bundle: ${{ fromJSON(needs.setup.outputs.linux_package_targets) }} - uses: ./.github/workflows/therock-ci-linux.yml + uses: ./.github/workflows/therock-ci-coverage.yml secrets: inherit with: cmake_options: ${{ matrix.projects.cmake_options }} - projects_to_test: ${{ matrix.projects.projects_to_test }} project_name: ${{ matrix.projects.project_name }} - test_type: coverage amdgpu_families: ${{ matrix.target_bundle.amdgpu_family }} test_runs_on: ${{ matrix.target_bundle.test_machine }} + therock_ci_summary: name: TheRock CI Summary if: always() From 50a0e7a948d0aec2fdbfce6b4de1049510ff9037 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 9 Apr 2026 15:41:43 -0600 Subject: [PATCH 21/79] WIP: Temporarily disable other test matices --- .github/workflows/therock-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci.yml b/.github/workflows/therock-ci.yml index 0ab5bef4f1a3..bf444527b10d 100644 --- a/.github/workflows/therock-ci.yml +++ b/.github/workflows/therock-ci.yml @@ -145,7 +145,7 @@ jobs: contents: read id-token: write needs: setup - if: ${{ needs.setup.outputs.linux_projects != '[]' }} + if: ${{ false && needs.setup.outputs.linux_projects != '[]' }} strategy: fail-fast: false matrix: @@ -169,7 +169,7 @@ jobs: contents: read id-token: write needs: setup - if: ${{ needs.setup.outputs.windows_projects != '[]' }} + if: ${{ false && needs.setup.outputs.windows_projects != '[]' }} strategy: fail-fast: false matrix: From e75eee3636b0cad3273bb7628cb4a7842dfa0ef1 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 13 Apr 2026 19:33:45 -0600 Subject: [PATCH 22/79] rename to coverage_projects for coverage --- .github/scripts/therock_configure_coverage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 7d28a148b176..405a8c48c32d 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -50,7 +50,7 @@ def main(): proj["project_name"] = primary.upper() output = { - "linux_projects_coverage": json.dumps(projects), + "coverage_projects": json.dumps(projects), } github_output = os.environ.get("GITHUB_OUTPUT") if github_output: From 62ba9e7fb9cd377df8a3a3ec771210b09c2529e0 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 13 Apr 2026 20:24:08 -0600 Subject: [PATCH 23/79] bump hashes --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 06cb1273da3e..a054535cfe5f 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -37,7 +37,7 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: 0f3a983528f2d097d89691d9f9c05d602b3f4aba + ref: 1db58af27e63a7da9cc3e06f0ff6a9e5c14d6eba - name: Install python deps run: | From e09d7643ae6482dc18183c116331a58280357503 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 13 Apr 2026 20:54:37 -0600 Subject: [PATCH 24/79] Only deploy code cov on gfx942 --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index a054535cfe5f..4e4a786d01cd 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -37,7 +37,7 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: 1db58af27e63a7da9cc3e06f0ff6a9e5c14d6eba + ref: 3285c73499dba64e16afcd9dd7059d328f2f1254 - name: Install python deps run: | From 74ae1ba476536bee54cfd616ca7002811d706d51 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 13 Apr 2026 21:19:22 -0600 Subject: [PATCH 25/79] WIP: just hardcode coverage directory to see if it works --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 4e4a786d01cd..a6b8be4cef07 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -87,4 +87,4 @@ jobs: - name: Build coverage run: | - cmake --build TheRock/build-coverage --target coverage + cmake --build TheRock/build-coverage/ml-libs/hipDNN/build --target coverage From b14386ff4a473752b45b347c00d0632c8c10e410 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Tue, 14 Apr 2026 09:41:12 -0600 Subject: [PATCH 26/79] Add a mapping to project directories --- .github/scripts/therock_configure_coverage.py | 44 ++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 405a8c48c32d..632958a36690 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -12,6 +12,27 @@ logging.basicConfig(level=logging.INFO) SCRIPT_DIR = Path(__file__).resolve().parent +# Coverage-enabled projects: project key -> (cmake_target, build_subdir) +# Only projects listed here will get coverage jobs +COVERAGE_PROJECT_METADATA = { + "hipdnn": ("hipDNN", "ml-libs/hipDNN"), + "prim": ("rocPRIM", "math-libs/PRIM"), +} + + +def get_build_metadata(project_key: str, base_dir: str = "TheRock/build-coverage"): + """Get CMake target and build directory for a coverage-enabled project. + + Returns: + Tuple of (uppercase_name, cmake_target, build_dir) or None if not coverage-enabled + """ + if project_key not in COVERAGE_PROJECT_METADATA: + return None + + cmake_target, build_subdir = COVERAGE_PROJECT_METADATA[project_key] + build_dir = f"{base_dir}/{build_subdir}/build" + return project_key.upper(), cmake_target, build_dir + def get_changed_subtrees_only(): repo_config_path = SCRIPT_DIR / ".." / "repos-config.json" @@ -35,22 +56,35 @@ def main(): projects = collect_projects_to_run(subtrees) + # Filter: only keep projects that have coverage-enabled tests + coverage_projects = [] for proj in projects: pts_list = [p for p in proj.get("projects_to_test", "").split(",") if p] - # TODO: We don't want a default + # Find primary project (prefer changed projects) primary = pts_list[0] if pts_list else "" - - # TODO: There's a better way than iterating and comparing to projects_to_test for p in pts_list: if p in changed_project_keys: primary = p break - proj["project_name"] = primary.upper() + # FILTER: Skip if not coverage-enabled + metadata = get_build_metadata(primary) + if metadata is None: + logging.info(f"Skipping {primary} - not coverage-enabled") + continue + + # Add coverage metadata + uppercase_name, cmake_target, build_dir = metadata + proj["project_name"] = uppercase_name + proj["cmake_target"] = cmake_target + proj["build_dir"] = build_dir + + coverage_projects.append(proj) + # Output for GitHub Actions output = { - "coverage_projects": json.dumps(projects), + "coverage_projects": json.dumps(coverage_projects), } github_output = os.environ.get("GITHUB_OUTPUT") if github_output: From c658ed6220af333c16dc70d70473bddf41282ec3 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Tue, 14 Apr 2026 09:42:51 -0600 Subject: [PATCH 27/79] Build any defined project's code coverage flow --- .github/workflows/therock-ci-coverage.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index a6b8be4cef07..0f2d20816a49 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -7,6 +7,10 @@ on: type: string project_name: type: string + cmake_target: + type: string + build_dir: + type: string amdgpu_families: type: string test_runs_on: @@ -85,6 +89,10 @@ jobs: run: | python3 TheRock/build_tools/github_actions/build_configure.py - - name: Build coverage + - name: Build ${{ inputs.cmake_target }} + run: | + ninja -C TheRock/build-coverage ${{ inputs.cmake_target }} + + - name: Build coverage for ${{ inputs.project_name }} run: | - cmake --build TheRock/build-coverage/ml-libs/hipDNN/build --target coverage + cmake --build ${{ inputs.build_dir }} --target coverage From 77aef508247cf5f64fae23a52f45ca1cffe50a72 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Tue, 14 Apr 2026 11:21:28 -0600 Subject: [PATCH 28/79] make sure llvm-cov and llvm-profdata are accessible --- .github/workflows/therock-ci-coverage.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 0f2d20816a49..242504ae7983 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -84,14 +84,14 @@ jobs: extra_cmake_options: >- -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../ -D${{ inputs.project_name }}_ENABLE_COVERAGE=ON + -DLLVM_TOOLS_SEARCH_PREFIX=${{ github.workspace }}/TheRock/build-coverage/dist/rocm/lib/llvm ${{ inputs.cmake_options }} BUILD_DIR: build-coverage run: | python3 TheRock/build_tools/github_actions/build_configure.py - - name: Build ${{ inputs.cmake_target }} - run: | - ninja -C TheRock/build-coverage ${{ inputs.cmake_target }} + - name: Build therock-archives and therock-dist + run: cmake --build TheRock/build-coverage --target therock-archives therock-dist -- -k 0 - name: Build coverage for ${{ inputs.project_name }} run: | From 459f3e75c9e817efeb15640cbf486fb0bc97d504 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Tue, 14 Apr 2026 13:34:37 -0600 Subject: [PATCH 29/79] bump hashes --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 242504ae7983..f8f35a75ef88 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -41,7 +41,7 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: 3285c73499dba64e16afcd9dd7059d328f2f1254 + ref: 00cef7573ba4cd8e7722a31bd521b5b9c76c4d95 - name: Install python deps run: | From c966a07368ea78812bcbbba9fc1f77fd51a5092c Mon Sep 17 00:00:00 2001 From: John Robbins Date: Wed, 15 Apr 2026 08:51:50 -0600 Subject: [PATCH 30/79] use commit in TheRock that exports llvm-cov and llvm-profdata --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index f8f35a75ef88..a5f2a70115cf 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -41,7 +41,7 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: 00cef7573ba4cd8e7722a31bd521b5b9c76c4d95 + ref: 04e101f74ebd4d278628748729b7812c812c2166 - name: Install python deps run: | From 87dfc68fed8ee5df3079ffd85b67ee4eb6516220 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Wed, 15 Apr 2026 09:34:55 -0600 Subject: [PATCH 31/79] use llvm version 22 --- .github/workflows/therock-ci-coverage.yml | 2 +- projects/hipdnn/cmake/CheckToolVersion.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index a5f2a70115cf..c87096d35a72 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -41,7 +41,7 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: 04e101f74ebd4d278628748729b7812c812c2166 + ref: 9faa2ef2ebf9347d008d3057bd909a5c5be03e22 - name: Install python deps run: | diff --git a/projects/hipdnn/cmake/CheckToolVersion.cmake b/projects/hipdnn/cmake/CheckToolVersion.cmake index d288b17d77ba..34e7dd2d79c8 100644 --- a/projects/hipdnn/cmake/CheckToolVersion.cmake +++ b/projects/hipdnn/cmake/CheckToolVersion.cmake @@ -4,7 +4,7 @@ # Expected tool versions set(EXPECTED_CLANG_FORMAT_VERSION "18") set(EXPECTED_CLANG_TIDY_VERSION "20") -set(EXPECTED_LLVM_VERSION "20") +set(EXPECTED_LLVM_VERSION "22") # Helper function to generate version-specific search paths hints by concatenating the base path # with a list of versioned path names. From b89ea2acc1c95cdf01f423231a2f3566e9ab5c8d Mon Sep 17 00:00:00 2001 From: John Robbins Date: Wed, 15 Apr 2026 13:51:43 -0600 Subject: [PATCH 32/79] expose variables needed for code cov --- .github/workflows/therock-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/therock-ci.yml b/.github/workflows/therock-ci.yml index bf444527b10d..5cb033e2a3c1 100644 --- a/.github/workflows/therock-ci.yml +++ b/.github/workflows/therock-ci.yml @@ -203,6 +203,8 @@ jobs: with: cmake_options: ${{ matrix.projects.cmake_options }} project_name: ${{ matrix.projects.project_name }} + cmake_target: ${{ matrix.projects.cmake_target }} + build_dir: ${{ matrix.projects.build_dir }} amdgpu_families: ${{ matrix.target_bundle.amdgpu_family }} test_runs_on: ${{ matrix.target_bundle.test_machine }} From 30da3909587b7ddee7661419f5f1f653884183b2 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 16 Apr 2026 15:30:22 -0600 Subject: [PATCH 33/79] actually run on a GPU node :/ --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index c87096d35a72..17f9e824b16a 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -22,7 +22,7 @@ permissions: jobs: therock-coverage-linux: name: Coverage (${{ inputs.project_name }} | ${{ inputs.amdgpu_families }}) - runs-on: azure-linux-scale-rocm + runs-on: ${{ inputs.test_runs_on }} container: image: ghcr.io/rocm/therock_build_manylinux_x86_64@sha256:4443d9d710b9471e8ef658d509358bd92602498e67161b9280474bce0bb0decd options: -v /runner/config:/home/awsconfig/ From 4b367224192d1d6db590682a66745c979ede304c Mon Sep 17 00:00:00 2001 From: John Robbins Date: Fri, 17 Apr 2026 08:38:30 -0600 Subject: [PATCH 34/79] split build and test for coverage --- .github/workflows/therock-ci-coverage.yml | 70 +++++++++++++++++++++-- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 17f9e824b16a..d53606c97ff2 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -20,9 +20,11 @@ permissions: contents: read jobs: - therock-coverage-linux: - name: Coverage (${{ inputs.project_name }} | ${{ inputs.amdgpu_families }}) - runs-on: ${{ inputs.test_runs_on }} + therock-coverage-build: + name: Build Coverage (${{ inputs.project_name }} | ${{ inputs.amdgpu_families }}) + runs-on: azure-linux-scale-rocm + permissions: + id-token: write container: image: ghcr.io/rocm/therock_build_manylinux_x86_64@sha256:4443d9d710b9471e8ef658d509358bd92602498e67161b9280474bce0bb0decd options: -v /runner/config:/home/awsconfig/ @@ -93,6 +95,66 @@ jobs: - name: Build therock-archives and therock-dist run: cmake --build TheRock/build-coverage --target therock-archives therock-dist -- -k 0 - - name: Build coverage for ${{ inputs.project_name }} + - name: Report + if: ${{ !cancelled() }} + run: | + echo "Full SDK du:" + echo "------------" + du -h -d 1 TheRock/build-coverage/dist/rocm + echo "Artifact Archives:" + echo "------------------" + ls -lh TheRock/build-coverage/artifacts/*.tar.xz + echo "Artifacts:" + echo "----------" + du -h -d 1 TheRock/build-coverage/artifacts + echo "CCache Stats:" + echo "-------------" + ccache -s -v + + - name: Configure AWS Credentials for non-forked repos + if: ${{ always() && !github.event.pull_request.head.repo.fork }} + uses: aws-actions/configure-aws-credentials@8df5847569e6427dd6c4fb1cf565c83acfa8afa7 # v6.0.0 + with: + aws-region: us-east-2 + role-to-assume: arn:aws:iam::692859939525:role/therock-ci-external + + - name: Post Build Upload + if: always() + run: | + python3 TheRock/build_tools/github_actions/post_build_upload.py \ + --run-id ${{ github.run_id }} \ + --artifact-group ${{ env.AMDGPU_FAMILIES }} \ + --build-dir TheRock/build-coverage \ + --upload + + therock-coverage-test: + name: Test Coverage (${{ inputs.project_name }} | ${{ inputs.amdgpu_families }}) + needs: [therock-coverage-build] + runs-on: ${{ inputs.test_runs_on }} + if: ${{ inputs.test_runs_on != '' }} + steps: + - name: "Checking out repository for rocm-libraries" + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Checkout TheRock repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + repository: "ROCm/TheRock" + path: TheRock + ref: 9faa2ef2ebf9347d008d3057bd909a5c5be03e22 + + - name: Install python deps + run: | + pip install -r TheRock/requirements.txt + + - name: Setup test environment and fetch artifacts + uses: ./.github/actions/setup_test_environment + with: + artifact_run_id: ${{ github.run_id }} + artifact_group: ${{ inputs.amdgpu_families }} + amdgpu_targets: "" + fetch_artifact_args: "" + + - name: Run coverage tests and generate report run: | cmake --build ${{ inputs.build_dir }} --target coverage From 35ccdbf05129e86165d6e5c1915be4bd30b690ec Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 20 Apr 2026 12:01:38 -0600 Subject: [PATCH 35/79] bump hashes --- .github/workflows/therock-ci-coverage.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index d53606c97ff2..e16291dd2a88 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -43,7 +43,7 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: 9faa2ef2ebf9347d008d3057bd909a5c5be03e22 + ref: f629edc0b56da77fc0d29e6bc01e724aaf0be826 - name: Install python deps run: | @@ -141,7 +141,7 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: 9faa2ef2ebf9347d008d3057bd909a5c5be03e22 + ref: f629edc0b56da77fc0d29e6bc01e724aaf0be826 - name: Install python deps run: | From c7a39101261cc04dba8b9aefa9436deae880390e Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 20 Apr 2026 13:39:47 -0600 Subject: [PATCH 36/79] change dir name --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index e16291dd2a88..d49fa693fdef 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -57,7 +57,7 @@ jobs: - name: Setup ccache run: | ./TheRock/build_tools/setup_ccache.py \ - --config-preset "github-oss-presubmit" \ + --config-preset "github-oss-dev" \ --dir "$(dirname $CCACHE_CONFIGPATH)" \ --local-path "$CACHE_DIR/ccache" From 1dd599cb97af4ae8e29444bb6a61cccf6398c3be Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 20 Apr 2026 14:05:22 -0600 Subject: [PATCH 37/79] bump container images --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index d49fa693fdef..4e603ca61bf2 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -26,7 +26,7 @@ jobs: permissions: id-token: write container: - image: ghcr.io/rocm/therock_build_manylinux_x86_64@sha256:4443d9d710b9471e8ef658d509358bd92602498e67161b9280474bce0bb0decd + image: ghcr.io/rocm/therock_build_manylinux_x86_64@sha256:702a5133851e6d1daf1207d2c9fbb01c2667914a5b6dc5a01faeb3ce66ea6421 options: -v /runner/config:/home/awsconfig/ env: AMDGPU_FAMILIES: ${{ inputs.amdgpu_families }} From c20a5efdb0af2d7d64d5d31cc51413164b05e405 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Mon, 20 Apr 2026 21:52:54 -0600 Subject: [PATCH 38/79] use proper container for testing --- .github/workflows/therock-ci-coverage.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 4e603ca61bf2..d0380b5bc1b8 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -132,6 +132,20 @@ jobs: needs: [therock-coverage-build] runs-on: ${{ inputs.test_runs_on }} if: ${{ inputs.test_runs_on != '' }} + timeout-minutes: 210 + container: + image: ghcr.io/rocm/no_rocm_image_ubuntu24_04@sha256:4150afe4759d14822f0e3f8930e1124f26e11f68b5c7b91ec9a02b20b1ebbb98 + options: --ipc host + --group-add video + --device /dev/kfd + --device /dev/dri + --group-add 993 + --group-add 992 + --group-add 110 + --env-file /etc/podinfo/gha-gpu-isolation-settings + defaults: + run: + shell: bash steps: - name: "Checking out repository for rocm-libraries" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 From f6ec900a9bbf321683fc531b70b333576906d991 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Tue, 21 Apr 2026 09:20:27 -0600 Subject: [PATCH 39/79] remove redundant pip install --- .github/workflows/therock-ci-coverage.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index d0380b5bc1b8..ae903b71c57d 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -157,10 +157,6 @@ jobs: path: TheRock ref: f629edc0b56da77fc0d29e6bc01e724aaf0be826 - - name: Install python deps - run: | - pip install -r TheRock/requirements.txt - - name: Setup test environment and fetch artifacts uses: ./.github/actions/setup_test_environment with: From 44505a378c796e85f47f19e030ac55c49a6f9b19 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Tue, 21 Apr 2026 15:17:04 -0600 Subject: [PATCH 40/79] align with therock-ci-linux test flow --- .github/workflows/therock-ci-coverage.yml | 41 +++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index ae903b71c57d..5b566ffb5e24 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -157,13 +157,42 @@ jobs: path: TheRock ref: f629edc0b56da77fc0d29e6bc01e724aaf0be826 - - name: Setup test environment and fetch artifacts - uses: ./.github/actions/setup_test_environment + - name: Setting up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: - artifact_run_id: ${{ github.run_id }} - artifact_group: ${{ inputs.amdgpu_families }} - amdgpu_targets: "" - fetch_artifact_args: "" + python-version: 3.12 + + - name: Install UV + run: curl -LsSf https://astral.sh/uv/install.sh | sh + + - name: Create Python venv + env: + VENV_DIR: ${{ github.workspace }}/.venv + run: | + python TheRock/build_tools/setup_venv.py ${VENV_DIR} \ + --activate-in-future-github-actions-steps \ + --use-uv + + - name: Install test requirements + run: | + uv pip install -r TheRock/requirements-test.txt + uv pip freeze + + - name: Download and Unpack Artifacts + env: + OUTPUT_ARTIFACTS_DIR: ${{ github.workspace }}/build + ARTIFACT_GROUP: ${{ inputs.amdgpu_families }} + AMDGPU_TARGETS: "" + ARTIFACT_RUN_ID: ${{ github.run_id }} + FETCH_ARTIFACT_ARGS: "" + RELEASE_TYPE: "" + run: | + python ./TheRock/build_tools/install_rocm_from_artifacts.py \ + --run-id=${ARTIFACT_RUN_ID} \ + --artifact-group=${ARTIFACT_GROUP} \ + --amdgpu-targets=${AMDGPU_TARGETS} \ + --output-dir=${OUTPUT_ARTIFACTS_DIR} \ + ${FETCH_ARTIFACT_ARGS} - name: Run coverage tests and generate report run: | From c8a6856303b694dbdf91c39fcb662fc4c131a76b Mon Sep 17 00:00:00 2001 From: John Robbins Date: Tue, 21 Apr 2026 15:32:47 -0600 Subject: [PATCH 41/79] bump container image --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 5b566ffb5e24..c861c0bc012a 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -26,7 +26,7 @@ jobs: permissions: id-token: write container: - image: ghcr.io/rocm/therock_build_manylinux_x86_64@sha256:702a5133851e6d1daf1207d2c9fbb01c2667914a5b6dc5a01faeb3ce66ea6421 + image: ghcr.io/rocm/therock_build_manylinux_x86_64@sha256:48492540591673fdc8d51beb89bde41e7ba13cbb528f643c0a481ba42c4058f2 options: -v /runner/config:/home/awsconfig/ env: AMDGPU_FAMILIES: ${{ inputs.amdgpu_families }} From 34a672926db93243a062bd4345aba3daf1a179b0 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Tue, 21 Apr 2026 16:10:49 -0600 Subject: [PATCH 42/79] Add gpu sanity check and bump hashes --- .github/workflows/therock-ci-coverage.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index c861c0bc012a..9e5081ec5cd9 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -43,7 +43,7 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: f629edc0b56da77fc0d29e6bc01e724aaf0be826 + ref: 6afcd5ac5298e9a5cdb3d2c45ae7605739ad2b94 - name: Install python deps run: | @@ -155,7 +155,12 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: f629edc0b56da77fc0d29e6bc01e724aaf0be826 + ref: 6afcd5ac5298e9a5cdb3d2c45ae7605739ad2b94 + + - name: Checkout rocm-libraries repository for scripts + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + path: rocm-libraries - name: Setting up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 @@ -194,6 +199,11 @@ jobs: --output-dir=${OUTPUT_ARTIFACTS_DIR} \ ${FETCH_ARTIFACT_ARGS} + - name: Driver / GPU sanity check + timeout-minutes: 3 + run: | + python ./TheRock/build_tools/print_driver_gpu_info.py + - name: Run coverage tests and generate report run: | cmake --build ${{ inputs.build_dir }} --target coverage From 790777cba03811e2c1707218d3f8e447a997b2fc Mon Sep 17 00:00:00 2001 From: John Robbins Date: Wed, 22 Apr 2026 09:22:35 -0600 Subject: [PATCH 43/79] use correct build dir for coverage --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 9e5081ec5cd9..1fd689f29013 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -185,7 +185,7 @@ jobs: - name: Download and Unpack Artifacts env: - OUTPUT_ARTIFACTS_DIR: ${{ github.workspace }}/build + OUTPUT_ARTIFACTS_DIR: ${{ github.workspace }}/TheRock/build-coverage ARTIFACT_GROUP: ${{ inputs.amdgpu_families }} AMDGPU_TARGETS: "" ARTIFACT_RUN_ID: ${{ github.run_id }} From b96b7d33f7bd8b59adf681abcabfc5cdf3099193 Mon Sep 17 00:00:00 2001 From: John Robbins Date: Thu, 23 Apr 2026 09:10:48 -0600 Subject: [PATCH 44/79] try rebuilding cmake build tree --- .github/workflows/therock-ci-coverage.yml | 24 +++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 1fd689f29013..d3beb7204355 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -204,6 +204,26 @@ jobs: run: | python ./TheRock/build_tools/print_driver_gpu_info.py - - name: Run coverage tests and generate report + - name: Reconfigure CMake for coverage + env: + amdgpu_families: ${{ inputs.amdgpu_families }} + package_version: ADHOCBUILD + extra_cmake_options: >- + -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../rocm-libraries/ + -D${{ inputs.project_name }}_ENABLE_COVERAGE=ON + -DLLVM_TOOLS_SEARCH_PREFIX=${{ github.workspace }}/TheRock/build-coverage/dist/rocm/lib/llvm + ${{ inputs.cmake_options }} + BUILD_DIR: build-coverage + working-directory: ${{ github.workspace }}/TheRock + run: | + python3 build_tools/github_actions/build_configure.py + + - name: Run tests to generate profraw files + working-directory: ${{ github.workspace }}/TheRock/build-coverage + run: | + cmake --build . --target ${{ inputs.cmake_target }}+test + + - name: Generate coverage report + working-directory: ${{ github.workspace }}/TheRock/build-coverage run: | - cmake --build ${{ inputs.build_dir }} --target coverage + cmake --build . --target coverage From 7e7589b0b085967d00e021465276f78e344cc32e Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Tue, 16 Jun 2026 08:32:44 +0000 Subject: [PATCH 45/79] fetch iree-libs sources in coverage build when IREE is enabled The coverage build matrix (e.g. hipDNN) passes THEROCK_ENABLE_IREE_LIBS=ON, which makes CMake configure the iree-compiler/fusilli/fusilliprovider subprojects. The coverage workflow's fetch step did not fetch the IREE sources, so the build failed with a missing iree-libs/fusilli/CMakeLists.txt. Mirror therock-ci-linux.yml by conditionally adding --include-iree-libs to fetch_sources.py when the project's cmake options enable IREE libs. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index d3beb7204355..d8a0d4937536 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -77,7 +77,7 @@ jobs: - name: Fetch sources timeout-minutes: 30 run: | - ./TheRock/build_tools/fetch_sources.py --jobs 12 --no-include-rocm-libraries --no-include-ml-frameworks + ./TheRock/build_tools/fetch_sources.py --jobs 12 --no-include-rocm-libraries --no-include-ml-frameworks ${{ contains(inputs.cmake_options, 'THEROCK_ENABLE_IREE_LIBS=ON') && '--include-iree-libs' || '' }} - name: Configure coverage build env: From 06f49942e913fa3435dba1edec9ca453d7b328c0 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Tue, 16 Jun 2026 15:55:05 +0000 Subject: [PATCH 46/79] hipRAND --- projects/hiprand/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/hiprand/CMakeLists.txt b/projects/hiprand/CMakeLists.txt index 364503576956..70d4bac9aac4 100644 --- a/projects/hiprand/CMakeLists.txt +++ b/projects/hiprand/CMakeLists.txt @@ -58,7 +58,7 @@ project(hipRAND CXX) # Build options option(BUILD_ADDRESS_SANITIZER "Build with address sanitizer enabled" OFF) option(BUILD_BENCHMARK "Build benchmarks" OFF) -option(BUILD_CODE_COVERAGE "Build with code coverage enabled" OFF) +option(BUILD_CODE_COVERAGE "Build with code coverage enabled" ON) option(BUILD_FORTRAN_WRAPPER "Build Fortran wrapper" OFF) option(BUILD_TEST "Build tests (requires googletest)" OFF) option(EXTERNAL_DEPS_FORCE_DOWNLOAD "Download non-ROCm dependencies and do not search for packages" OFF) @@ -255,4 +255,4 @@ rocm_create_package( MAINTAINER "hipRAND Maintainer " LDCONFIG LDCONFIG_DIR ${HIPRAND_CONFIG_DIR} -) \ No newline at end of file +) From 0f0f7e88fb501e36c8239a9d0d6562418bd828c8 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Tue, 16 Jun 2026 16:28:47 +0000 Subject: [PATCH 47/79] hipRANDcmake --- projects/hiprand/CMakeLists.txt | 4 ++-- projects/hiprand/test/CMakeLists.txt | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/projects/hiprand/CMakeLists.txt b/projects/hiprand/CMakeLists.txt index 70d4bac9aac4..8141e06575bb 100644 --- a/projects/hiprand/CMakeLists.txt +++ b/projects/hiprand/CMakeLists.txt @@ -58,7 +58,7 @@ project(hipRAND CXX) # Build options option(BUILD_ADDRESS_SANITIZER "Build with address sanitizer enabled" OFF) option(BUILD_BENCHMARK "Build benchmarks" OFF) -option(BUILD_CODE_COVERAGE "Build with code coverage enabled" ON) +option(HIPRAND_ENABLE_COVERAGE "Build with code coverage enabled" OFF) option(BUILD_FORTRAN_WRAPPER "Build Fortran wrapper" OFF) option(BUILD_TEST "Build tests (requires googletest)" OFF) option(EXTERNAL_DEPS_FORCE_DOWNLOAD "Download non-ROCm dependencies and do not search for packages" OFF) @@ -244,7 +244,7 @@ else() set(package_name hiprand) endif() -if(BUILD_CODE_COVERAGE) +if(HIPRAND_ENABLE_COVERAGE) target_compile_options(hiprand PRIVATE -g -O0 -fprofile-instr-generate -fcoverage-mapping) target_link_options(hiprand PUBLIC -fprofile-instr-generate) endif() diff --git a/projects/hiprand/test/CMakeLists.txt b/projects/hiprand/test/CMakeLists.txt index ad0dc409060b..8a0f4568528f 100644 --- a/projects/hiprand/test/CMakeLists.txt +++ b/projects/hiprand/test/CMakeLists.txt @@ -67,7 +67,7 @@ function(add_relative_test test_name test_target) endif() file(RELATIVE_PATH rel_path "${CMAKE_CURRENT_BINARY_DIR}" "${EXE_PATH}/${EXE_NAME}") add_test(NAME "${test_name}" COMMAND "./${rel_path}") - if(BUILD_CODE_COVERAGE) + if(HIPRAND_ENABLE_COVERAGE) set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${PROFILE_DIR}/profraw/hiprand-coverage_%m.profraw" ) @@ -78,7 +78,7 @@ endfunction() # Get hipRAND tests source files file(GLOB hipRAND_TEST_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/test_hiprand*.cpp) -if(BUILD_CODE_COVERAGE) +if(HIPRAND_ENABLE_COVERAGE) add_custom_target( coverage_analysis DEPENDS hiprand @@ -161,7 +161,7 @@ foreach(test_src ${hipRAND_TEST_SRCS}) RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test" ) add_relative_test(${test_name} ${test_name}) - if(BUILD_CODE_COVERAGE) + if(HIPRAND_ENABLE_COVERAGE) set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${PROFILE_DIR}/profraw/hiprand-coverage_%m.profraw" ) @@ -184,7 +184,7 @@ foreach(test_src ${hipRAND_TEST_SRCS}) endforeach( file_i ) endif() - if (BUILD_CODE_COVERAGE) + if (HIPRAND_ENABLE_COVERAGE) add_dependencies(coverage_analysis ${test_name}) endif() endforeach() From f92882b9754729ffc4f9b7e6ab598ffbce1c3770 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Wed, 17 Jun 2026 06:51:52 +0000 Subject: [PATCH 48/79] enable hipRAND coverage and fix primary-project selection Switch the coverage matrix to target hipRAND, and make primary-project selection deterministic by preferring the first coverage-enabled entry in projects_to_test. This is required for multi-project groups (e.g. the rand group's projects_to_test is rocrand,hiprand) where the group key never matches an individual test project name. Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 632958a36690..2872cf097ade 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -15,8 +15,7 @@ # Coverage-enabled projects: project key -> (cmake_target, build_subdir) # Only projects listed here will get coverage jobs COVERAGE_PROJECT_METADATA = { - "hipdnn": ("hipDNN", "ml-libs/hipDNN"), - "prim": ("rocPRIM", "math-libs/PRIM"), + "hiprand": ("hipRAND", "ml-libs/hipRAND"), } @@ -61,8 +60,12 @@ def main(): for proj in projects: pts_list = [p for p in proj.get("projects_to_test", "").split(",") if p] - # Find primary project (prefer changed projects) - primary = pts_list[0] if pts_list else "" + # Find primary project: prefer the first coverage-enabled test project, + # then a changed project, otherwise fall back to the first entry. + primary = next( + (p for p in pts_list if p in COVERAGE_PROJECT_METADATA), + pts_list[0] if pts_list else "", + ) for p in pts_list: if p in changed_project_keys: primary = p From 673458769d36f99508da065690e67677888c6153 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Wed, 17 Jun 2026 06:54:30 +0000 Subject: [PATCH 49/79] only override coverage primary with a coverage-enabled changed project In merged "enable all" groups, projects_to_test contains both hiprand and hipdnn. The changed-project override was re-selecting hipdnn (a changed but no-longer-coverage-enabled project), emptying the coverage matrix. Require the overriding changed project to be coverage-enabled so hiprand stays selected. Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 2872cf097ade..c0566a64f9f6 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -66,8 +66,11 @@ def main(): (p for p in pts_list if p in COVERAGE_PROJECT_METADATA), pts_list[0] if pts_list else "", ) + # Only let a changed project override the choice if it is itself + # coverage-enabled (otherwise a changed-but-uncovered project such as + # hipdnn would displace a covered one like hiprand in a merged group). for p in pts_list: - if p in changed_project_keys: + if p in changed_project_keys and p in COVERAGE_PROJECT_METADATA: primary = p break From e512035b605f2ed6f8b576d477c599a27c5c2497 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Wed, 17 Jun 2026 16:15:40 +0000 Subject: [PATCH 50/79] pin hipRAND coverage build to RAND-only and fix coverage report tooling The coverage job inherited the merged mega-group cmake options (when a workflow change enables all projects, rand is absorbed into the miopen group), so the HIPRAND build was building hipdnn/providers and failing on an unrelated hipblaslt-provider clang-tidy step. Pin the coverage build to its own options (-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF). Also make the hipRAND coverage report step robust in the TheRock dist build: honor LLVM_TOOLS_SEARCH_PREFIX when locating llvm-profdata/llvm-cov, and use $ instead of the hardcoded debug-suffixed libhiprand-d.so. Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 20 ++++++++++++------- projects/hiprand/test/CMakeLists.txt | 10 +++++----- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index c0566a64f9f6..8f1125d267e6 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -12,10 +12,12 @@ logging.basicConfig(level=logging.INFO) SCRIPT_DIR = Path(__file__).resolve().parent -# Coverage-enabled projects: project key -> (cmake_target, build_subdir) -# Only projects listed here will get coverage jobs +# Coverage-enabled projects: project key -> (cmake_target, build_subdir, cmake_options) +# Only projects listed here will get coverage jobs. cmake_options pins the build +# to just this project so the coverage job does not inherit the (possibly merged) +# mega-group options that would otherwise build unrelated components. COVERAGE_PROJECT_METADATA = { - "hiprand": ("hipRAND", "ml-libs/hipRAND"), + "hiprand": ("hipRAND", "ml-libs/hipRAND", "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), } @@ -23,14 +25,15 @@ def get_build_metadata(project_key: str, base_dir: str = "TheRock/build-coverage """Get CMake target and build directory for a coverage-enabled project. Returns: - Tuple of (uppercase_name, cmake_target, build_dir) or None if not coverage-enabled + Tuple of (uppercase_name, cmake_target, build_dir, cmake_options) or None if not + coverage-enabled """ if project_key not in COVERAGE_PROJECT_METADATA: return None - cmake_target, build_subdir = COVERAGE_PROJECT_METADATA[project_key] + cmake_target, build_subdir, cmake_options = COVERAGE_PROJECT_METADATA[project_key] build_dir = f"{base_dir}/{build_subdir}/build" - return project_key.upper(), cmake_target, build_dir + return project_key.upper(), cmake_target, build_dir, cmake_options def get_changed_subtrees_only(): @@ -81,10 +84,13 @@ def main(): continue # Add coverage metadata - uppercase_name, cmake_target, build_dir = metadata + uppercase_name, cmake_target, build_dir, cmake_options = metadata proj["project_name"] = uppercase_name proj["cmake_target"] = cmake_target proj["build_dir"] = build_dir + # Pin to this project's own options so we don't build the merged + # mega-group (which pulls in unrelated components like hipdnn/providers). + proj["cmake_options"] = cmake_options coverage_projects.append(proj) diff --git a/projects/hiprand/test/CMakeLists.txt b/projects/hiprand/test/CMakeLists.txt index 8a0f4568528f..6867b1ecc5bf 100644 --- a/projects/hiprand/test/CMakeLists.txt +++ b/projects/hiprand/test/CMakeLists.txt @@ -93,7 +93,7 @@ if(HIPRAND_ENABLE_COVERAGE) LLVM_PROFDATA llvm-profdata REQUIRED - HINTS ${ROCM_PATH}/llvm/bin + HINTS ${LLVM_TOOLS_SEARCH_PREFIX}/bin ${ROCM_PATH}/llvm/bin PATHS /opt/rocm/llvm/bin ) @@ -101,7 +101,7 @@ if(HIPRAND_ENABLE_COVERAGE) LLVM_COV llvm-cov REQUIRED - HINTS ${ROCM_PATH}/llvm/bin + HINTS ${LLVM_TOOLS_SEARCH_PREFIX}/bin ${ROCM_PATH}/llvm/bin PATHS /opt/rocm/llvm/bin ) @@ -109,9 +109,9 @@ if(HIPRAND_ENABLE_COVERAGE) coverage DEPENDS coverage_analysis COMMAND ${LLVM_PROFDATA} merge -sparse ${PROFILE_DIR}/profraw/hiprand-coverage_*.profraw -o ${PROFILE_DIR}/hiprand.profdata - COMMAND ${LLVM_COV} report -object ${CMAKE_BINARY_DIR}/library/libhiprand-d.so -instr-profile=${PROFILE_DIR}/hiprand.profdata - COMMAND ${LLVM_COV} show -object ${CMAKE_BINARY_DIR}/library/libhiprand-d.so -instr-profile=${PROFILE_DIR}/hiprand.profdata -format=html -output-dir=${PROFILE_DIR} - COMMAND ${LLVM_COV} export -object ${CMAKE_BINARY_DIR}/library/libhiprand-d.so -instr-profile=${PROFILE_DIR}/hiprand.profdata -format=lcov > ${PROFILE_DIR}/coverage.info + COMMAND ${LLVM_COV} report -object $ -instr-profile=${PROFILE_DIR}/hiprand.profdata + COMMAND ${LLVM_COV} show -object $ -instr-profile=${PROFILE_DIR}/hiprand.profdata -format=html -output-dir=${PROFILE_DIR} + COMMAND ${LLVM_COV} export -object $ -instr-profile=${PROFILE_DIR}/hiprand.profdata -format=lcov > ${PROFILE_DIR}/coverage.info WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) endif() From 8a1a7cfa1edba20f3c5f94fca80e4b411791e84c Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Wed, 17 Jun 2026 16:49:38 +0000 Subject: [PATCH 51/79] remove therock-coverage-test job from coverage workflow Drop the GPU test/report stage from the coverage workflow, leaving only the coverage build job. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 101 ---------------------- 1 file changed, 101 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index d8a0d4937536..ad19610905a5 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -126,104 +126,3 @@ jobs: --artifact-group ${{ env.AMDGPU_FAMILIES }} \ --build-dir TheRock/build-coverage \ --upload - - therock-coverage-test: - name: Test Coverage (${{ inputs.project_name }} | ${{ inputs.amdgpu_families }}) - needs: [therock-coverage-build] - runs-on: ${{ inputs.test_runs_on }} - if: ${{ inputs.test_runs_on != '' }} - timeout-minutes: 210 - container: - image: ghcr.io/rocm/no_rocm_image_ubuntu24_04@sha256:4150afe4759d14822f0e3f8930e1124f26e11f68b5c7b91ec9a02b20b1ebbb98 - options: --ipc host - --group-add video - --device /dev/kfd - --device /dev/dri - --group-add 993 - --group-add 992 - --group-add 110 - --env-file /etc/podinfo/gha-gpu-isolation-settings - defaults: - run: - shell: bash - steps: - - name: "Checking out repository for rocm-libraries" - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - - name: Checkout TheRock repository - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - with: - repository: "ROCm/TheRock" - path: TheRock - ref: 6afcd5ac5298e9a5cdb3d2c45ae7605739ad2b94 - - - name: Checkout rocm-libraries repository for scripts - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - with: - path: rocm-libraries - - - name: Setting up Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 - with: - python-version: 3.12 - - - name: Install UV - run: curl -LsSf https://astral.sh/uv/install.sh | sh - - - name: Create Python venv - env: - VENV_DIR: ${{ github.workspace }}/.venv - run: | - python TheRock/build_tools/setup_venv.py ${VENV_DIR} \ - --activate-in-future-github-actions-steps \ - --use-uv - - - name: Install test requirements - run: | - uv pip install -r TheRock/requirements-test.txt - uv pip freeze - - - name: Download and Unpack Artifacts - env: - OUTPUT_ARTIFACTS_DIR: ${{ github.workspace }}/TheRock/build-coverage - ARTIFACT_GROUP: ${{ inputs.amdgpu_families }} - AMDGPU_TARGETS: "" - ARTIFACT_RUN_ID: ${{ github.run_id }} - FETCH_ARTIFACT_ARGS: "" - RELEASE_TYPE: "" - run: | - python ./TheRock/build_tools/install_rocm_from_artifacts.py \ - --run-id=${ARTIFACT_RUN_ID} \ - --artifact-group=${ARTIFACT_GROUP} \ - --amdgpu-targets=${AMDGPU_TARGETS} \ - --output-dir=${OUTPUT_ARTIFACTS_DIR} \ - ${FETCH_ARTIFACT_ARGS} - - - name: Driver / GPU sanity check - timeout-minutes: 3 - run: | - python ./TheRock/build_tools/print_driver_gpu_info.py - - - name: Reconfigure CMake for coverage - env: - amdgpu_families: ${{ inputs.amdgpu_families }} - package_version: ADHOCBUILD - extra_cmake_options: >- - -DTHEROCK_ROCM_LIBRARIES_SOURCE_DIR=../rocm-libraries/ - -D${{ inputs.project_name }}_ENABLE_COVERAGE=ON - -DLLVM_TOOLS_SEARCH_PREFIX=${{ github.workspace }}/TheRock/build-coverage/dist/rocm/lib/llvm - ${{ inputs.cmake_options }} - BUILD_DIR: build-coverage - working-directory: ${{ github.workspace }}/TheRock - run: | - python3 build_tools/github_actions/build_configure.py - - - name: Run tests to generate profraw files - working-directory: ${{ github.workspace }}/TheRock/build-coverage - run: | - cmake --build . --target ${{ inputs.cmake_target }}+test - - - name: Generate coverage report - working-directory: ${{ github.workspace }}/TheRock/build-coverage - run: | - cmake --build . --target coverage From 94300a7a6f5920985d55c81a24a5f05430797bcf Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Wed, 17 Jun 2026 18:58:16 +0000 Subject: [PATCH 52/79] run coverage tests via the standard package test flow and add report stage Wire the coverage build into the same build -> test-packages -> test-component flow used by mainline CI, then merge/report: - therock-test-component.yml / therock-test-packages.yml: add an opt-in `coverage` input (default false). When set, the component test job exports LLVM_PROFILE_FILE and uploads the resulting profraw files as an artifact. Mainline CI is unaffected since it does not pass coverage. - therock-ci-coverage.yml: the build job stages the instrumented libraries and version-matched llvm-profdata/llvm-cov into an artifact; add a test job that reuses therock-test-packages.yml with coverage=true, and a report job that merges the profraw files and runs llvm-cov report/show/export. - therock-ci.yml: forward projects_to_test and test_type to the coverage flow. - therock_configure_coverage.py: pin projects_to_test to the coverage project so the test stage matches the pinned (single-project) build. Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 3 + .github/workflows/therock-ci-coverage.yml | 117 +++++++++++++++++- .github/workflows/therock-ci.yml | 2 + .github/workflows/therock-test-component.yml | 21 ++++ .github/workflows/therock-test-packages.yml | 5 + 5 files changed, 147 insertions(+), 1 deletion(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 8f1125d267e6..ea63d29ea5c6 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -91,6 +91,9 @@ def main(): # Pin to this project's own options so we don't build the merged # mega-group (which pulls in unrelated components like hipdnn/providers). proj["cmake_options"] = cmake_options + # Only run the coverage project's own tests, not every test in the + # (possibly merged) group, so the test stage matches the pinned build. + proj["projects_to_test"] = primary coverage_projects.append(proj) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index ad19610905a5..6eaee1dc57e9 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -15,6 +15,15 @@ on: type: string test_runs_on: type: string + projects_to_test: + type: string + test_type: + type: string + # TheRock revision pinned to a commit that exports llvm-cov / llvm-profdata + # in the dist. Kept as an input so the build, test and report stages stay in sync. + therock_ref: + type: string + default: 6afcd5ac5298e9a5cdb3d2c45ae7605739ad2b94 permissions: contents: read @@ -43,7 +52,7 @@ jobs: with: repository: "ROCm/TheRock" path: TheRock - ref: 6afcd5ac5298e9a5cdb3d2c45ae7605739ad2b94 + ref: ${{ inputs.therock_ref }} - name: Install python deps run: | @@ -95,6 +104,30 @@ jobs: - name: Build therock-archives and therock-dist run: cmake --build TheRock/build-coverage --target therock-archives therock-dist -- -k 0 + - name: Stage coverage objects and llvm tools + run: | + set -euo pipefail + STAGE="${{ github.workspace }}/coverage-objects" + DIST="TheRock/build-coverage/dist/rocm" + LLVM_BIN="${DIST}/lib/llvm/bin" + LIB_NAME="lib$(echo '${{ inputs.cmake_target }}' | tr '[:upper:]' '[:lower:]')" + mkdir -p "${STAGE}/lib" "${STAGE}/bin" + # Instrumented shared libraries for the target component (used as llvm-cov -object). + find "${DIST}" -type f -name "${LIB_NAME}*.so*" -exec cp -av {} "${STAGE}/lib/" \; + # Version-matched coverage tooling, so the report job does not depend on the dist. + cp -av "${LLVM_BIN}/llvm-profdata" "${STAGE}/bin/" + cp -av "${LLVM_BIN}/llvm-cov" "${STAGE}/bin/" + echo "Staged coverage objects:" + ls -lR "${STAGE}" + + - name: Upload coverage objects and llvm tools + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: coverage-objects-${{ inputs.project_name }}-${{ inputs.amdgpu_families }} + path: ${{ github.workspace }}/coverage-objects + if-no-files-found: error + retention-days: 1 + - name: Report if: ${{ !cancelled() }} run: | @@ -126,3 +159,85 @@ jobs: --artifact-group ${{ env.AMDGPU_FAMILIES }} \ --build-dir TheRock/build-coverage \ --upload + + # Run the standard package test flow against the coverage-instrumented build. + # Each sharded component test uploads its llvm profraw data (see + # therock-test-component.yml) which the report job below merges. + therock-coverage-test: + name: Test Coverage (${{ inputs.project_name }} | ${{ inputs.amdgpu_families }}) + needs: [therock-coverage-build] + if: ${{ inputs.test_runs_on != '' }} + uses: ./.github/workflows/therock-test-packages.yml + secrets: inherit + with: + therock_ref: ${{ inputs.therock_ref }} + projects_to_test: ${{ inputs.projects_to_test }} + amdgpu_families: ${{ inputs.amdgpu_families }} + test_runs_on: ${{ inputs.test_runs_on }} + platform: "linux" + test_type: ${{ inputs.test_type }} + coverage: true + + # Merge the profraw files from all test shards and produce the coverage report + # using the version-matched llvm tools staged by the build job. + therock-coverage-report: + name: Coverage Report (${{ inputs.project_name }} | ${{ inputs.amdgpu_families }}) + needs: [therock-coverage-test] + if: ${{ !cancelled() && needs.therock-coverage-test.result != 'skipped' }} + runs-on: ubuntu-24.04 + env: + OBJECTS_DIR: ${{ github.workspace }}/coverage-objects + PROFRAW_DIR: ${{ github.workspace }}/coverage-profraw + REPORT_DIR: ${{ github.workspace }}/coverage-report + steps: + - name: Download coverage objects and llvm tools + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + name: coverage-objects-${{ inputs.project_name }}-${{ inputs.amdgpu_families }} + path: ${{ env.OBJECTS_DIR }} + + - name: Download coverage profraw artifacts + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 + with: + pattern: coverage-profraw-${{ inputs.amdgpu_families }}-* + path: ${{ env.PROFRAW_DIR }} + merge-multiple: true + + - name: Merge profraw and generate coverage report + run: | + set -euo pipefail + mkdir -p "${REPORT_DIR}" + chmod +x "${OBJECTS_DIR}/bin/llvm-profdata" "${OBJECTS_DIR}/bin/llvm-cov" + LLVM_PROFDATA="${OBJECTS_DIR}/bin/llvm-profdata" + LLVM_COV="${OBJECTS_DIR}/bin/llvm-cov" + LIB_NAME="lib$(echo '${{ inputs.cmake_target }}' | tr '[:upper:]' '[:lower:]')" + + # Object files (instrumented libraries) for llvm-cov. + mapfile -t OBJECTS < <(find "${OBJECTS_DIR}/lib" -type f -name "*.so*") + if [[ ${#OBJECTS[@]} -eq 0 ]]; then + echo "No instrumented libraries were staged for ${LIB_NAME}." + exit 1 + fi + OBJ_ARGS=() + for obj in "${OBJECTS[@]}"; do OBJ_ARGS+=("-object" "${obj}"); done + + # Profraw files collected from every test shard. + mapfile -t PROFRAW < <(find "${PROFRAW_DIR}" -type f -name "*.profraw") + if [[ ${#PROFRAW[@]} -eq 0 ]]; then + echo "No profraw files were collected from the test runs." + exit 1 + fi + echo "Merging ${#PROFRAW[@]} profraw file(s) for objects: ${OBJECTS[*]}" + + "${LLVM_PROFDATA}" merge -sparse "${PROFRAW[@]}" -o "${REPORT_DIR}/${LIB_NAME}.profdata" + "${LLVM_COV}" report "${OBJ_ARGS[@]}" -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" | tee "${REPORT_DIR}/coverage.report" + "${LLVM_COV}" show "${OBJ_ARGS[@]}" -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" -format=html -output-dir="${REPORT_DIR}" + "${LLVM_COV}" export "${OBJ_ARGS[@]}" -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" -format=lcov > "${REPORT_DIR}/coverage.info" + + - name: Upload coverage report + if: ${{ always() }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: coverage-report-${{ inputs.project_name }}-${{ inputs.amdgpu_families }} + path: ${{ env.REPORT_DIR }} + if-no-files-found: warn diff --git a/.github/workflows/therock-ci.yml b/.github/workflows/therock-ci.yml index 0f4007ebdb45..7c39ae18857f 100644 --- a/.github/workflows/therock-ci.yml +++ b/.github/workflows/therock-ci.yml @@ -217,6 +217,8 @@ jobs: build_dir: ${{ matrix.projects.build_dir }} amdgpu_families: ${{ matrix.target_bundle.amdgpu_family }} test_runs_on: ${{ matrix.target_bundle.test_machine }} + projects_to_test: ${{ matrix.projects.projects_to_test }} + test_type: ${{ needs.setup.outputs.test_type }} therock_ci_summary: diff --git a/.github/workflows/therock-test-component.yml b/.github/workflows/therock-test-component.yml index e7c8b85e45c8..881a90bc7fd6 100644 --- a/.github/workflows/therock-test-component.yml +++ b/.github/workflows/therock-test-component.yml @@ -17,6 +17,10 @@ on: type: string component: type: string + coverage: + description: "When true, collect llvm profraw data from the test run and upload it as an artifact." + type: boolean + default: false permissions: @@ -54,6 +58,10 @@ jobs: AMDGPU_FAMILIES: ${{ inputs.amdgpu_families }} ARTIFACT_GROUP: ${{ inputs.amdgpu_families }} TEST_COMPONENT: ${{ fromJSON(inputs.component).job_name }} + # When coverage is enabled, instrumented binaries emit one profraw file per + # process/binary into this directory. Non-instrumented binaries ignore this. + COVERAGE_PROFRAW_DIR: ${{ github.workspace }}/coverage-profraw + LLVM_PROFILE_FILE: ${{ inputs.coverage && format('{0}/coverage-profraw/{1}-shard{2}-%p-%m.profraw', github.workspace, fromJSON(inputs.component).job_name, matrix.shard) || '' }} steps: - name: "Fetch 'build_tools' from repository" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -104,6 +112,10 @@ jobs: run: | python ./build_tools/print_driver_gpu_info.py + - name: Prepare coverage profile directory + if: ${{ inputs.coverage }} + run: mkdir -p "${COVERAGE_PROFRAW_DIR}" + - name: Test timeout-minutes: ${{ fromJSON(inputs.component).timeout_minutes }} env: @@ -118,6 +130,15 @@ jobs: python ./build_tools/memory_monitor.py --phase "Test ${{ fromJSON(inputs.component).job_name }}" -- \ bash -c '${{ fromJSON(inputs.component).test_script }}' 2>&1 | tee ./test_logs/test_output.log + - name: Upload coverage profraw + if: ${{ always() && inputs.coverage }} + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: coverage-profraw-${{ inputs.amdgpu_families }}-${{ fromJSON(inputs.component).job_name }}-shard${{ matrix.shard }} + path: ${{ env.COVERAGE_PROFRAW_DIR }}/*.profraw + if-no-files-found: warn + retention-days: 1 + - name: Notify Teams Channel on Failure if: ${{ failure() && !github.event.pull_request.head.repo.fork }} run: | diff --git a/.github/workflows/therock-test-packages.yml b/.github/workflows/therock-test-packages.yml index 78c80080df5c..0e323c4e3dc8 100644 --- a/.github/workflows/therock-test-packages.yml +++ b/.github/workflows/therock-test-packages.yml @@ -16,6 +16,10 @@ on: type: string test_type: type: string + coverage: + description: "When true, collect llvm profraw data from the test runs for a coverage report." + type: boolean + default: false permissions: contents: read @@ -78,4 +82,5 @@ jobs: test_runs_on: ${{ inputs.test_runs_on }} platform: ${{ inputs.platform }} component: ${{ toJSON(matrix.components) }} + coverage: ${{ inputs.coverage }} secrets: inherit From feaf41dac7931b9a7e2da00bcbd83bd3b2b3a71a Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Thu, 18 Jun 2026 04:29:25 +0000 Subject: [PATCH 53/79] fix coverage artifact paths for containerized jobs In container jobs the github.workspace expression resolves to the host path (/home/runner/_work/...) while upload-artifact uses the container workspace (/__w/...), so the staged coverage objects and profraw files were written to a different path than the upload step read, failing with "No files were found". Use $GITHUB_WORKSPACE (container path) when writing files and relative paths in upload-artifact so both sides agree. Set LLVM_PROFILE_FILE at runtime via GITHUB_ENV using $GITHUB_WORKSPACE for the same reason. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 7 +++++-- .github/workflows/therock-test-component.yml | 14 ++++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 6eaee1dc57e9..8d601534e5e6 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -107,7 +107,9 @@ jobs: - name: Stage coverage objects and llvm tools run: | set -euo pipefail - STAGE="${{ github.workspace }}/coverage-objects" + # Use $GITHUB_WORKSPACE (container path) rather than the github.workspace + # expression (host path) so the staged dir matches what upload-artifact reads. + STAGE="${GITHUB_WORKSPACE}/coverage-objects" DIST="TheRock/build-coverage/dist/rocm" LLVM_BIN="${DIST}/lib/llvm/bin" LIB_NAME="lib$(echo '${{ inputs.cmake_target }}' | tr '[:upper:]' '[:lower:]')" @@ -124,7 +126,8 @@ jobs: uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: coverage-objects-${{ inputs.project_name }}-${{ inputs.amdgpu_families }} - path: ${{ github.workspace }}/coverage-objects + # Relative path resolves against the container workspace, matching the staging step. + path: coverage-objects if-no-files-found: error retention-days: 1 diff --git a/.github/workflows/therock-test-component.yml b/.github/workflows/therock-test-component.yml index 881a90bc7fd6..377d1e16429e 100644 --- a/.github/workflows/therock-test-component.yml +++ b/.github/workflows/therock-test-component.yml @@ -58,10 +58,6 @@ jobs: AMDGPU_FAMILIES: ${{ inputs.amdgpu_families }} ARTIFACT_GROUP: ${{ inputs.amdgpu_families }} TEST_COMPONENT: ${{ fromJSON(inputs.component).job_name }} - # When coverage is enabled, instrumented binaries emit one profraw file per - # process/binary into this directory. Non-instrumented binaries ignore this. - COVERAGE_PROFRAW_DIR: ${{ github.workspace }}/coverage-profraw - LLVM_PROFILE_FILE: ${{ inputs.coverage && format('{0}/coverage-profraw/{1}-shard{2}-%p-%m.profraw', github.workspace, fromJSON(inputs.component).job_name, matrix.shard) || '' }} steps: - name: "Fetch 'build_tools' from repository" uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -114,7 +110,12 @@ jobs: - name: Prepare coverage profile directory if: ${{ inputs.coverage }} - run: mkdir -p "${COVERAGE_PROFRAW_DIR}" + run: | + # Use $GITHUB_WORKSPACE (container path) so the dir matches what + # upload-artifact reads. Instrumented binaries emit one profraw file + # per process/binary here (%p/%m); non-instrumented binaries ignore it. + mkdir -p "${GITHUB_WORKSPACE}/coverage-profraw" + echo "LLVM_PROFILE_FILE=${GITHUB_WORKSPACE}/coverage-profraw/${TEST_COMPONENT}-shard${{ matrix.shard }}-%p-%m.profraw" >> "${GITHUB_ENV}" - name: Test timeout-minutes: ${{ fromJSON(inputs.component).timeout_minutes }} @@ -135,7 +136,8 @@ jobs: uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: coverage-profraw-${{ inputs.amdgpu_families }}-${{ fromJSON(inputs.component).job_name }}-shard${{ matrix.shard }} - path: ${{ env.COVERAGE_PROFRAW_DIR }}/*.profraw + # Relative path resolves against the container workspace, matching the prepare step. + path: coverage-profraw/*.profraw if-no-files-found: warn retention-days: 1 From 63679018433552150657e06c38c75f498eb05fbb Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Thu, 18 Jun 2026 05:13:10 +0000 Subject: [PATCH 54/79] revert hipdnn coverage changes (hipRAND-only PR) This PR now targets hipRAND code coverage only; hipdnn is no longer a coverage-enabled project. Revert the projects/hipdnn build changes so the PR touches no hipdnn sources, which also stops the unrelated HipDNN Superbuild CI from running on this PR. Co-authored-by: Cursor --- projects/hipdnn/CMakeLists.txt | 2 +- projects/hipdnn/cmake/CheckToolVersion.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/hipdnn/CMakeLists.txt b/projects/hipdnn/CMakeLists.txt index f021e8fa1949..9c1b14e091a1 100644 --- a/projects/hipdnn/CMakeLists.txt +++ b/projects/hipdnn/CMakeLists.txt @@ -220,7 +220,7 @@ set(EXTRA_LINK_OPTIONS) if(HIPDNN_ENABLE_COVERAGE) message(VERBOSE "Enabling compile flags for coverage-mapping") list(PREPEND EXTRA_COMPILE_OPTIONS -fprofile-instr-generate -fcoverage-mapping) - list(PREPEND EXTRA_LINK_OPTIONS -fprofile-instr-generate) + list(PREPEND EXTRA_LINK_OPTIONS -fprofile-instr-generate -fcoverage-mapping) endif() list( diff --git a/projects/hipdnn/cmake/CheckToolVersion.cmake b/projects/hipdnn/cmake/CheckToolVersion.cmake index 24ab9de13f76..fa43b9ac4b61 100644 --- a/projects/hipdnn/cmake/CheckToolVersion.cmake +++ b/projects/hipdnn/cmake/CheckToolVersion.cmake @@ -9,7 +9,7 @@ if(NOT EXPECTED_CLANG_TIDY_VERSION) set(EXPECTED_CLANG_TIDY_VERSION "20") endif() if(NOT EXPECTED_LLVM_VERSION) - set(EXPECTED_LLVM_VERSION "22") + set(EXPECTED_LLVM_VERSION "20") endif() # Allows using any tool when the found version doesn't match expected. From 411aa2e78098dc55d2db84078e855843a3a29790 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Thu, 18 Jun 2026 08:30:12 +0000 Subject: [PATCH 55/79] make coverage report job self-sufficient for llvm tooling The staged llvm-profdata/llvm-cov are dynamically linked against libLLVM.so., which is absent on a plain runner, so the merge step failed with "error while loading shared libraries: libLLVM.so". Stage libLLVM.so next to the tools, run the report job in the build container, and point LD_LIBRARY_PATH at the staged libs. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 24 +++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 8d601534e5e6..a50c006cfe9a 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -119,6 +119,9 @@ jobs: # Version-matched coverage tooling, so the report job does not depend on the dist. cp -av "${LLVM_BIN}/llvm-profdata" "${STAGE}/bin/" cp -av "${LLVM_BIN}/llvm-cov" "${STAGE}/bin/" + # The llvm tools are dynamically linked against libLLVM; stage it next to + # them so the report job can run them via LD_LIBRARY_PATH. + find "${DIST}" -type f -name 'libLLVM.so*' -exec cp -av {} "${STAGE}/bin/" \; echo "Staged coverage objects:" ls -lR "${STAGE}" @@ -187,30 +190,35 @@ jobs: name: Coverage Report (${{ inputs.project_name }} | ${{ inputs.amdgpu_families }}) needs: [therock-coverage-test] if: ${{ !cancelled() && needs.therock-coverage-test.result != 'skipped' }} - runs-on: ubuntu-24.04 - env: - OBJECTS_DIR: ${{ github.workspace }}/coverage-objects - PROFRAW_DIR: ${{ github.workspace }}/coverage-profraw - REPORT_DIR: ${{ github.workspace }}/coverage-report + runs-on: azure-linux-scale-rocm + # Run in the build container so the staged llvm tools (and libLLVM) have a + # compatible base environment. + container: + image: ghcr.io/rocm/therock_build_manylinux_x86_64@sha256:48492540591673fdc8d51beb89bde41e7ba13cbb528f643c0a481ba42c4058f2 steps: - name: Download coverage objects and llvm tools uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: name: coverage-objects-${{ inputs.project_name }}-${{ inputs.amdgpu_families }} - path: ${{ env.OBJECTS_DIR }} + path: coverage-objects - name: Download coverage profraw artifacts uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: pattern: coverage-profraw-${{ inputs.amdgpu_families }}-* - path: ${{ env.PROFRAW_DIR }} + path: coverage-profraw merge-multiple: true - name: Merge profraw and generate coverage report run: | set -euo pipefail + OBJECTS_DIR="${GITHUB_WORKSPACE}/coverage-objects" + PROFRAW_DIR="${GITHUB_WORKSPACE}/coverage-profraw" + REPORT_DIR="${GITHUB_WORKSPACE}/coverage-report" mkdir -p "${REPORT_DIR}" chmod +x "${OBJECTS_DIR}/bin/llvm-profdata" "${OBJECTS_DIR}/bin/llvm-cov" + # The llvm tools are dynamically linked against the staged libLLVM.so. + export LD_LIBRARY_PATH="${OBJECTS_DIR}/bin:${LD_LIBRARY_PATH:-}" LLVM_PROFDATA="${OBJECTS_DIR}/bin/llvm-profdata" LLVM_COV="${OBJECTS_DIR}/bin/llvm-cov" LIB_NAME="lib$(echo '${{ inputs.cmake_target }}' | tr '[:upper:]' '[:lower:]')" @@ -242,5 +250,5 @@ jobs: uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: coverage-report-${{ inputs.project_name }}-${{ inputs.amdgpu_families }} - path: ${{ env.REPORT_DIR }} + path: coverage-report if-no-files-found: warn From 5a9bd2751001c874baf4423a61b1e0d3f801e320 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Thu, 18 Jun 2026 09:18:16 +0000 Subject: [PATCH 56/79] use a current TheRock ref for the coverage test stage The build stage needs the (unmerged) export ref that ships llvm-cov/llvm-profdata in the dist, but that ref predates build_tools/github_actions/cleanup_processes.sh, so the shared test flow failed in its post-job cleanup. Run the test stage on a current TheRock commit (2d417fa) that has the cleanup script. The report stage uses the build-staged llvm tools, so it is unaffected by the test ref. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index a50c006cfe9a..482659a48d70 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -19,11 +19,19 @@ on: type: string test_type: type: string - # TheRock revision pinned to a commit that exports llvm-cov / llvm-profdata - # in the dist. Kept as an input so the build, test and report stages stay in sync. + # TheRock revision for the BUILD stage. Pinned to a commit that exports + # llvm-cov / llvm-profdata in the dist (a feature branch not yet on main). therock_ref: type: string default: 6afcd5ac5298e9a5cdb3d2c45ae7605739ad2b94 + # TheRock revision for the TEST stage. Uses a current commit (which has + # build_tools/github_actions/cleanup_processes.sh) so the shared test flow + # does not fail in its post-job cleanup. The build ref above lacks that + # script, and current TheRock lacks the llvm export, so the two stages use + # different refs until the export work lands on main. + test_therock_ref: + type: string + default: 2d417fa49bc4e657bcbcf0ae549238784175f0fe permissions: contents: read @@ -176,7 +184,7 @@ jobs: uses: ./.github/workflows/therock-test-packages.yml secrets: inherit with: - therock_ref: ${{ inputs.therock_ref }} + therock_ref: ${{ inputs.test_therock_ref }} projects_to_test: ${{ inputs.projects_to_test }} amdgpu_families: ${{ inputs.amdgpu_families }} test_runs_on: ${{ inputs.test_runs_on }} From d7cb3ee0e4b8399e233983319bffa7ff8ff95160 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Thu, 18 Jun 2026 11:05:12 +0000 Subject: [PATCH 57/79] run coverage report step under bash The merge/report step uses bash-only constructs (mapfile, process substitution), but ran under the container's default sh, failing with "syntax error near unexpected token '<'". Pin the step shell to bash. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 482659a48d70..ed462c5e08a5 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -218,6 +218,7 @@ jobs: merge-multiple: true - name: Merge profraw and generate coverage report + shell: bash run: | set -euo pipefail OBJECTS_DIR="${GITHUB_WORKSPACE}/coverage-objects" From 2bfee8aafa14de65a736abd9f21d6482f208c20b Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Fri, 19 Jun 2026 06:46:34 +0000 Subject: [PATCH 58/79] stage llvm tool dependency libraries for the coverage report llvm-profdata/llvm-cov link libLLVM plus TheRock's bundled sysdeps (librocm_sysdeps_z, etc.), so the report job failed with "error while loading shared libraries: librocm_sysdeps_z.so.1". Stage the whole llvm lib dir and all librocm_sysdeps_* next to the tools, and add ldd diagnostics to both stages. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index ed462c5e08a5..11b22c05c1c0 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -127,11 +127,18 @@ jobs: # Version-matched coverage tooling, so the report job does not depend on the dist. cp -av "${LLVM_BIN}/llvm-profdata" "${STAGE}/bin/" cp -av "${LLVM_BIN}/llvm-cov" "${STAGE}/bin/" - # The llvm tools are dynamically linked against libLLVM; stage it next to - # them so the report job can run them via LD_LIBRARY_PATH. + # The llvm tools dynamically link libLLVM plus TheRock's bundled sysdeps + # (e.g. librocm_sysdeps_z). Stage the whole llvm lib dir and all sysdeps + # next to the tools so the report job can run them via LD_LIBRARY_PATH. + if [[ -d "${DIST}/lib/llvm/lib" ]]; then + find "${DIST}/lib/llvm/lib" -maxdepth 1 -name '*.so*' -exec cp -av {} "${STAGE}/bin/" \; + fi find "${DIST}" -type f -name 'libLLVM.so*' -exec cp -av {} "${STAGE}/bin/" \; + find "${DIST}" -type f -name 'librocm_sysdeps_*.so*' -exec cp -av {} "${STAGE}/bin/" \; echo "Staged coverage objects:" ls -lR "${STAGE}" + echo "llvm-profdata dependencies (in build env):" + ldd "${STAGE}/bin/llvm-profdata" || true - name: Upload coverage objects and llvm tools uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 @@ -226,12 +233,15 @@ jobs: REPORT_DIR="${GITHUB_WORKSPACE}/coverage-report" mkdir -p "${REPORT_DIR}" chmod +x "${OBJECTS_DIR}/bin/llvm-profdata" "${OBJECTS_DIR}/bin/llvm-cov" - # The llvm tools are dynamically linked against the staged libLLVM.so. + # The llvm tools are dynamically linked against the staged libLLVM.so + # and TheRock's bundled sysdeps, all staged in bin/. export LD_LIBRARY_PATH="${OBJECTS_DIR}/bin:${LD_LIBRARY_PATH:-}" LLVM_PROFDATA="${OBJECTS_DIR}/bin/llvm-profdata" LLVM_COV="${OBJECTS_DIR}/bin/llvm-cov" LIB_NAME="lib$(echo '${{ inputs.cmake_target }}' | tr '[:upper:]' '[:lower:]')" + echo "llvm-profdata dependencies:"; ldd "${LLVM_PROFDATA}" || true + # Object files (instrumented libraries) for llvm-cov. mapfile -t OBJECTS < <(find "${OBJECTS_DIR}/lib" -type f -name "*.so*") if [[ ${#OBJECTS[@]} -eq 0 ]]; then From 778a9b0cf59d381a736428bd3ea286eb2f4e755f Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Fri, 19 Jun 2026 09:01:58 +0000 Subject: [PATCH 59/79] stage SONAME symlinks for coverage llvm tool dependencies The sysdeps copy used find -type f, which skipped the SONAME symlinks (librocm_sysdeps_z.so.1 -> ...1.3.2), so the loader still reported "librocm_sysdeps_z.so.1: cannot open shared object file" even though the versioned file was staged. Drop -type f so the symlinks are staged too. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 11b22c05c1c0..19da99b50545 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -133,8 +133,11 @@ jobs: if [[ -d "${DIST}/lib/llvm/lib" ]]; then find "${DIST}/lib/llvm/lib" -maxdepth 1 -name '*.so*' -exec cp -av {} "${STAGE}/bin/" \; fi - find "${DIST}" -type f -name 'libLLVM.so*' -exec cp -av {} "${STAGE}/bin/" \; - find "${DIST}" -type f -name 'librocm_sysdeps_*.so*' -exec cp -av {} "${STAGE}/bin/" \; + # Note: do NOT use -type f here, otherwise the SONAME symlinks (e.g. + # librocm_sysdeps_z.so.1 -> librocm_sysdeps_z.so.1.3.2) are skipped and + # the loader cannot resolve the dependency. + find "${DIST}" -name 'libLLVM.so*' -exec cp -av {} "${STAGE}/bin/" \; + find "${DIST}" -name 'librocm_sysdeps_*.so*' -exec cp -av {} "${STAGE}/bin/" \; echo "Staged coverage objects:" ls -lR "${STAGE}" echo "llvm-profdata dependencies (in build env):" From 13a81b4e7bc47c948283bcfcded5c0b187ffa87f Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Sat, 20 Jun 2026 14:36:15 +0000 Subject: [PATCH 60/79] annotate coverage HTML, upload to Codecov, and emit a paths/links file - Check out the sources in the report job so llvm-cov show can annotate the HTML report (previously the source file could not be found). - Make the lcov paths repo-relative and upload coverage.info to Codecov under the project flag (non-fatal), so the report is browsable online. - Generate coverage-report-links.txt listing the report outputs, instrumented source/objects, tooling libraries, tests executed, the TheRock build/pack location, and the report upload/download locations; also surface a summary with the run/Codecov links in the job summary. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 116 +++++++++++++++++++++- 1 file changed, 114 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 19da99b50545..8d2340c0c9fe 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -213,7 +213,16 @@ jobs: # compatible base environment. container: image: ghcr.io/rocm/therock_build_manylinux_x86_64@sha256:48492540591673fdc8d51beb89bde41e7ba13cbb528f643c0a481ba42c4058f2 + env: + REPORT_ARTIFACT: coverage-report-${{ inputs.project_name }}-${{ inputs.amdgpu_families }} + RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} steps: + # Check out the sources so llvm-cov can annotate the HTML report. The build + # embeds absolute source paths under the workspace, so checking out here (at + # the workspace root) makes those paths resolve. + - name: Checkout rocm-libraries (for source annotation) + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Download coverage objects and llvm tools uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: @@ -229,6 +238,17 @@ jobs: - name: Merge profraw and generate coverage report shell: bash + env: + AMDGPU_FAMILIES: ${{ inputs.amdgpu_families }} + PROJECT_NAME: ${{ inputs.project_name }} + CMAKE_TARGET: ${{ inputs.cmake_target }} + PROJECTS_TO_TEST: ${{ inputs.projects_to_test }} + BUILD_DIR: ${{ inputs.build_dir }} + BUILD_THEROCK_REF: ${{ inputs.therock_ref }} + TEST_THEROCK_REF: ${{ inputs.test_therock_ref }} + REPO: ${{ github.repository }} + COMMIT_SHA: ${{ github.sha }} + PR_NUMBER: ${{ github.event.pull_request.number }} run: | set -euo pipefail OBJECTS_DIR="${GITHUB_WORKSPACE}/coverage-objects" @@ -241,7 +261,7 @@ jobs: export LD_LIBRARY_PATH="${OBJECTS_DIR}/bin:${LD_LIBRARY_PATH:-}" LLVM_PROFDATA="${OBJECTS_DIR}/bin/llvm-profdata" LLVM_COV="${OBJECTS_DIR}/bin/llvm-cov" - LIB_NAME="lib$(echo '${{ inputs.cmake_target }}' | tr '[:upper:]' '[:lower:]')" + LIB_NAME="lib$(echo "${CMAKE_TARGET}" | tr '[:upper:]' '[:lower:]')" echo "llvm-profdata dependencies:"; ldd "${LLVM_PROFDATA}" || true @@ -267,10 +287,102 @@ jobs: "${LLVM_COV}" show "${OBJ_ARGS[@]}" -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" -format=html -output-dir="${REPORT_DIR}" "${LLVM_COV}" export "${OBJ_ARGS[@]}" -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" -format=lcov > "${REPORT_DIR}/coverage.info" + # Make lcov paths repo-relative so Codecov can map them to the source tree. + sed -i "s|${GITHUB_WORKSPACE}/||g" "${REPORT_DIR}/coverage.info" + + # Source files referenced by the coverage data (repo-relative). + mapfile -t SOURCES < <("${LLVM_COV}" export "${OBJ_ARGS[@]}" \ + -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" -format=lcov \ + | sed -n 's|^SF:||p' | sed "s|${GITHUB_WORKSPACE}/||g" | sort -u) + + # Generate the reference text file with all relevant paths and links. + LINKS_FILE="${REPORT_DIR}/coverage-report-links.txt" + { + echo "${PROJECT_NAME} Code Coverage - Paths and Links" + echo "==================================================" + echo "Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)" + echo "Repository: ${REPO}" + echo "Commit: ${COMMIT_SHA}" + echo "Pull request: ${GITHUB_SERVER_URL}/${REPO}/pull/${PR_NUMBER:-N/A}" + echo "Workflow run: ${RUN_URL}" + echo "GPU family: ${AMDGPU_FAMILIES}" + echo + echo "[TheRock - where ${PROJECT_NAME} was packed for coverage]" + echo " Build TheRock ref: ${BUILD_THEROCK_REF}" + echo " Test TheRock ref: ${TEST_THEROCK_REF}" + echo " Build dir: ${BUILD_DIR}" + echo + echo "[Instrumented code - source file(s)]" + for s in "${SOURCES[@]}"; do echo " ${s}"; done + echo + echo "[Instrumented code - library object(s) used by llvm-cov]" + for o in "${OBJECTS[@]}"; do echo " ${o#${GITHUB_WORKSPACE}/}"; done + echo + echo "[Libraries used by the coverage tooling]" + for f in $(find "${OBJECTS_DIR}/bin" -maxdepth 1 -type f | sort); do echo " ${f#${GITHUB_WORKSPACE}/}"; done + echo + echo "[Tests executed against the instrumented build]" + echo " projects_to_test: ${PROJECTS_TO_TEST}" + echo " Test driver: ctest (via .github/workflows/therock-test-component.yml)" + echo " profraw merged: ${#PROFRAW[@]} file(s)" + echo " Test stage: ${RUN_URL} (job 'Test Coverage (${PROJECT_NAME} | ${AMDGPU_FAMILIES})')" + echo + echo "[Coverage report outputs]" + echo " HTML report: coverage-report/index.html" + echo " Text summary: coverage-report/coverage.report" + echo " LCOV: coverage-report/coverage.info" + echo " Merged profile: coverage-report/${LIB_NAME}.profdata" + echo + echo "[Report upload / download]" + echo " Artifact name: ${REPORT_ARTIFACT}" + echo " Download from: ${RUN_URL} (Artifacts section)" + echo " Codecov: https://app.codecov.io/gh/${REPO}/pull/${PR_NUMBER:-} (flag: ${CMAKE_TARGET})" + } > "${LINKS_FILE}" + + echo "----- ${LINKS_FILE} -----" + cat "${LINKS_FILE}" + - name: Upload coverage report if: ${{ always() }} uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: - name: coverage-report-${{ inputs.project_name }}-${{ inputs.amdgpu_families }} + name: ${{ env.REPORT_ARTIFACT }} path: coverage-report if-no-files-found: warn + + - name: Upload coverage to Codecov + if: ${{ always() }} + continue-on-error: true + shell: bash + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + run: | + set -x + if ! curl -Os https://cli.codecov.io/latest/linux/codecov; then + echo "Could not download the Codecov CLI; skipping upload." + exit 0 + fi + chmod +x codecov + ./codecov upload-process \ + --disable-search \ + --file coverage-report/coverage.info \ + --flag "${{ inputs.cmake_target }}" \ + --name "${{ inputs.cmake_target }}-${{ inputs.amdgpu_families }}" \ + --slug "${{ github.repository }}" \ + || echo "Codecov upload failed (non-fatal)." + + - name: Coverage report summary + if: ${{ always() }} + shell: bash + run: | + { + echo "### ${{ inputs.project_name }} coverage (${{ inputs.amdgpu_families }})" + echo "" + if [[ -f coverage-report/coverage.report ]]; then + echo '```' + tail -n 3 coverage-report/coverage.report + echo '```' + fi + echo "- Report artifact: \`${REPORT_ARTIFACT}\` (download from [run artifacts](${RUN_URL}))" + echo "- Codecov: https://app.codecov.io/gh/${{ github.repository }}/pull/${{ github.event.pull_request.number }} (flag: ${{ inputs.cmake_target }})" + } >> "${GITHUB_STEP_SUMMARY}" From 4107d19e63b0bb020ebe1e9078e6fa0e37526e36 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Mon, 22 Jun 2026 06:38:56 +0000 Subject: [PATCH 61/79] adopt documented coverage structure (YAML + metadata + coverage_runner) for hipRAND Implement the Phase-1 layout from TheRock #3761's coverage design docs, adapted to hipRAND and the proven build/test pipeline: - test_categories_coverage.yaml: per-project coverage config (objects, ignore_filename_regex, llvm_profile_pattern, test_category) for hiprand. - .github/scripts/export_coverage_metadata.py: build-time export of coverage_metadata.json from the YAML config + build tree. - .github/scripts/coverage_runner.py: metadata-driven merge/report with a --skip-tests mode (tests run in the shared package-test stage); resolves objects and llvm tools by name so it works against the staged artifact. - therock-ci-coverage.yml: build job exports + ships coverage_metadata.json with the staged objects; report job drives merge/report via coverage_runner.py and now applies the YAML ignore_filename_regex. Co-authored-by: Cursor --- .github/scripts/coverage_runner.py | 189 ++++++++++++++++++++ .github/scripts/export_coverage_metadata.py | 116 ++++++++++++ .github/workflows/therock-ci-coverage.yml | 80 ++++----- test_categories_coverage.yaml | 26 +++ 4 files changed, 371 insertions(+), 40 deletions(-) create mode 100644 .github/scripts/coverage_runner.py create mode 100644 .github/scripts/export_coverage_metadata.py create mode 100644 test_categories_coverage.yaml diff --git a/.github/scripts/coverage_runner.py b/.github/scripts/coverage_runner.py new file mode 100644 index 000000000000..4ec9fb9d48ab --- /dev/null +++ b/.github/scripts/coverage_runner.py @@ -0,0 +1,189 @@ +#!/usr/bin/env python3 +"""Run tests with coverage profiling and/or generate coverage reports. + +This is the report-time half of the coverage flow described in TheRock's coverage +design docs. It is driven by the ``coverage_metadata.json`` produced by +``export_coverage_metadata.py`` and can either: + + * run tests to produce profraw files (default), or + * skip tests and merge pre-collected profraw files (``--skip-tests``), which is + how the GitHub Actions flow uses it (tests run in the shared package-test + workflow and upload their profraw). + +Object and llvm tool locations are resolved by name within ``--build-dir`` so the +script works whether it is pointed at a full build/dist tree or a staged artifact. +""" +import argparse +import json +import logging +import os +import subprocess +from pathlib import Path + +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") + + +def find_tool(build_dir: Path, name: str) -> Path | None: + """Locate an executable ``name`` inside ``build_dir`` (prefer bin/ dirs).""" + candidates = [p for p in build_dir.rglob(name) if p.is_file()] + if not candidates: + return None + candidates.sort(key=lambda p: (0 if p.parent.name == "bin" else 1, len(str(p)))) + return candidates[0] + + +def resolve_objects(build_dir: Path, metadata: dict) -> list[Path]: + """Resolve coverage object files (libraries + test binaries) within build_dir.""" + objects: list[Path] = [] + + # Prefer the explicit relative paths recorded at export time, if present. + rel_objects = [] + for kind in ("libraries", "test_binaries"): + rel_objects.extend(metadata.get("coverage_objects", {}).get(kind, []) or []) + for rel in rel_objects: + candidate = build_dir / rel + if candidate.is_file(): + objects.append(candidate) + + # Fall back to resolving by basename (handles a different layout than export). + if not objects: + basenames = [] + for kind in ("libraries", "test_binaries"): + basenames.extend(metadata.get("object_basenames", {}).get(kind, []) or []) + for basename in basenames: + hits = [p for p in build_dir.rglob(f"{basename}*") if p.is_file()] + # Prefer concrete files (e.g. libhiprand.so.1.1) over bare symlinks, + # and the most specific (longest) name. + hits.sort(key=lambda p: (not p.is_symlink(), len(p.name)), reverse=True) + if hits: + objects.append(hits[0]) + + # De-duplicate while preserving order. + seen, unique = set(), [] + for obj in objects: + key = obj.resolve() + if key not in seen: + seen.add(key) + unique.append(obj) + return unique + + +def set_coverage_environment(metadata: dict, coverage_dir: Path): + pattern = metadata.get("llvm_profile_pattern", "%m") + profraw_dir = coverage_dir / "profraw" + profraw_dir.mkdir(parents=True, exist_ok=True) + profile_file = str(profraw_dir / f"{pattern}.profraw") + os.environ["LLVM_PROFILE_FILE"] = profile_file + logging.info("Set LLVM_PROFILE_FILE=%s", profile_file) + + +def run_tests(test_dir: Path, metadata: dict) -> int: + category = metadata.get("test_category", "") + cmd = ["ctest", "--test-dir", str(test_dir), "--output-on-failure", + "--parallel", "8", "--timeout", "7200"] + if category: + cmd += ["-L", category] + logging.info("Running tests: %s", " ".join(cmd)) + return subprocess.run(cmd).returncode + + +def merge_profraw_files(llvm_profdata: Path, profraw_dir: Path, out_path: Path) -> Path: + profraw_files = [str(p) for p in profraw_dir.rglob("*.profraw")] + if not profraw_files: + raise RuntimeError(f"No .profraw files found under {profraw_dir}") + logging.info("Merging %d profraw file(s)", len(profraw_files)) + subprocess.run([str(llvm_profdata), "merge", "-sparse", "-o", str(out_path), + *profraw_files], check=True) + logging.info("Created %s", out_path) + return out_path + + +def generate_reports(llvm_cov: Path, llvm_cxxfilt: Path | None, objects: list[Path], + ignore_regex: str, profdata: Path, coverage_dir: Path, project: str): + object_args: list[str] = [] + for obj in objects: + object_args += ["-object", str(obj)] + ignore_args = [f"-ignore-filename-regex={ignore_regex}"] if ignore_regex else [] + + text_report = coverage_dir / f"code_cov_{project}.report" + logging.info("Generating text report -> %s", text_report) + with open(text_report, "w") as f: + subprocess.run([str(llvm_cov), "report", *object_args, + f"-instr-profile={profdata}", *ignore_args], stdout=f, check=True) + print(text_report.read_text()) + + logging.info("Generating HTML report -> %s", coverage_dir) + show_cmd = [str(llvm_cov), "show", *object_args, f"-instr-profile={profdata}", + *ignore_args, "--format=html", f"--output-dir={coverage_dir}"] + if llvm_cxxfilt is not None: + show_cmd.insert(2, f"-Xdemangler={llvm_cxxfilt}") + subprocess.run(show_cmd, check=True) + + lcov_file = coverage_dir / "coverage.info" + logging.info("Generating LCOV export -> %s", lcov_file) + with open(lcov_file, "w") as f: + subprocess.run([str(llvm_cov), "export", *object_args, + f"-instr-profile={profdata}", *ignore_args, "--format=lcov"], + stdout=f, check=True) + + +def main(): + parser = argparse.ArgumentParser(description="Run/aggregate coverage and report") + parser.add_argument("--build-dir", type=Path, required=True, + help="Tree to resolve coverage objects and llvm tools from") + parser.add_argument("--metadata", type=Path, required=True, + help="coverage_metadata.json from export_coverage_metadata.py") + parser.add_argument("--coverage-dir", type=Path, required=True, + help="Output directory for reports") + parser.add_argument("--profraw-dir", type=Path, default=None, + help="Directory of profraw files (default: /profraw)") + parser.add_argument("--test-dir", type=Path, default=None, + help="ctest directory (default: --build-dir) when running tests") + parser.add_argument("--skip-tests", action="store_true", + help="Do not run tests; merge existing profraw files") + args = parser.parse_args() + + with open(args.metadata) as f: + metadata = json.load(f) + project = metadata.get("project", "project") + logging.info("Coverage for project: %s", project) + + args.coverage_dir.mkdir(parents=True, exist_ok=True) + profraw_dir = args.profraw_dir or (args.coverage_dir / "profraw") + + # Resolve tooling. Tools link libLLVM and bundled sysdeps that sit next to + # them, so add their directory to LD_LIBRARY_PATH. + llvm_profdata = find_tool(args.build_dir, "llvm-profdata") + llvm_cov = find_tool(args.build_dir, "llvm-cov") + llvm_cxxfilt = find_tool(args.build_dir, "llvm-cxxfilt") + if llvm_profdata is None or llvm_cov is None: + raise FileNotFoundError( + f"llvm-profdata/llvm-cov not found under {args.build_dir}") + tool_dirs = {str(t.parent) for t in (llvm_profdata, llvm_cov, llvm_cxxfilt) if t} + os.environ["LD_LIBRARY_PATH"] = os.pathsep.join( + [*tool_dirs, os.environ.get("LD_LIBRARY_PATH", "")]) + for t in (llvm_profdata, llvm_cov, llvm_cxxfilt): + if t: + t.chmod(0o755) + + objects = resolve_objects(args.build_dir, metadata) + if not objects: + raise RuntimeError("No coverage object files could be resolved.") + logging.info("Coverage objects: %s", ", ".join(str(o) for o in objects)) + + if not args.skip_tests: + set_coverage_environment(metadata, args.coverage_dir) + rc = run_tests(args.test_dir or args.build_dir, metadata) + if rc != 0: + logging.warning("Tests exited with %d; continuing with coverage.", rc) + + profdata = merge_profraw_files(llvm_profdata, profraw_dir, + args.coverage_dir / f"{project}.profdata") + generate_reports(llvm_cov, llvm_cxxfilt, objects, + metadata.get("ignore_filename_regex", ""), profdata, + args.coverage_dir, project) + logging.info("Coverage generation complete.") + + +if __name__ == "__main__": + main() diff --git a/.github/scripts/export_coverage_metadata.py b/.github/scripts/export_coverage_metadata.py new file mode 100644 index 000000000000..186625da8aca --- /dev/null +++ b/.github/scripts/export_coverage_metadata.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python3 +"""Export coverage metadata from a build tree to JSON for use in the report job. + +This is the build-time half of the coverage flow described in TheRock's coverage +design docs. It reads ``test_categories_coverage.yaml``, verifies the configured +coverage objects exist in the build/dist tree, and writes a ``coverage_metadata.json`` +that ``coverage_runner.py`` consumes later to merge profraw files and produce a report. + +Object/tool names are recorded by file name (basename). The report job locates the +actual files in whatever layout it has (build dist or staged artifact), so version +suffixes such as ``libhiprand.so.1.1`` are handled by the runner. +""" +import argparse +import json +import logging +from pathlib import Path + +import yaml + +logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s") + + +def load_coverage_config(config_path: Path) -> dict: + with open(config_path) as f: + return yaml.safe_load(f) + + +def resolve_project_key(config: dict, project: str) -> str: + """Return the config key for ``project`` (case-insensitive).""" + projects = config.get("projects", {}) + if project in projects: + return project + lowered = project.lower() + if lowered in projects: + return lowered + raise ValueError( + f"Project '{project}' not found in coverage config " + f"(known: {sorted(projects)})" + ) + + +def find_by_basename(build_dir: Path, basename: str) -> list[str]: + """Find files in ``build_dir`` whose name starts with ``basename``. + + Matches versioned shared libraries (e.g. libhiprand.so -> libhiprand.so.1.1). + Returns paths relative to ``build_dir`` so the metadata is location independent. + """ + matches: list[str] = [] + for path in build_dir.rglob(f"{basename}*"): + if path.is_file(): + matches.append(str(path.relative_to(build_dir))) + return sorted(set(matches)) + + +def export_metadata(build_dir: Path, project: str, config_path: Path, output_path: Path): + config = load_coverage_config(config_path) + key = resolve_project_key(config, project) + project_config = config["projects"][key] + + if not project_config.get("enabled", False): + logging.info("Coverage disabled for %s; nothing to export.", key) + return + + objects = project_config.get("coverage_objects", {}) + found = {"libraries": [], "test_binaries": []} + for kind in ("libraries", "test_binaries"): + for basename in objects.get(kind, []) or []: + hits = find_by_basename(build_dir, basename) + if hits: + found[kind].extend(hits) + else: + logging.warning("Coverage object not found for %s: %s", kind, basename) + + metadata = { + "project": key, + "coverage_objects": found, + # Basenames are kept so the runner can re-resolve in a different layout. + "object_basenames": { + "libraries": objects.get("libraries", []) or [], + "test_binaries": objects.get("test_binaries", []) or [], + }, + "ignore_filename_regex": project_config.get("ignore_filename_regex", ""), + "llvm_profile_pattern": project_config.get("llvm_profile_pattern", "%m"), + "test_category": project_config.get("test_category", ""), + "llvm_tools": { + "llvm_profdata": "llvm-profdata", + "llvm_cov": "llvm-cov", + "llvm_cxxfilt": "llvm-cxxfilt", + }, + } + + output_path.parent.mkdir(parents=True, exist_ok=True) + with open(output_path, "w") as f: + json.dump(metadata, f, indent=2) + + logging.info("Exported coverage metadata to %s", output_path) + logging.info(" Libraries found: %d", len(found["libraries"])) + logging.info(" Test binaries found: %d", len(found["test_binaries"])) + + +def main(): + parser = argparse.ArgumentParser(description="Export coverage metadata to JSON") + parser.add_argument("--build-dir", type=Path, required=True, + help="Build/dist tree to search for coverage objects") + parser.add_argument("--project", type=str, required=True, + help="Project key or name (e.g. hiprand / HIPRAND)") + parser.add_argument("--config", type=Path, required=True, + help="Path to test_categories_coverage.yaml") + parser.add_argument("--output", type=Path, required=True, + help="Output coverage_metadata.json path") + args = parser.parse_args() + export_metadata(args.build_dir, args.project, args.config, args.output) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index 8d2340c0c9fe..c506ba0a65a1 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -138,11 +138,25 @@ jobs: # the loader cannot resolve the dependency. find "${DIST}" -name 'libLLVM.so*' -exec cp -av {} "${STAGE}/bin/" \; find "${DIST}" -name 'librocm_sysdeps_*.so*' -exec cp -av {} "${STAGE}/bin/" \; + # Demangler used by llvm-cov show for readable HTML. + cp -av "${LLVM_BIN}/llvm-cxxfilt" "${STAGE}/bin/" 2>/dev/null || true echo "Staged coverage objects:" ls -lR "${STAGE}" echo "llvm-profdata dependencies (in build env):" ldd "${STAGE}/bin/llvm-profdata" || true + - name: Export coverage metadata + run: | + set -euo pipefail + python3 -m pip install --quiet pyyaml || true + # Written into the staged dir so it travels with the coverage objects. + python3 .github/scripts/export_coverage_metadata.py \ + --build-dir TheRock/build-coverage \ + --project "${{ inputs.project_name }}" \ + --config test_categories_coverage.yaml \ + --output "${GITHUB_WORKSPACE}/coverage-objects/coverage_metadata.json" + cat "${GITHUB_WORKSPACE}/coverage-objects/coverage_metadata.json" + - name: Upload coverage objects and llvm tools uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: @@ -255,45 +269,26 @@ jobs: PROFRAW_DIR="${GITHUB_WORKSPACE}/coverage-profraw" REPORT_DIR="${GITHUB_WORKSPACE}/coverage-report" mkdir -p "${REPORT_DIR}" - chmod +x "${OBJECTS_DIR}/bin/llvm-profdata" "${OBJECTS_DIR}/bin/llvm-cov" - # The llvm tools are dynamically linked against the staged libLLVM.so - # and TheRock's bundled sysdeps, all staged in bin/. - export LD_LIBRARY_PATH="${OBJECTS_DIR}/bin:${LD_LIBRARY_PATH:-}" - LLVM_PROFDATA="${OBJECTS_DIR}/bin/llvm-profdata" - LLVM_COV="${OBJECTS_DIR}/bin/llvm-cov" - LIB_NAME="lib$(echo "${CMAKE_TARGET}" | tr '[:upper:]' '[:lower:]')" - - echo "llvm-profdata dependencies:"; ldd "${LLVM_PROFDATA}" || true + METADATA="${OBJECTS_DIR}/coverage_metadata.json" - # Object files (instrumented libraries) for llvm-cov. - mapfile -t OBJECTS < <(find "${OBJECTS_DIR}/lib" -type f -name "*.so*") - if [[ ${#OBJECTS[@]} -eq 0 ]]; then - echo "No instrumented libraries were staged for ${LIB_NAME}." - exit 1 - fi - OBJ_ARGS=() - for obj in "${OBJECTS[@]}"; do OBJ_ARGS+=("-object" "${obj}"); done - - # Profraw files collected from every test shard. - mapfile -t PROFRAW < <(find "${PROFRAW_DIR}" -type f -name "*.profraw") - if [[ ${#PROFRAW[@]} -eq 0 ]]; then - echo "No profraw files were collected from the test runs." - exit 1 - fi - echo "Merging ${#PROFRAW[@]} profraw file(s) for objects: ${OBJECTS[*]}" - - "${LLVM_PROFDATA}" merge -sparse "${PROFRAW[@]}" -o "${REPORT_DIR}/${LIB_NAME}.profdata" - "${LLVM_COV}" report "${OBJ_ARGS[@]}" -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" | tee "${REPORT_DIR}/coverage.report" - "${LLVM_COV}" show "${OBJ_ARGS[@]}" -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" -format=html -output-dir="${REPORT_DIR}" - "${LLVM_COV}" export "${OBJ_ARGS[@]}" -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" -format=lcov > "${REPORT_DIR}/coverage.info" + # Drive merge + report from the build-time metadata. --skip-tests: the + # tests already ran in the package-test stage and uploaded their profraw. + python3 .github/scripts/coverage_runner.py \ + --build-dir "${OBJECTS_DIR}" \ + --metadata "${METADATA}" \ + --coverage-dir "${REPORT_DIR}" \ + --profraw-dir "${PROFRAW_DIR}" \ + --skip-tests # Make lcov paths repo-relative so Codecov can map them to the source tree. - sed -i "s|${GITHUB_WORKSPACE}/||g" "${REPORT_DIR}/coverage.info" + if [[ -f "${REPORT_DIR}/coverage.info" ]]; then + sed -i "s|${GITHUB_WORKSPACE}/||g" "${REPORT_DIR}/coverage.info" + fi - # Source files referenced by the coverage data (repo-relative). - mapfile -t SOURCES < <("${LLVM_COV}" export "${OBJ_ARGS[@]}" \ - -instr-profile="${REPORT_DIR}/${LIB_NAME}.profdata" -format=lcov \ - | sed -n 's|^SF:||p' | sed "s|${GITHUB_WORKSPACE}/||g" | sort -u) + # Collect details for the reference links file. + mapfile -t SOURCES < <(sed -n 's|^SF:||p' "${REPORT_DIR}/coverage.info" 2>/dev/null | sort -u) + mapfile -t OBJECTS < <(find "${OBJECTS_DIR}/lib" -type f -name "*.so*" 2>/dev/null | sort) + PROFRAW_COUNT=$(find "${PROFRAW_DIR}" -type f -name '*.profraw' 2>/dev/null | wc -l) # Generate the reference text file with all relevant paths and links. LINKS_FILE="${REPORT_DIR}/coverage-report-links.txt" @@ -307,6 +302,10 @@ jobs: echo "Workflow run: ${RUN_URL}" echo "GPU family: ${AMDGPU_FAMILIES}" echo + echo "[Coverage config]" + echo " Config: test_categories_coverage.yaml -> coverage_metadata.json" + echo " Runner: .github/scripts/coverage_runner.py (--skip-tests)" + echo echo "[TheRock - where ${PROJECT_NAME} was packed for coverage]" echo " Build TheRock ref: ${BUILD_THEROCK_REF}" echo " Test TheRock ref: ${TEST_THEROCK_REF}" @@ -324,14 +323,14 @@ jobs: echo "[Tests executed against the instrumented build]" echo " projects_to_test: ${PROJECTS_TO_TEST}" echo " Test driver: ctest (via .github/workflows/therock-test-component.yml)" - echo " profraw merged: ${#PROFRAW[@]} file(s)" + echo " profraw merged: ${PROFRAW_COUNT} file(s)" echo " Test stage: ${RUN_URL} (job 'Test Coverage (${PROJECT_NAME} | ${AMDGPU_FAMILIES})')" echo echo "[Coverage report outputs]" echo " HTML report: coverage-report/index.html" - echo " Text summary: coverage-report/coverage.report" + echo " Text summary: coverage-report/code_cov_$(echo "${CMAKE_TARGET}" | tr '[:upper:]' '[:lower:]').report" echo " LCOV: coverage-report/coverage.info" - echo " Merged profile: coverage-report/${LIB_NAME}.profdata" + echo " Merged profile: coverage-report/$(echo "${CMAKE_TARGET}" | tr '[:upper:]' '[:lower:]').profdata" echo echo "[Report upload / download]" echo " Artifact name: ${REPORT_ARTIFACT}" @@ -378,9 +377,10 @@ jobs: { echo "### ${{ inputs.project_name }} coverage (${{ inputs.amdgpu_families }})" echo "" - if [[ -f coverage-report/coverage.report ]]; then + report_file="$(find coverage-report -maxdepth 1 -name 'code_cov_*.report' 2>/dev/null | head -1)" + if [[ -n "${report_file}" ]]; then echo '```' - tail -n 3 coverage-report/coverage.report + tail -n 3 "${report_file}" echo '```' fi echo "- Report artifact: \`${REPORT_ARTIFACT}\` (download from [run artifacts](${RUN_URL}))" diff --git a/test_categories_coverage.yaml b/test_categories_coverage.yaml new file mode 100644 index 000000000000..2a0bfb630955 --- /dev/null +++ b/test_categories_coverage.yaml @@ -0,0 +1,26 @@ +# Coverage configuration for rocm-libraries projects. +# +# Defines which projects have coverage enabled and the metadata used to drive +# the coverage report (see .github/scripts/export_coverage_metadata.py and +# .github/scripts/coverage_runner.py). +# +# Notes: +# * `libraries` / `test_binaries` are matched by file name (basename); the +# export/runner scripts locate the actual instrumented files in the build +# tree, so version suffixes (e.g. libhiprand.so.1.1) are handled +# automatically. +# * `ignore_filename_regex` is passed to `llvm-cov` as -ignore-filename-regex. +# * `llvm_profile_pattern` is the LLVM_PROFILE_FILE pattern; %m keeps one file +# per instrumented binary so parallel tests do not clobber each other. +# * `test_category` is the ctest label coverage tests run under. +projects: + hiprand: + enabled: true + coverage_objects: + # hipRAND is a thin wrapper; coverage is collected from the wrapper lib. + libraries: + - libhiprand.so + test_binaries: [] + ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/_deps/.*|.*deps.*' + llvm_profile_pattern: '%m' + test_category: quick From 211f7d7f2ca4aca5bf9700b1d6f2d0de21878b69 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Mon, 22 Jun 2026 11:12:23 +0000 Subject: [PATCH 62/79] fix Codecov upload (glibc) and surface coverage summary in step log The standalone Codecov CLI binary failed to load in the manylinux build container ("libpython3.9.so: GLIBC_2.29 not found"). Install codecov-cli via pip so it runs under the container's Python instead, and log when CODECOV_TOKEN is empty (expected for fork PRs, which do not receive repository secrets). Also tee the coverage summary to the step log so it is visible there in addition to the job summary page. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index c506ba0a65a1..e613cf42238c 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -357,12 +357,19 @@ jobs: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} run: | set -x - if ! curl -Os https://cli.codecov.io/latest/linux/codecov; then - echo "Could not download the Codecov CLI; skipping upload." + # The standalone Codecov CLI binary is built against a newer glibc than + # the manylinux build container provides (it failed to load libpython + # with "GLIBC_2.29 not found"). Install via pip so it runs under the + # container's own Python interpreter instead. + if ! python3 -m pip install --quiet codecov-cli; then + echo "Could not install codecov-cli; skipping upload." exit 0 fi - chmod +x codecov - ./codecov upload-process \ + if [[ -z "${CODECOV_TOKEN:-}" ]]; then + echo "CODECOV_TOKEN is empty (expected for fork PRs, which do not receive" + echo "repository secrets); attempting a tokenless upload (public repo)." + fi + codecovcli upload-process \ --disable-search \ --file coverage-report/coverage.info \ --flag "${{ inputs.cmake_target }}" \ @@ -385,4 +392,5 @@ jobs: fi echo "- Report artifact: \`${REPORT_ARTIFACT}\` (download from [run artifacts](${RUN_URL}))" echo "- Codecov: https://app.codecov.io/gh/${{ github.repository }}/pull/${{ github.event.pull_request.number }} (flag: ${{ inputs.cmake_target }})" - } >> "${GITHUB_STEP_SUMMARY}" + # tee so the summary is also visible in this step's log, not only the job summary page. + } | tee -a "${GITHUB_STEP_SUMMARY}" From 7fd82d4e020ee70e378fa3158bf4db62bbe99339 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Tue, 23 Jun 2026 11:22:57 +0000 Subject: [PATCH 63/79] extend coverage artifact retention Keep the shareable coverage report for 90 days and the coverage objects/profraw for 7 days (up from 1) to make sharing and experimentation easier. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 4 +++- .github/workflows/therock-test-component.yml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index e613cf42238c..b7a6083f568a 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -164,7 +164,7 @@ jobs: # Relative path resolves against the container workspace, matching the staging step. path: coverage-objects if-no-files-found: error - retention-days: 1 + retention-days: 7 - name: Report if: ${{ !cancelled() }} @@ -348,6 +348,8 @@ jobs: name: ${{ env.REPORT_ARTIFACT }} path: coverage-report if-no-files-found: warn + # Keep the shareable report around well beyond the build inputs. + retention-days: 90 - name: Upload coverage to Codecov if: ${{ always() }} diff --git a/.github/workflows/therock-test-component.yml b/.github/workflows/therock-test-component.yml index 377d1e16429e..3c21f7bf112d 100644 --- a/.github/workflows/therock-test-component.yml +++ b/.github/workflows/therock-test-component.yml @@ -139,7 +139,7 @@ jobs: # Relative path resolves against the container workspace, matching the prepare step. path: coverage-profraw/*.profraw if-no-files-found: warn - retention-days: 1 + retention-days: 7 - name: Notify Teams Channel on Failure if: ${{ failure() && !github.event.pull_request.head.repo.fork }} From 9ec5d19eaf58237c87f4c58c8e74a5e2d5923905 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Wed, 24 Jun 2026 12:36:23 +0000 Subject: [PATCH 64/79] only show the Codecov link in the summary when the upload succeeded The summary previously printed the Codecov PR URL unconditionally, even though the upload fails on fork PRs (no CODECOV_TOKEN, tokenless disabled), leaving a dead link. Record the upload outcome and show the live link only on success; otherwise explain why Codecov is unavailable and point to the report artifact. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index b7a6083f568a..b6ebf0eef28c 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -352,6 +352,7 @@ jobs: retention-days: 90 - name: Upload coverage to Codecov + id: codecov if: ${{ always() }} continue-on-error: true shell: bash @@ -365,19 +366,24 @@ jobs: # container's own Python interpreter instead. if ! python3 -m pip install --quiet codecov-cli; then echo "Could not install codecov-cli; skipping upload." + echo "uploaded=false" >> "${GITHUB_OUTPUT}" exit 0 fi if [[ -z "${CODECOV_TOKEN:-}" ]]; then echo "CODECOV_TOKEN is empty (expected for fork PRs, which do not receive" echo "repository secrets); attempting a tokenless upload (public repo)." fi - codecovcli upload-process \ + if codecovcli upload-process \ --disable-search \ --file coverage-report/coverage.info \ --flag "${{ inputs.cmake_target }}" \ --name "${{ inputs.cmake_target }}-${{ inputs.amdgpu_families }}" \ - --slug "${{ github.repository }}" \ - || echo "Codecov upload failed (non-fatal)." + --slug "${{ github.repository }}"; then + echo "uploaded=true" >> "${GITHUB_OUTPUT}" + else + echo "Codecov upload failed (non-fatal)." + echo "uploaded=false" >> "${GITHUB_OUTPUT}" + fi - name: Coverage report summary if: ${{ always() }} @@ -393,6 +399,10 @@ jobs: echo '```' fi echo "- Report artifact: \`${REPORT_ARTIFACT}\` (download from [run artifacts](${RUN_URL}))" - echo "- Codecov: https://app.codecov.io/gh/${{ github.repository }}/pull/${{ github.event.pull_request.number }} (flag: ${{ inputs.cmake_target }})" + if [[ "${{ steps.codecov.outputs.uploaded }}" == "true" ]]; then + echo "- Codecov: https://app.codecov.io/gh/${{ github.repository }}/pull/${{ github.event.pull_request.number }} (flag: ${{ inputs.cmake_target }})" + else + echo "- Codecov: upload unavailable for this run (fork PRs do not receive CODECOV_TOKEN, and tokenless upload is disabled for this repo). Use the report artifact above; Codecov populates when run in a non-fork context." + fi # tee so the summary is also visible in this step's log, not only the job summary page. } | tee -a "${GITHUB_STEP_SUMMARY}" From fc42d35d4efc3be0d99d8fa9310f6fbe795b9339 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Thu, 25 Jun 2026 09:17:07 +0000 Subject: [PATCH 65/79] add rocRAND as an independent coverage component Track rocRAND coverage separately from hipRAND. Both live in the rand build group, so emit one independent coverage job per coverage-enabled project in a group (each gets its own build -> test -> report and its own artifacts/flag) instead of a single primary per group. - therock_configure_coverage.py: emit a coverage job per coverage-enabled projects_to_test entry; add rocrand to COVERAGE_PROJECT_METADATA (rocRAND, math-libs/rocRAND, RAND-only build options). - test_categories_coverage.yaml: add rocrand (object librocrand.so). - projects/rocrand/CMakeLists.txt: add ROCRAND_ENABLE_COVERAGE alias that maps to the existing CODE_COVERAGE switch so the CI flag instruments librocrand. Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 71 +++++++++---------- projects/rocrand/CMakeLists.txt | 6 ++ test_categories_coverage.yaml | 11 +++ 3 files changed, 49 insertions(+), 39 deletions(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index ea63d29ea5c6..ffebc4a412b7 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -4,7 +4,7 @@ import os from pathlib import Path -from therock_matrix import collect_projects_to_run, subtree_to_project_map +from therock_matrix import collect_projects_to_run from pr_detect_changed_subtrees import get_valid_prefixes, find_matched_subtrees from config_loader import load_repo_config from therock_configure_ci import get_modified_paths # reuse existing helper @@ -18,6 +18,7 @@ # mega-group options that would otherwise build unrelated components. COVERAGE_PROJECT_METADATA = { "hiprand": ("hipRAND", "ml-libs/hipRAND", "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), + "rocrand": ("rocRAND", "math-libs/rocRAND", "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), } @@ -50,52 +51,44 @@ def get_changed_subtrees_only(): def main(): subtrees = get_changed_subtrees_only() - - changed_project_keys = set() - for subtree in subtrees: - if subtree in subtree_to_project_map: - changed_project_keys.add(subtree_to_project_map[subtree]) - projects = collect_projects_to_run(subtrees) - # Filter: only keep projects that have coverage-enabled tests + # Emit one INDEPENDENT coverage job per coverage-enabled project in each + # group. Several coverage-enabled projects can share a group (e.g. the rand + # group contains both rocrand and hiprand); each gets its own build -> test + # -> report pipeline so the components are tracked separately. coverage_projects = [] + seen_projects = set() for proj in projects: pts_list = [p for p in proj.get("projects_to_test", "").split(",") if p] - # Find primary project: prefer the first coverage-enabled test project, - # then a changed project, otherwise fall back to the first entry. - primary = next( - (p for p in pts_list if p in COVERAGE_PROJECT_METADATA), - pts_list[0] if pts_list else "", - ) - # Only let a changed project override the choice if it is itself - # coverage-enabled (otherwise a changed-but-uncovered project such as - # hipdnn would displace a covered one like hiprand in a merged group). - for p in pts_list: - if p in changed_project_keys and p in COVERAGE_PROJECT_METADATA: - primary = p - break - - # FILTER: Skip if not coverage-enabled - metadata = get_build_metadata(primary) - if metadata is None: - logging.info(f"Skipping {primary} - not coverage-enabled") + covered = [p for p in pts_list if p in COVERAGE_PROJECT_METADATA] + if not covered: + logging.info( + "Skipping group with tests %s - no coverage-enabled project", pts_list + ) continue - # Add coverage metadata - uppercase_name, cmake_target, build_dir, cmake_options = metadata - proj["project_name"] = uppercase_name - proj["cmake_target"] = cmake_target - proj["build_dir"] = build_dir - # Pin to this project's own options so we don't build the merged - # mega-group (which pulls in unrelated components like hipdnn/providers). - proj["cmake_options"] = cmake_options - # Only run the coverage project's own tests, not every test in the - # (possibly merged) group, so the test stage matches the pinned build. - proj["projects_to_test"] = primary - - coverage_projects.append(proj) + for project_key in covered: + if project_key in seen_projects: + continue # avoid duplicate jobs if a project appears in multiple groups + seen_projects.add(project_key) + + uppercase_name, cmake_target, build_dir, cmake_options = get_build_metadata( + project_key + ) + # Copy the group entry so each coverage project gets its own job. + entry = dict(proj) + entry["project_name"] = uppercase_name + entry["cmake_target"] = cmake_target + entry["build_dir"] = build_dir + # Pin to this project's own options so we don't build the merged + # mega-group (which pulls in unrelated components like hipdnn/providers). + entry["cmake_options"] = cmake_options + # Only run this project's own tests, so the test stage matches the + # pinned (single-project) build. + entry["projects_to_test"] = project_key + coverage_projects.append(entry) # Output for GitHub Actions output = { diff --git a/projects/rocrand/CMakeLists.txt b/projects/rocrand/CMakeLists.txt index 0a7f909bd0e8..d41d49fe742f 100644 --- a/projects/rocrand/CMakeLists.txt +++ b/projects/rocrand/CMakeLists.txt @@ -160,6 +160,12 @@ if(DISABLE_WERROR) else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") endif() +# CI passes -DROCRAND_ENABLE_COVERAGE=ON (the standardized coverage flag); +# map it onto the existing CODE_COVERAGE switch. +option(ROCRAND_ENABLE_COVERAGE "Enable code coverage (alias for CODE_COVERAGE)" OFF) +if(ROCRAND_ENABLE_COVERAGE) + set(CODE_COVERAGE ON) +endif() if(CODE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping") add_definitions(-DCODE_COVERAGE_ENABLED) diff --git a/test_categories_coverage.yaml b/test_categories_coverage.yaml index 2a0bfb630955..923b78e56410 100644 --- a/test_categories_coverage.yaml +++ b/test_categories_coverage.yaml @@ -24,3 +24,14 @@ projects: ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/_deps/.*|.*deps.*' llvm_profile_pattern: '%m' test_category: quick + + rocrand: + enabled: true + coverage_objects: + # Coverage is collected from the rocRAND device library. + libraries: + - librocrand.so + test_binaries: [] + ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/benchmark/.*|.*/_deps/.*|.*deps.*' + llvm_profile_pattern: '%m' + test_category: quick From b7d9e3a408e5fa9782e42cac5b6fbfeb6456a752 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Thu, 25 Jun 2026 10:58:46 +0000 Subject: [PATCH 66/79] add rocFFT as an independent coverage component Track rocFFT coverage as its own build -> test -> report job (the fft group's projects_to_test is hipfft,rocfft; only rocfft is coverage-enabled). - therock_configure_coverage.py: add rocfft to COVERAGE_PROJECT_METADATA (rocFFT, math-libs/rocFFT, FFT+RAND build options, ALL=OFF). - test_categories_coverage.yaml: add rocfft (object librocfft.so). - projects/rocfft/CMakeLists.txt: add ROCFFT_ENABLE_COVERAGE alias that sets BUILD_CODE_COVERAGE before the library subdir is processed, so librocfft is instrumented when the CI flag is passed. Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 1 + projects/rocfft/CMakeLists.txt | 7 +++++++ test_categories_coverage.yaml | 11 +++++++++++ 3 files changed, 19 insertions(+) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index ffebc4a412b7..14ca238d946e 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -19,6 +19,7 @@ COVERAGE_PROJECT_METADATA = { "hiprand": ("hipRAND", "ml-libs/hipRAND", "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), "rocrand": ("rocRAND", "math-libs/rocRAND", "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), + "rocfft": ("rocFFT", "math-libs/rocFFT", "-DTHEROCK_ENABLE_FFT=ON -DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), } diff --git a/projects/rocfft/CMakeLists.txt b/projects/rocfft/CMakeLists.txt index 1002938e94f1..cf3d7d30a486 100644 --- a/projects/rocfft/CMakeLists.txt +++ b/projects/rocfft/CMakeLists.txt @@ -222,6 +222,13 @@ if( ROCFFT_MPI_ENABLE ) include_directories(SYSTEM ${MPI_INCLUDE_PATH}) endif() +# CI passes -DROCFFT_ENABLE_COVERAGE=ON (the standardized coverage flag); map it +# onto BUILD_CODE_COVERAGE before the library subdir is processed below. +option(ROCFFT_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) +if( ROCFFT_ENABLE_COVERAGE ) + set( BUILD_CODE_COVERAGE ON ) +endif() + add_subdirectory( library ) include( clients/cmake/build-options.cmake ) diff --git a/test_categories_coverage.yaml b/test_categories_coverage.yaml index 923b78e56410..b1f1a94409f7 100644 --- a/test_categories_coverage.yaml +++ b/test_categories_coverage.yaml @@ -35,3 +35,14 @@ projects: ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/benchmark/.*|.*/_deps/.*|.*deps.*' llvm_profile_pattern: '%m' test_category: quick + + rocfft: + enabled: true + coverage_objects: + # Coverage is collected from the rocFFT library. + libraries: + - librocfft.so + test_binaries: [] + ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/clients/.*|.*/_deps/.*|.*deps.*' + llvm_profile_pattern: '%m' + test_category: quick From f0601ac944770d144c214aaeb011c2e8d5fe5876 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Thu, 25 Jun 2026 12:39:42 +0000 Subject: [PATCH 67/79] scope coverage profraw download to the component With multiple coverage components on the same GPU family (hipRAND, rocRAND, rocFFT), the report job's profraw download pattern coverage-profraw--* matched every component, risking cross-contamination and masking a component's own missing profraw. Scope it to coverage-profraw---* using the pinned projects_to_test. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index b6ebf0eef28c..a988558bd088 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -246,7 +246,10 @@ jobs: - name: Download coverage profraw artifacts uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 with: - pattern: coverage-profraw-${{ inputs.amdgpu_families }}-* + # Scope to THIS component's profraw (projects_to_test is pinned to the + # single coverage project) so multiple components on the same GPU + # family don't cross-contaminate each other's reports. + pattern: coverage-profraw-${{ inputs.amdgpu_families }}-${{ inputs.projects_to_test }}-* path: coverage-profraw merge-multiple: true From f269236c49a83b52cc14f9190c173369ee5a5c65 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Sun, 28 Jun 2026 16:51:04 +0000 Subject: [PATCH 68/79] add rocBLAS and rocSPARSE as independent coverage components Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 2 ++ projects/rocblas/CMakeLists.txt | 8 +++++++ projects/rocsparse/CMakeLists.txt | 7 ++++++ test_categories_coverage.yaml | 22 +++++++++++++++++++ 4 files changed, 39 insertions(+) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 14ca238d946e..6b8409373080 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -20,6 +20,8 @@ "hiprand": ("hipRAND", "ml-libs/hipRAND", "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), "rocrand": ("rocRAND", "math-libs/rocRAND", "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), "rocfft": ("rocFFT", "math-libs/rocFFT", "-DTHEROCK_ENABLE_FFT=ON -DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), + "rocblas": ("rocBLAS", "math-libs/rocBLAS", "-DTHEROCK_ENABLE_BLAS=ON -DTHEROCK_ENABLE_ALL=OFF"), + "rocsparse": ("rocSPARSE", "math-libs/rocSPARSE", "-DTHEROCK_ENABLE_SPARSE=ON -DTHEROCK_ENABLE_ALL=OFF"), } diff --git a/projects/rocblas/CMakeLists.txt b/projects/rocblas/CMakeLists.txt index ef441b34cede..6e44008f6f5b 100644 --- a/projects/rocblas/CMakeLists.txt +++ b/projects/rocblas/CMakeLists.txt @@ -325,6 +325,14 @@ if( BUILD_CLIENTS_SAMPLES OR BUILD_CLIENTS_TESTS OR BUILD_CLIENTS_BENCHMARKS ) endif() endif() +# CI passes -DROCBLAS_ENABLE_COVERAGE=ON (the standardized coverage flag); map it +# onto BUILD_CODE_COVERAGE before the library subdir is processed below. +option(ROCBLAS_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) +if( ROCBLAS_ENABLE_COVERAGE ) + set( BUILD_CODE_COVERAGE ON ) + set( ROCBLAS_BUILD_COVERAGE ON ) +endif() + if( NOT SKIP_LIBRARY ) add_subdirectory( library ) endif() diff --git a/projects/rocsparse/CMakeLists.txt b/projects/rocsparse/CMakeLists.txt index 9bae48d2ebc1..cdb30dfd3b28 100644 --- a/projects/rocsparse/CMakeLists.txt +++ b/projects/rocsparse/CMakeLists.txt @@ -88,6 +88,13 @@ option(BUILD_WITH_ROCTX "Enable building rocSPARSE with rocTX" ON) option(BUILD_WITH_OFFLOAD_COMPRESS "Enable offload compression during compilation" ON) +# CI passes -DROCSPARSE_ENABLE_COVERAGE=ON (the standardized coverage flag); map +# it onto BUILD_CODE_COVERAGE before the library subdir is processed below. +option(ROCSPARSE_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) +if(ROCSPARSE_ENABLE_COVERAGE) + set(BUILD_CODE_COVERAGE ON) +endif() + # Clients utilize rocsparse fortran API and a fortran compiler if( NOT BUILD_FORTRAN_CLIENTS ) option( BUILD_FORTRAN_CLIENTS "Build rocSPARSE clients requiring Fortran capabilities" ON ) diff --git a/test_categories_coverage.yaml b/test_categories_coverage.yaml index b1f1a94409f7..034fb1a7c00c 100644 --- a/test_categories_coverage.yaml +++ b/test_categories_coverage.yaml @@ -46,3 +46,25 @@ projects: ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/clients/.*|.*/_deps/.*|.*deps.*' llvm_profile_pattern: '%m' test_category: quick + + rocblas: + enabled: true + coverage_objects: + # Coverage is collected from the rocBLAS library. + libraries: + - librocblas.so + test_binaries: [] + ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/clients/.*|.*[Tt]ensile.*|.*/_deps/.*|.*deps.*' + llvm_profile_pattern: '%m' + test_category: quick + + rocsparse: + enabled: true + coverage_objects: + # Coverage is collected from the rocSPARSE library. + libraries: + - librocsparse.so + test_binaries: [] + ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/clients/.*|.*/_deps/.*|.*deps.*' + llvm_profile_pattern: '%m' + test_category: quick From 1529434fe6471bd5cfdc5eca92eb09ddaa533676 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Sun, 28 Jun 2026 16:59:20 +0000 Subject: [PATCH 69/79] format coverage metadata table with black The COVERAGE_PROJECT_METADATA entries exceeded black's line length, which was failing the pre-commit black hook. Wrap them to satisfy formatting. Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 30 +++++++++++++++---- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 6b8409373080..b74c6b3ce431 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -17,11 +17,31 @@ # to just this project so the coverage job does not inherit the (possibly merged) # mega-group options that would otherwise build unrelated components. COVERAGE_PROJECT_METADATA = { - "hiprand": ("hipRAND", "ml-libs/hipRAND", "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), - "rocrand": ("rocRAND", "math-libs/rocRAND", "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), - "rocfft": ("rocFFT", "math-libs/rocFFT", "-DTHEROCK_ENABLE_FFT=ON -DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF"), - "rocblas": ("rocBLAS", "math-libs/rocBLAS", "-DTHEROCK_ENABLE_BLAS=ON -DTHEROCK_ENABLE_ALL=OFF"), - "rocsparse": ("rocSPARSE", "math-libs/rocSPARSE", "-DTHEROCK_ENABLE_SPARSE=ON -DTHEROCK_ENABLE_ALL=OFF"), + "hiprand": ( + "hipRAND", + "ml-libs/hipRAND", + "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF", + ), + "rocrand": ( + "rocRAND", + "math-libs/rocRAND", + "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF", + ), + "rocfft": ( + "rocFFT", + "math-libs/rocFFT", + "-DTHEROCK_ENABLE_FFT=ON -DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF", + ), + "rocblas": ( + "rocBLAS", + "math-libs/rocBLAS", + "-DTHEROCK_ENABLE_BLAS=ON -DTHEROCK_ENABLE_ALL=OFF", + ), + "rocsparse": ( + "rocSPARSE", + "math-libs/rocSPARSE", + "-DTHEROCK_ENABLE_SPARSE=ON -DTHEROCK_ENABLE_ALL=OFF", + ), } From b0d3601d88fdb4bdb83d9a7cc71c91c8a81eeaf2 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Sun, 28 Jun 2026 17:39:59 +0000 Subject: [PATCH 70/79] format coverage runner and metadata exporter with black These coverage scripts predated the black pre-commit hook enforcement and were failing it; reformat to satisfy the hook. Co-authored-by: Cursor --- .github/scripts/coverage_runner.py | 135 +++++++++++++++----- .github/scripts/export_coverage_metadata.py | 33 +++-- 2 files changed, 127 insertions(+), 41 deletions(-) diff --git a/.github/scripts/coverage_runner.py b/.github/scripts/coverage_runner.py index 4ec9fb9d48ab..a6b3147cdc8c 100644 --- a/.github/scripts/coverage_runner.py +++ b/.github/scripts/coverage_runner.py @@ -79,8 +79,16 @@ def set_coverage_environment(metadata: dict, coverage_dir: Path): def run_tests(test_dir: Path, metadata: dict) -> int: category = metadata.get("test_category", "") - cmd = ["ctest", "--test-dir", str(test_dir), "--output-on-failure", - "--parallel", "8", "--timeout", "7200"] + cmd = [ + "ctest", + "--test-dir", + str(test_dir), + "--output-on-failure", + "--parallel", + "8", + "--timeout", + "7200", + ] if category: cmd += ["-L", category] logging.info("Running tests: %s", " ".join(cmd)) @@ -92,14 +100,23 @@ def merge_profraw_files(llvm_profdata: Path, profraw_dir: Path, out_path: Path) if not profraw_files: raise RuntimeError(f"No .profraw files found under {profraw_dir}") logging.info("Merging %d profraw file(s)", len(profraw_files)) - subprocess.run([str(llvm_profdata), "merge", "-sparse", "-o", str(out_path), - *profraw_files], check=True) + subprocess.run( + [str(llvm_profdata), "merge", "-sparse", "-o", str(out_path), *profraw_files], + check=True, + ) logging.info("Created %s", out_path) return out_path -def generate_reports(llvm_cov: Path, llvm_cxxfilt: Path | None, objects: list[Path], - ignore_regex: str, profdata: Path, coverage_dir: Path, project: str): +def generate_reports( + llvm_cov: Path, + llvm_cxxfilt: Path | None, + objects: list[Path], + ignore_regex: str, + profdata: Path, + coverage_dir: Path, + project: str, +): object_args: list[str] = [] for obj in objects: object_args += ["-object", str(obj)] @@ -108,13 +125,29 @@ def generate_reports(llvm_cov: Path, llvm_cxxfilt: Path | None, objects: list[Pa text_report = coverage_dir / f"code_cov_{project}.report" logging.info("Generating text report -> %s", text_report) with open(text_report, "w") as f: - subprocess.run([str(llvm_cov), "report", *object_args, - f"-instr-profile={profdata}", *ignore_args], stdout=f, check=True) + subprocess.run( + [ + str(llvm_cov), + "report", + *object_args, + f"-instr-profile={profdata}", + *ignore_args, + ], + stdout=f, + check=True, + ) print(text_report.read_text()) logging.info("Generating HTML report -> %s", coverage_dir) - show_cmd = [str(llvm_cov), "show", *object_args, f"-instr-profile={profdata}", - *ignore_args, "--format=html", f"--output-dir={coverage_dir}"] + show_cmd = [ + str(llvm_cov), + "show", + *object_args, + f"-instr-profile={profdata}", + *ignore_args, + "--format=html", + f"--output-dir={coverage_dir}", + ] if llvm_cxxfilt is not None: show_cmd.insert(2, f"-Xdemangler={llvm_cxxfilt}") subprocess.run(show_cmd, check=True) @@ -122,25 +155,54 @@ def generate_reports(llvm_cov: Path, llvm_cxxfilt: Path | None, objects: list[Pa lcov_file = coverage_dir / "coverage.info" logging.info("Generating LCOV export -> %s", lcov_file) with open(lcov_file, "w") as f: - subprocess.run([str(llvm_cov), "export", *object_args, - f"-instr-profile={profdata}", *ignore_args, "--format=lcov"], - stdout=f, check=True) + subprocess.run( + [ + str(llvm_cov), + "export", + *object_args, + f"-instr-profile={profdata}", + *ignore_args, + "--format=lcov", + ], + stdout=f, + check=True, + ) def main(): parser = argparse.ArgumentParser(description="Run/aggregate coverage and report") - parser.add_argument("--build-dir", type=Path, required=True, - help="Tree to resolve coverage objects and llvm tools from") - parser.add_argument("--metadata", type=Path, required=True, - help="coverage_metadata.json from export_coverage_metadata.py") - parser.add_argument("--coverage-dir", type=Path, required=True, - help="Output directory for reports") - parser.add_argument("--profraw-dir", type=Path, default=None, - help="Directory of profraw files (default: /profraw)") - parser.add_argument("--test-dir", type=Path, default=None, - help="ctest directory (default: --build-dir) when running tests") - parser.add_argument("--skip-tests", action="store_true", - help="Do not run tests; merge existing profraw files") + parser.add_argument( + "--build-dir", + type=Path, + required=True, + help="Tree to resolve coverage objects and llvm tools from", + ) + parser.add_argument( + "--metadata", + type=Path, + required=True, + help="coverage_metadata.json from export_coverage_metadata.py", + ) + parser.add_argument( + "--coverage-dir", type=Path, required=True, help="Output directory for reports" + ) + parser.add_argument( + "--profraw-dir", + type=Path, + default=None, + help="Directory of profraw files (default: /profraw)", + ) + parser.add_argument( + "--test-dir", + type=Path, + default=None, + help="ctest directory (default: --build-dir) when running tests", + ) + parser.add_argument( + "--skip-tests", + action="store_true", + help="Do not run tests; merge existing profraw files", + ) args = parser.parse_args() with open(args.metadata) as f: @@ -158,10 +220,12 @@ def main(): llvm_cxxfilt = find_tool(args.build_dir, "llvm-cxxfilt") if llvm_profdata is None or llvm_cov is None: raise FileNotFoundError( - f"llvm-profdata/llvm-cov not found under {args.build_dir}") + f"llvm-profdata/llvm-cov not found under {args.build_dir}" + ) tool_dirs = {str(t.parent) for t in (llvm_profdata, llvm_cov, llvm_cxxfilt) if t} os.environ["LD_LIBRARY_PATH"] = os.pathsep.join( - [*tool_dirs, os.environ.get("LD_LIBRARY_PATH", "")]) + [*tool_dirs, os.environ.get("LD_LIBRARY_PATH", "")] + ) for t in (llvm_profdata, llvm_cov, llvm_cxxfilt): if t: t.chmod(0o755) @@ -177,11 +241,18 @@ def main(): if rc != 0: logging.warning("Tests exited with %d; continuing with coverage.", rc) - profdata = merge_profraw_files(llvm_profdata, profraw_dir, - args.coverage_dir / f"{project}.profdata") - generate_reports(llvm_cov, llvm_cxxfilt, objects, - metadata.get("ignore_filename_regex", ""), profdata, - args.coverage_dir, project) + profdata = merge_profraw_files( + llvm_profdata, profraw_dir, args.coverage_dir / f"{project}.profdata" + ) + generate_reports( + llvm_cov, + llvm_cxxfilt, + objects, + metadata.get("ignore_filename_regex", ""), + profdata, + args.coverage_dir, + project, + ) logging.info("Coverage generation complete.") diff --git a/.github/scripts/export_coverage_metadata.py b/.github/scripts/export_coverage_metadata.py index 186625da8aca..c4b8df18bfcd 100644 --- a/.github/scripts/export_coverage_metadata.py +++ b/.github/scripts/export_coverage_metadata.py @@ -52,7 +52,9 @@ def find_by_basename(build_dir: Path, basename: str) -> list[str]: return sorted(set(matches)) -def export_metadata(build_dir: Path, project: str, config_path: Path, output_path: Path): +def export_metadata( + build_dir: Path, project: str, config_path: Path, output_path: Path +): config = load_coverage_config(config_path) key = resolve_project_key(config, project) project_config = config["projects"][key] @@ -100,14 +102,27 @@ def export_metadata(build_dir: Path, project: str, config_path: Path, output_pat def main(): parser = argparse.ArgumentParser(description="Export coverage metadata to JSON") - parser.add_argument("--build-dir", type=Path, required=True, - help="Build/dist tree to search for coverage objects") - parser.add_argument("--project", type=str, required=True, - help="Project key or name (e.g. hiprand / HIPRAND)") - parser.add_argument("--config", type=Path, required=True, - help="Path to test_categories_coverage.yaml") - parser.add_argument("--output", type=Path, required=True, - help="Output coverage_metadata.json path") + parser.add_argument( + "--build-dir", + type=Path, + required=True, + help="Build/dist tree to search for coverage objects", + ) + parser.add_argument( + "--project", + type=str, + required=True, + help="Project key or name (e.g. hiprand / HIPRAND)", + ) + parser.add_argument( + "--config", + type=Path, + required=True, + help="Path to test_categories_coverage.yaml", + ) + parser.add_argument( + "--output", type=Path, required=True, help="Output coverage_metadata.json path" + ) args = parser.parse_args() export_metadata(args.build_dir, args.project, args.config, args.output) From 71ec37dd4f2b0ada47f8ec12f755f3dbca6051f7 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Mon, 29 Jun 2026 04:56:16 +0000 Subject: [PATCH 71/79] skip coverage report gracefully when no profraw is produced GPU families whose test machines lack a matching GPU run only host-side quick tests that never exercise the instrumented library, so they upload no profraw (e.g. rocRAND/hipRAND/rocBLAS on gfx94X). With nothing to merge, treat it as a no-op success and skip the report instead of failing the whole coverage job; families that do produce profraw (gfx950) still generate and upload reports. Co-authored-by: Cursor --- .github/scripts/coverage_runner.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/scripts/coverage_runner.py b/.github/scripts/coverage_runner.py index a6b3147cdc8c..993245613f2c 100644 --- a/.github/scripts/coverage_runner.py +++ b/.github/scripts/coverage_runner.py @@ -241,6 +241,19 @@ def main(): if rc != 0: logging.warning("Tests exited with %d; continuing with coverage.", rc) + # Some test runners (e.g. GPU families whose machines have no matching GPU) + # run only host-side quick tests that never exercise the instrumented + # library, so they upload no profraw. With nothing to merge there is no + # coverage to report; treat that as a no-op success rather than failing the + # job, so the absence of data on one GPU family does not break CI. + if not list(profraw_dir.rglob("*.profraw")): + logging.warning( + "No .profraw files found under %s; skipping coverage report " + "(no instrumented test data was produced for this build).", + profraw_dir, + ) + return + profdata = merge_profraw_files( llvm_profdata, profraw_dir, args.coverage_dir / f"{project}.profdata" ) From ef829fb9680fb76ef8ab5167e14060e64a56295e Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Mon, 29 Jun 2026 05:10:03 +0000 Subject: [PATCH 72/79] drop rocSPARSE coverage component rocSPARSE coverage cannot build: enabling SPARSE pulls in the PRIM group, whose rocThrust configure fails on find_package(SQLite3 3.51.3) because the sysdeps-provided SQLite3 reports an unknown version. This is an upstream rocThrust/TheRock dependency issue, so remove the rocSPARSE coverage component (metadata, YAML entry, and CMake alias) until it is resolved. rocBLAS coverage is unaffected and retained. Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 5 ----- projects/rocsparse/CMakeLists.txt | 7 ------- test_categories_coverage.yaml | 11 ----------- 3 files changed, 23 deletions(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index b74c6b3ce431..1e2f5afc8a27 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -37,11 +37,6 @@ "math-libs/rocBLAS", "-DTHEROCK_ENABLE_BLAS=ON -DTHEROCK_ENABLE_ALL=OFF", ), - "rocsparse": ( - "rocSPARSE", - "math-libs/rocSPARSE", - "-DTHEROCK_ENABLE_SPARSE=ON -DTHEROCK_ENABLE_ALL=OFF", - ), } diff --git a/projects/rocsparse/CMakeLists.txt b/projects/rocsparse/CMakeLists.txt index 609dcd92b17a..dddb1aa27adf 100644 --- a/projects/rocsparse/CMakeLists.txt +++ b/projects/rocsparse/CMakeLists.txt @@ -89,13 +89,6 @@ option(BUILD_WITH_OFFLOAD_COMPRESS "Enable offload compression during compilation" ON) option(BUILD_WITH_ILDLT0 "Build rocSPARSE with incomplete LDL^T (zero fill-in) factorization support" ON) -# CI passes -DROCSPARSE_ENABLE_COVERAGE=ON (the standardized coverage flag); map -# it onto BUILD_CODE_COVERAGE before the library subdir is processed below. -option(ROCSPARSE_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) -if(ROCSPARSE_ENABLE_COVERAGE) - set(BUILD_CODE_COVERAGE ON) -endif() - # Clients utilize rocsparse fortran API and a fortran compiler if( NOT BUILD_FORTRAN_CLIENTS ) option( BUILD_FORTRAN_CLIENTS "Build rocSPARSE clients requiring Fortran capabilities" ON ) diff --git a/test_categories_coverage.yaml b/test_categories_coverage.yaml index 034fb1a7c00c..38bd2fa60e06 100644 --- a/test_categories_coverage.yaml +++ b/test_categories_coverage.yaml @@ -57,14 +57,3 @@ projects: ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/clients/.*|.*[Tt]ensile.*|.*/_deps/.*|.*deps.*' llvm_profile_pattern: '%m' test_category: quick - - rocsparse: - enabled: true - coverage_objects: - # Coverage is collected from the rocSPARSE library. - libraries: - - librocsparse.so - test_binaries: [] - ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/clients/.*|.*/_deps/.*|.*deps.*' - llvm_profile_pattern: '%m' - test_category: quick From 994739e1dee46cbeac427138f41eb2b6e501af0e Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Mon, 29 Jun 2026 08:27:02 +0000 Subject: [PATCH 73/79] exit coverage report step cleanly when no profraw was produced coverage_runner.py now skips report generation when a build produced no profraw, so no coverage.info is written. The downstream report bash runs under 'set -euo pipefail', where expanding the resulting empty SOURCES / OBJECTS arrays tripped 'unbound variable' and failed the job. Short-circuit the step with a clean exit 0 when coverage.info is absent. Co-authored-by: Cursor --- .github/workflows/therock-ci-coverage.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index a988558bd088..c309bec19234 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -283,6 +283,15 @@ jobs: --profraw-dir "${PROFRAW_DIR}" \ --skip-tests + # If no profraw was produced (e.g. a GPU family whose machines run only + # host-side tests that never exercise the instrumented library), the + # runner skips report generation and no coverage.info exists. Treat that + # as a clean no-op so the absence of data on one family does not fail CI. + if [[ ! -f "${REPORT_DIR}/coverage.info" ]]; then + echo "No coverage.info produced; skipping report post-processing for this build." + exit 0 + fi + # Make lcov paths repo-relative so Codecov can map them to the source tree. if [[ -f "${REPORT_DIR}/coverage.info" ]]; then sed -i "s|${GITHUB_WORKSPACE}/||g" "${REPORT_DIR}/coverage.info" From daef4c3341d50ce0cf73586658a622631998c82e Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Mon, 29 Jun 2026 09:18:25 +0000 Subject: [PATCH 74/79] add header-only coverage for rocPRIM, hipCUB, rocThrust Header-only libraries have no shared object to instrument, so coverage is collected from their instrumented test binaries (all three add -fprofile-instr-generate/-fcoverage-mapping to the tests under their coverage flag). Changes: - CMake aliases ROCPRIM/HIPCUB/ROCTHRUST_ENABLE_COVERAGE mapping onto each project's BUILD_CODE_COVERAGE / CODE_COVERAGE option. - COVERAGE_PROJECT_METADATA + YAML entries (test_binaries name prefixes) and a rocPRIM codecov flag. - export_coverage_metadata.py resolves the instrumented test executables (ELF, scoped to the component build subdir, extension/CMakeFiles filtered) and stages them into coverage-objects so the report job can pass them to llvm-cov; coverage_runner.py already resolves them. - report step includes staged test binaries and guards empty arrays under set -u. Also make rocThrust resilient to a missing/mis-versioned system SQLite3 by falling back to its bundled download (find_package no longer REQUIRED). Without this the PRIM group coverage build fails at find_package(SQLite3 3.51.3) against TheRock's sysdeps SQLite3 (version "unknown") - the same issue that blocked rocSPARSE. Co-authored-by: Cursor --- .github/scripts/export_coverage_metadata.py | 127 ++++++++++++++++-- .github/scripts/therock_configure_coverage.py | 18 +++ .github/workflows/therock-ci-coverage.yml | 12 +- codecov.yml | 3 + projects/hipcub/CMakeLists.txt | 6 + projects/rocprim/CMakeLists.txt | 6 + projects/rocthrust/CMakeLists.txt | 6 + projects/rocthrust/cmake/Dependencies.cmake | 15 ++- test_categories_coverage.yaml | 33 +++++ 9 files changed, 210 insertions(+), 16 deletions(-) diff --git a/.github/scripts/export_coverage_metadata.py b/.github/scripts/export_coverage_metadata.py index c4b8df18bfcd..50ac5f7179ed 100644 --- a/.github/scripts/export_coverage_metadata.py +++ b/.github/scripts/export_coverage_metadata.py @@ -13,6 +13,7 @@ import argparse import json import logging +import shutil from pathlib import Path import yaml @@ -52,8 +53,51 @@ def find_by_basename(build_dir: Path, basename: str) -> list[str]: return sorted(set(matches)) +def _looks_like_executable(path: Path) -> bool: + """Heuristic: a built test executable (ELF), not a source/object/CMake file.""" + if not path.is_file() or path.is_symlink(): + return False + if path.suffix: # test executables have no extension (test_foo, not test_foo.cpp) + return False + if "CMakeFiles" in path.parts: + return False + try: + with open(path, "rb") as f: + return f.read(4) == b"\x7fELF" + except OSError: + return False + + +def find_test_binaries(build_dir: Path, prefix: str, scope: str | None) -> list[Path]: + """Resolve instrumented test executables whose name starts with ``prefix``. + + Header-only libraries have no shared object to instrument; coverage instead + comes from the test binaries. ``scope`` (e.g. the component build subdir name + like ``rocPRIM``) restricts matches to that component so a shared group build + (PRIM builds rocprim + hipcub + rocthrust together) does not pull in the other + components' binaries. De-duplicates by basename, preferring the copy under a + ``test`` directory. + """ + by_name: dict[str, Path] = {} + for path in build_dir.rglob(f"{prefix}*"): + if not _looks_like_executable(path): + continue + if scope and scope not in path.parts: + continue + name = path.name + prev = by_name.get(name) + if prev is None or ("test" in path.parts and "test" not in prev.parts): + by_name[name] = path + return [by_name[k] for k in sorted(by_name)] + + def export_metadata( - build_dir: Path, project: str, config_path: Path, output_path: Path + build_dir: Path, + project: str, + config_path: Path, + output_path: Path, + cmake_target: str | None = None, + stage_dir: Path | None = None, ): config = load_coverage_config(config_path) key = resolve_project_key(config, project) @@ -64,14 +108,57 @@ def export_metadata( return objects = project_config.get("coverage_objects", {}) + + # Shared libraries are located by basename and staged separately (by the + # workflow) from dist/lib; the runner re-resolves them by basename. found = {"libraries": [], "test_binaries": []} - for kind in ("libraries", "test_binaries"): - for basename in objects.get(kind, []) or []: - hits = find_by_basename(build_dir, basename) - if hits: - found[kind].extend(hits) + for basename in objects.get("libraries", []) or []: + hits = find_by_basename(build_dir, basename) + if hits: + found["libraries"].extend(hits) + else: + logging.warning("Coverage object not found for libraries: %s", basename) + + # Header-only libraries: the configured test_binaries entries are name + # prefixes. Resolve them to the actual instrumented executables, then copy + # them into the staged coverage-objects dir so the report job can pass them + # to llvm-cov as -object. We record their paths relative to the stage dir so + # the runner finds them directly. + staged_test_binaries: list[str] = [] + staged_basenames: list[str] = [] + test_stage = (stage_dir / "test") if stage_dir is not None else None + total_bytes = 0 + for prefix in objects.get("test_binaries", []) or []: + binaries = find_test_binaries(build_dir, prefix, cmake_target) + if not binaries: + logging.warning( + "No instrumented test binaries found for prefix '%s' (scope=%s)", + prefix, + cmake_target, + ) + continue + logging.info( + "Resolved %d test binary(ies) for prefix '%s'", len(binaries), prefix + ) + for binary in binaries: + if test_stage is not None: + test_stage.mkdir(parents=True, exist_ok=True) + dest = test_stage / binary.name + if not dest.exists(): + shutil.copy2(binary, dest) + total_bytes += dest.stat().st_size + staged_test_binaries.append(f"test/{binary.name}") else: - logging.warning("Coverage object not found for %s: %s", kind, basename) + staged_test_binaries.append(str(binary.relative_to(build_dir))) + staged_basenames.append(binary.name) + found["test_binaries"] = sorted(set(staged_test_binaries)) + if test_stage is not None and staged_basenames: + logging.info( + "Staged %d test binary(ies) (%.1f MiB) into %s", + len(set(staged_basenames)), + total_bytes / (1024 * 1024), + test_stage, + ) metadata = { "project": key, @@ -79,7 +166,7 @@ def export_metadata( # Basenames are kept so the runner can re-resolve in a different layout. "object_basenames": { "libraries": objects.get("libraries", []) or [], - "test_binaries": objects.get("test_binaries", []) or [], + "test_binaries": sorted(set(staged_basenames)), }, "ignore_filename_regex": project_config.get("ignore_filename_regex", ""), "llvm_profile_pattern": project_config.get("llvm_profile_pattern", "%m"), @@ -123,8 +210,30 @@ def main(): parser.add_argument( "--output", type=Path, required=True, help="Output coverage_metadata.json path" ) + parser.add_argument( + "--cmake-target", + type=str, + default=None, + help="Component build subdir name used to scope header-only test binaries " + "(e.g. rocPRIM), so a shared group build does not pull in siblings.", + ) + parser.add_argument( + "--stage-dir", + type=Path, + default=None, + help="Coverage-objects dir to copy resolved test binaries into " + "(header-only libs). Defaults to the output file's directory.", + ) args = parser.parse_args() - export_metadata(args.build_dir, args.project, args.config, args.output) + stage_dir = args.stage_dir or args.output.parent + export_metadata( + args.build_dir, + args.project, + args.config, + args.output, + cmake_target=args.cmake_target, + stage_dir=stage_dir, + ) if __name__ == "__main__": diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 1e2f5afc8a27..161fd244118b 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -37,6 +37,24 @@ "math-libs/rocBLAS", "-DTHEROCK_ENABLE_BLAS=ON -DTHEROCK_ENABLE_ALL=OFF", ), + # Header-only libraries: coverage comes from the instrumented test binaries + # (there is no shared library to instrument). All three build together in + # TheRock's PRIM group. + "rocprim": ( + "rocPRIM", + "math-libs/rocPRIM", + "-DTHEROCK_ENABLE_PRIM=ON -DTHEROCK_ENABLE_ALL=OFF", + ), + "hipcub": ( + "hipCUB", + "math-libs/hipCUB", + "-DTHEROCK_ENABLE_PRIM=ON -DTHEROCK_ENABLE_ALL=OFF", + ), + "rocthrust": ( + "rocThrust", + "math-libs/rocThrust", + "-DTHEROCK_ENABLE_PRIM=ON -DTHEROCK_ENABLE_ALL=OFF", + ), } diff --git a/.github/workflows/therock-ci-coverage.yml b/.github/workflows/therock-ci-coverage.yml index c309bec19234..5a4749e73b31 100644 --- a/.github/workflows/therock-ci-coverage.yml +++ b/.github/workflows/therock-ci-coverage.yml @@ -154,6 +154,7 @@ jobs: --build-dir TheRock/build-coverage \ --project "${{ inputs.project_name }}" \ --config test_categories_coverage.yaml \ + --cmake-target "${{ inputs.cmake_target }}" \ --output "${GITHUB_WORKSPACE}/coverage-objects/coverage_metadata.json" cat "${GITHUB_WORKSPACE}/coverage-objects/coverage_metadata.json" @@ -297,9 +298,10 @@ jobs: sed -i "s|${GITHUB_WORKSPACE}/||g" "${REPORT_DIR}/coverage.info" fi - # Collect details for the reference links file. + # Collect details for the reference links file. Header-only components + # have no .so; their instrumented objects are the staged test binaries. mapfile -t SOURCES < <(sed -n 's|^SF:||p' "${REPORT_DIR}/coverage.info" 2>/dev/null | sort -u) - mapfile -t OBJECTS < <(find "${OBJECTS_DIR}/lib" -type f -name "*.so*" 2>/dev/null | sort) + mapfile -t OBJECTS < <( { find "${OBJECTS_DIR}/lib" -type f -name "*.so*" 2>/dev/null; find "${OBJECTS_DIR}/test" -type f 2>/dev/null; } | sort) PROFRAW_COUNT=$(find "${PROFRAW_DIR}" -type f -name '*.profraw' 2>/dev/null | wc -l) # Generate the reference text file with all relevant paths and links. @@ -324,10 +326,10 @@ jobs: echo " Build dir: ${BUILD_DIR}" echo echo "[Instrumented code - source file(s)]" - for s in "${SOURCES[@]}"; do echo " ${s}"; done + for s in ${SOURCES[@]+"${SOURCES[@]}"}; do echo " ${s}"; done echo - echo "[Instrumented code - library object(s) used by llvm-cov]" - for o in "${OBJECTS[@]}"; do echo " ${o#${GITHUB_WORKSPACE}/}"; done + echo "[Instrumented code - object(s) used by llvm-cov]" + for o in ${OBJECTS[@]+"${OBJECTS[@]}"}; do echo " ${o#${GITHUB_WORKSPACE}/}"; done echo echo "[Libraries used by the coverage tooling]" for f in $(find "${OBJECTS_DIR}/bin" -maxdepth 1 -type f | sort); do echo " ${f#${GITHUB_WORKSPACE}/}"; done diff --git a/codecov.yml b/codecov.yml index 0b053b577024..48798920ecf7 100644 --- a/codecov.yml +++ b/codecov.yml @@ -57,6 +57,9 @@ coverage: rocThrust: flags: [rocThrust] target: 80% + rocPRIM: + flags: [rocPRIM] + target: 80% hipFFT: flags: [hipFFT] target: 80% diff --git a/projects/hipcub/CMakeLists.txt b/projects/hipcub/CMakeLists.txt index b152b21e8cd3..9fdad72d521e 100644 --- a/projects/hipcub/CMakeLists.txt +++ b/projects/hipcub/CMakeLists.txt @@ -76,6 +76,12 @@ include(CMakeDependentOption) # Build options option(BUILD_TEST "Build tests (requires googletest)" OFF) option(BUILD_CODE_COVERAGE "Enable code coverage" OFF) +# CI passes -DHIPCUB_ENABLE_COVERAGE=ON (the standardized coverage flag); map it +# onto BUILD_CODE_COVERAGE so the header-only library and its tests are instrumented. +option(HIPCUB_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) +if(HIPCUB_ENABLE_COVERAGE) + set(BUILD_CODE_COVERAGE ON) +endif() option(EXTERNAL_DEPS_FORCE_DOWNLOAD "Download non-ROCm dependencies and do not search for packages" OFF) option(DOWNLOAD_CUB "Download CUB and thrust. Do not search for CUB package" OFF) option(BUILD_BENCHMARK "Build benchmarks" OFF) diff --git a/projects/rocprim/CMakeLists.txt b/projects/rocprim/CMakeLists.txt index 3cc662611908..40316c483109 100644 --- a/projects/rocprim/CMakeLists.txt +++ b/projects/rocprim/CMakeLists.txt @@ -77,6 +77,12 @@ cmake_dependent_option(BUILD_EXAMPLE "Build examples" OFF "NOT ONLY_INSTALL" OFF option(BUILD_NAIVE_BENCHMARK "Build naive benchmarks" OFF) cmake_dependent_option(BUILD_DOCS "Build documentation (requires sphinx)" OFF "NOT ONLY_INSTALL" OFF) option(BUILD_CODE_COVERAGE "Build with code coverage enabled" OFF) +# CI passes -DROCPRIM_ENABLE_COVERAGE=ON (the standardized coverage flag); map it +# onto BUILD_CODE_COVERAGE so the header-only library and its tests are instrumented. +option(ROCPRIM_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) +if(ROCPRIM_ENABLE_COVERAGE) + set(BUILD_CODE_COVERAGE ON) +endif() option(ROCPRIM_INSTALL "Enable installation of rocPRIM (projects embedding rocPRIM may want to turn this OFF)" ON) option(ROCPRIM_ENABLE_ASSERTS "Enable asserts in release build)" OFF) cmake_dependent_option(ROCPRIM_ENABLE_TOPK "Enable the device level topk and segmented topk algorithms" OFF BUILD_TEST ON) diff --git a/projects/rocthrust/CMakeLists.txt b/projects/rocthrust/CMakeLists.txt index 643a730be4d8..66fb92ae466a 100644 --- a/projects/rocthrust/CMakeLists.txt +++ b/projects/rocthrust/CMakeLists.txt @@ -58,6 +58,12 @@ include(CMakeDependentOption) option(DISABLE_WERROR "Disable building with Werror" ON) option(BUILD_TEST "Build tests" OFF) option(CODE_COVERAGE "Enable code coverage" OFF) +# CI passes -DROCTHRUST_ENABLE_COVERAGE=ON (the standardized coverage flag); map it +# onto CODE_COVERAGE so the header-only library and its tests are instrumented. +option(ROCTHRUST_ENABLE_COVERAGE "Enable code coverage (alias for CODE_COVERAGE)" OFF) +if(ROCTHRUST_ENABLE_COVERAGE) + set(CODE_COVERAGE ON) +endif() option(BUILD_HIPSTDPAR_TEST "Build hipstdpar tests" OFF) option(BUILD_HIPSTDPAR_TEST_WITH_TBB "Build hipstdpar tests with TBB" OFF) option(BUILD_EXAMPLE "Build example" OFF) diff --git a/projects/rocthrust/cmake/Dependencies.cmake b/projects/rocthrust/cmake/Dependencies.cmake index 5abf60e95430..1e4bcd253392 100644 --- a/projects/rocthrust/cmake/Dependencies.cmake +++ b/projects/rocthrust/cmake/Dependencies.cmake @@ -329,11 +329,22 @@ if(BUILD_TEST OR BUILD_HIPSTDPAR_TEST) string(REPLACE "." "_" SQLITE_VER_UNDERSCORE ${SQLITE_MIN_VERSION}) if(SQLITE_USE_SYSTEM_PACKAGE) - find_package(SQLite3 ${SQLITE_MIN_VERSION} REQUIRED) + # Prefer a system SQLite3, but do not hard-fail (REQUIRED) when it is missing + # or reports an unsuitable/unknown version (seen with some sysdeps-provided + # SQLite3 configs, e.g. TheRock coverage builds). Fall back to the bundled + # download below so configure stays robust instead of breaking the build. + find_package(SQLite3 ${SQLITE_MIN_VERSION} QUIET) + endif() + + if(SQLITE_USE_SYSTEM_PACKAGE AND SQLite3_FOUND) list(APPEND static_depends PACKAGE SQLite3) set(ROCTHRUST_SQLITE_LIB SQLite::SQLite3) else() - message(STATUS "Force download local copy of SQLite on. Downloading and building SQLite.") + if(SQLITE_USE_SYSTEM_PACKAGE) + message(STATUS "Suitable system SQLite3 (>= ${SQLITE_MIN_VERSION}) not found; downloading a local copy.") + else() + message(STATUS "Force download local copy of SQLite on. Downloading and building SQLite.") + endif() if(DEFINED ENV{SQLITE_${SQLITE_VER_UNDERSCORE}_SRC_URL}) set(SQLITE_${SQLITE_VER_UNDERSCORE}_SRC_URL_INIT $ENV{SQLITE_${SQLITE_VER_UNDERSCORE}_SRC_URL}) else() diff --git a/test_categories_coverage.yaml b/test_categories_coverage.yaml index 38bd2fa60e06..0b8106f5adea 100644 --- a/test_categories_coverage.yaml +++ b/test_categories_coverage.yaml @@ -57,3 +57,36 @@ projects: ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/clients/.*|.*[Tt]ensile.*|.*/_deps/.*|.*deps.*' llvm_profile_pattern: '%m' test_category: quick + + # Header-only libraries: there is no shared library to instrument, so coverage + # is collected from the instrumented test binaries (matched by name prefix and + # staged from the build tree). test_binaries entries are name prefixes. + rocprim: + enabled: true + coverage_objects: + libraries: [] + test_binaries: + - test_ + ignore_filename_regex: '.*/test/.*|.*/benchmark/.*|.*/gtest/.*|.*/_deps/.*|.*deps.*' + llvm_profile_pattern: '%m' + test_category: quick + + hipcub: + enabled: true + coverage_objects: + libraries: [] + test_binaries: + - test_hipcub_ + ignore_filename_regex: '.*/test/.*|.*/benchmark/.*|.*/gtest/.*|.*/_deps/.*|.*deps.*' + llvm_profile_pattern: '%m' + test_category: quick + + rocthrust: + enabled: true + coverage_objects: + libraries: [] + test_binaries: + - test_thrust_ + ignore_filename_regex: '.*/testing/.*|.*/test/.*|.*/benchmark/.*|.*/gtest/.*|.*/_deps/.*|.*deps.*' + llvm_profile_pattern: '%m' + test_category: quick From 811bb4a1833d88e5ee74636f5751e45e89d9b3d7 Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Mon, 29 Jun 2026 10:53:04 +0000 Subject: [PATCH 75/79] scope header-only test binaries to the component's test subproject rocPRIM's tests build in a dedicated TheRock subproject ("rocPRIM_tests"), so the exact path-part scope match found no rocprim test binaries and the report failed with "No coverage object files could be resolved". Match the component build subdir as a substring of a path part so "_tests" subprojects are scoped correctly, while still excluding sibling components in the shared PRIM build. Co-authored-by: Cursor --- .github/scripts/export_coverage_metadata.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/scripts/export_coverage_metadata.py b/.github/scripts/export_coverage_metadata.py index 50ac5f7179ed..74772d3cae0a 100644 --- a/.github/scripts/export_coverage_metadata.py +++ b/.github/scripts/export_coverage_metadata.py @@ -82,7 +82,10 @@ def find_test_binaries(build_dir: Path, prefix: str, scope: str | None) -> list[ for path in build_dir.rglob(f"{prefix}*"): if not _looks_like_executable(path): continue - if scope and scope not in path.parts: + # Match the component build subdir as a substring of a path part, so the + # dedicated test subproject TheRock generates for some components (e.g. + # rocPRIM's tests live under "rocPRIM_tests") is still scoped correctly. + if scope and not any(scope in part for part in path.parts): continue name = path.name prev = by_name.get(name) From 8efef19a36087a2afcda2bc57c3cac95339cfccc Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Tue, 30 Jun 2026 10:45:23 +0000 Subject: [PATCH 76/79] gate coverage on _ENABLE_COVERAGE instead of shared vars Review feedback (reboss): aliasing the standardized _ENABLE_COVERAGE flag onto the shared BUILD_CODE_COVERAGE / CODE_COVERAGE / ROCBLAS_BUILD_COVERAGE switches risks inadvertently instrumenting other components. Instead, gate each project's instrumentation directly on its own _ENABLE_COVERAGE (OR'd with the project's legacy local switch) and stop toggling the shared variables, matching the existing hipRAND/hipDNN convention. rocFFT additionally guards its -fgpu-rdc opt-out on ROCFFT_ENABLE_COVERAGE so a coverage build still disables relocatable device code. Co-authored-by: Cursor --- projects/hipcub/CMakeLists.txt | 11 ++++------- projects/rocblas/CMakeLists.txt | 11 ++++------- projects/rocblas/library/CMakeLists.txt | 2 +- projects/rocfft/CMakeLists.txt | 10 ++++------ projects/rocfft/library/src/CMakeLists.txt | 4 ++-- projects/rocprim/CMakeLists.txt | 11 ++++------- projects/rocrand/CMakeLists.txt | 12 +++++------- projects/rocthrust/CMakeLists.txt | 11 ++++------- 8 files changed, 28 insertions(+), 44 deletions(-) diff --git a/projects/hipcub/CMakeLists.txt b/projects/hipcub/CMakeLists.txt index 9fdad72d521e..95196d8ed436 100644 --- a/projects/hipcub/CMakeLists.txt +++ b/projects/hipcub/CMakeLists.txt @@ -76,12 +76,9 @@ include(CMakeDependentOption) # Build options option(BUILD_TEST "Build tests (requires googletest)" OFF) option(BUILD_CODE_COVERAGE "Enable code coverage" OFF) -# CI passes -DHIPCUB_ENABLE_COVERAGE=ON (the standardized coverage flag); map it -# onto BUILD_CODE_COVERAGE so the header-only library and its tests are instrumented. -option(HIPCUB_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) -if(HIPCUB_ENABLE_COVERAGE) - set(BUILD_CODE_COVERAGE ON) -endif() +# CI passes -DHIPCUB_ENABLE_COVERAGE=ON (the standardized coverage flag); it is +# gated directly at the instrumentation site below (no shared variable toggled). +option(HIPCUB_ENABLE_COVERAGE "Enable code coverage" OFF) option(EXTERNAL_DEPS_FORCE_DOWNLOAD "Download non-ROCm dependencies and do not search for packages" OFF) option(DOWNLOAD_CUB "Download CUB and thrust. Do not search for CUB package" OFF) option(BUILD_BENCHMARK "Build benchmarks" OFF) @@ -208,7 +205,7 @@ endif() # hipCUB library add_subdirectory(hipcub) -if(BUILD_CODE_COVERAGE) +if(BUILD_CODE_COVERAGE OR HIPCUB_ENABLE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-instr-generate -fcoverage-mapping" ) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-instr-generate") endif() diff --git a/projects/rocblas/CMakeLists.txt b/projects/rocblas/CMakeLists.txt index 6e44008f6f5b..fc83cc19c0c6 100644 --- a/projects/rocblas/CMakeLists.txt +++ b/projects/rocblas/CMakeLists.txt @@ -325,13 +325,10 @@ if( BUILD_CLIENTS_SAMPLES OR BUILD_CLIENTS_TESTS OR BUILD_CLIENTS_BENCHMARKS ) endif() endif() -# CI passes -DROCBLAS_ENABLE_COVERAGE=ON (the standardized coverage flag); map it -# onto BUILD_CODE_COVERAGE before the library subdir is processed below. -option(ROCBLAS_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) -if( ROCBLAS_ENABLE_COVERAGE ) - set( BUILD_CODE_COVERAGE ON ) - set( ROCBLAS_BUILD_COVERAGE ON ) -endif() +# CI passes -DROCBLAS_ENABLE_COVERAGE=ON (the standardized coverage flag); it is +# gated directly at the instrumentation site (library/) without toggling the +# shared BUILD_CODE_COVERAGE / ROCBLAS_BUILD_COVERAGE variables. +option(ROCBLAS_ENABLE_COVERAGE "Enable code coverage" OFF) if( NOT SKIP_LIBRARY ) add_subdirectory( library ) diff --git a/projects/rocblas/library/CMakeLists.txt b/projects/rocblas/library/CMakeLists.txt index 631626fce546..17f2a757ab32 100644 --- a/projects/rocblas/library/CMakeLists.txt +++ b/projects/rocblas/library/CMakeLists.txt @@ -140,7 +140,7 @@ function( rocblas_library_settings lib_target_ ) set_target_properties( ${lib_target_} PROPERTIES PREFIX "lib" ) endif() - if(BUILD_CODE_COVERAGE) + if(BUILD_CODE_COVERAGE OR ROCBLAS_ENABLE_COVERAGE) target_compile_options(${lib_target_} PRIVATE -fprofile-instr-generate -fcoverage-mapping) target_link_options(${lib_target_} PRIVATE -fprofile-instr-generate) endif() diff --git a/projects/rocfft/CMakeLists.txt b/projects/rocfft/CMakeLists.txt index e086f7b4c155..7fcbd13415ee 100644 --- a/projects/rocfft/CMakeLists.txt +++ b/projects/rocfft/CMakeLists.txt @@ -223,12 +223,10 @@ if( ROCFFT_MPI_ENABLE ) include_directories(SYSTEM ${MPI_INCLUDE_PATH}) endif() -# CI passes -DROCFFT_ENABLE_COVERAGE=ON (the standardized coverage flag); map it -# onto BUILD_CODE_COVERAGE before the library subdir is processed below. -option(ROCFFT_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) -if( ROCFFT_ENABLE_COVERAGE ) - set( BUILD_CODE_COVERAGE ON ) -endif() +# CI passes -DROCFFT_ENABLE_COVERAGE=ON (the standardized coverage flag); it is +# gated directly at the instrumentation sites (library/src) without toggling the +# shared BUILD_CODE_COVERAGE variable. +option(ROCFFT_ENABLE_COVERAGE "Enable code coverage" OFF) # Internal (library-side) unit tests. enable_testing() must be called # here, an ancestor of library/src, for ctest to discover them. diff --git a/projects/rocfft/library/src/CMakeLists.txt b/projects/rocfft/library/src/CMakeLists.txt index 0bb72bc96d11..1df767fccb76 100644 --- a/projects/rocfft/library/src/CMakeLists.txt +++ b/projects/rocfft/library/src/CMakeLists.txt @@ -46,7 +46,7 @@ endfunction() # Add code coverage flags to a library target, if enabled function( rocfft_add_coverage_flags target ) - if( BUILD_CODE_COVERAGE ) + if( BUILD_CODE_COVERAGE OR ROCFFT_ENABLE_COVERAGE ) target_compile_options( ${target} PRIVATE -g -O0 -fprofile-instr-generate -fcoverage-mapping ) target_link_options( ${target} INTERFACE -fprofile-instr-generate ) endif() @@ -419,7 +419,7 @@ endif() # rocFFT contains default implementations of callback functions that # need to be built as relocatable device code (causes failure at link # stage on Windows) -if( NOT WIN32 AND NOT BUILD_CODE_COVERAGE ) +if( NOT WIN32 AND NOT BUILD_CODE_COVERAGE AND NOT ROCFFT_ENABLE_COVERAGE ) target_compile_options( rocfft PRIVATE -fgpu-rdc ) target_link_options( rocfft PRIVATE -fgpu-rdc ) endif() diff --git a/projects/rocprim/CMakeLists.txt b/projects/rocprim/CMakeLists.txt index 40316c483109..1f73fde83fb4 100644 --- a/projects/rocprim/CMakeLists.txt +++ b/projects/rocprim/CMakeLists.txt @@ -77,12 +77,9 @@ cmake_dependent_option(BUILD_EXAMPLE "Build examples" OFF "NOT ONLY_INSTALL" OFF option(BUILD_NAIVE_BENCHMARK "Build naive benchmarks" OFF) cmake_dependent_option(BUILD_DOCS "Build documentation (requires sphinx)" OFF "NOT ONLY_INSTALL" OFF) option(BUILD_CODE_COVERAGE "Build with code coverage enabled" OFF) -# CI passes -DROCPRIM_ENABLE_COVERAGE=ON (the standardized coverage flag); map it -# onto BUILD_CODE_COVERAGE so the header-only library and its tests are instrumented. -option(ROCPRIM_ENABLE_COVERAGE "Enable code coverage (alias for BUILD_CODE_COVERAGE)" OFF) -if(ROCPRIM_ENABLE_COVERAGE) - set(BUILD_CODE_COVERAGE ON) -endif() +# CI passes -DROCPRIM_ENABLE_COVERAGE=ON (the standardized coverage flag); it is +# gated directly at the instrumentation site below (no shared variable toggled). +option(ROCPRIM_ENABLE_COVERAGE "Enable code coverage" OFF) option(ROCPRIM_INSTALL "Enable installation of rocPRIM (projects embedding rocPRIM may want to turn this OFF)" ON) option(ROCPRIM_ENABLE_ASSERTS "Enable asserts in release build)" OFF) cmake_dependent_option(ROCPRIM_ENABLE_TOPK "Enable the device level topk and segmented topk algorithms" OFF BUILD_TEST ON) @@ -280,7 +277,7 @@ if (ROCPRIM_PROJECT_IS_TOP_LEVEL) ) endif() -if(BUILD_CODE_COVERAGE) +if(BUILD_CODE_COVERAGE OR ROCPRIM_ENABLE_COVERAGE) target_compile_options(rocprim INTERFACE -w -fprofile-instr-generate diff --git a/projects/rocrand/CMakeLists.txt b/projects/rocrand/CMakeLists.txt index d561fb845fe3..b56d38a6acb3 100644 --- a/projects/rocrand/CMakeLists.txt +++ b/projects/rocrand/CMakeLists.txt @@ -160,13 +160,11 @@ if(DISABLE_WERROR) else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") endif() -# CI passes -DROCRAND_ENABLE_COVERAGE=ON (the standardized coverage flag); -# map it onto the existing CODE_COVERAGE switch. -option(ROCRAND_ENABLE_COVERAGE "Enable code coverage (alias for CODE_COVERAGE)" OFF) -if(ROCRAND_ENABLE_COVERAGE) - set(CODE_COVERAGE ON) -endif() -if(CODE_COVERAGE) +# CI passes -DROCRAND_ENABLE_COVERAGE=ON (the standardized coverage flag). +# Gate instrumentation on it directly (alongside the legacy CODE_COVERAGE +# switch) rather than toggling a shared variable. +option(ROCRAND_ENABLE_COVERAGE "Enable code coverage" OFF) +if(CODE_COVERAGE OR ROCRAND_ENABLE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping") add_definitions(-DCODE_COVERAGE_ENABLED) endif() diff --git a/projects/rocthrust/CMakeLists.txt b/projects/rocthrust/CMakeLists.txt index 66fb92ae466a..d95cc129063e 100644 --- a/projects/rocthrust/CMakeLists.txt +++ b/projects/rocthrust/CMakeLists.txt @@ -58,12 +58,9 @@ include(CMakeDependentOption) option(DISABLE_WERROR "Disable building with Werror" ON) option(BUILD_TEST "Build tests" OFF) option(CODE_COVERAGE "Enable code coverage" OFF) -# CI passes -DROCTHRUST_ENABLE_COVERAGE=ON (the standardized coverage flag); map it -# onto CODE_COVERAGE so the header-only library and its tests are instrumented. -option(ROCTHRUST_ENABLE_COVERAGE "Enable code coverage (alias for CODE_COVERAGE)" OFF) -if(ROCTHRUST_ENABLE_COVERAGE) - set(CODE_COVERAGE ON) -endif() +# CI passes -DROCTHRUST_ENABLE_COVERAGE=ON (the standardized coverage flag); it is +# gated directly at the instrumentation site below (no shared variable toggled). +option(ROCTHRUST_ENABLE_COVERAGE "Enable code coverage" OFF) option(BUILD_HIPSTDPAR_TEST "Build hipstdpar tests" OFF) option(BUILD_HIPSTDPAR_TEST_WITH_TBB "Build hipstdpar tests with TBB" OFF) option(BUILD_EXAMPLE "Build example" OFF) @@ -243,7 +240,7 @@ if(BUILD_TEST OR BUILD_BENCHMARK OR BUILD_HIPSTDPAR_TEST) rocm_package_setup_component(clients) endif() -if(CODE_COVERAGE) +if(CODE_COVERAGE OR ROCTHRUST_ENABLE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -fprofile-instr-generate -fcoverage-mapping") endif() From 69b3ed3ea009f5f3e2ce1892ac2ff47e51c2a02e Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Tue, 30 Jun 2026 10:47:05 +0000 Subject: [PATCH 77/79] move codecov flag and rocThrust SQLite fallback to separate PRs Per review feedback, the codecov.yml rocPRIM flag and the rocThrust SQLite3 fallback are out-of-scope for this PR. They now live in their own PRs: - codecov rocPRIM flag: ROCm/rocm-libraries#8955 - rocThrust SQLite fallback: ROCm/rocm-libraries#8956 Note: the header-only (PRIM group) coverage build here depends on #8956 landing so rocThrust configure does not fail on find_package(SQLite3). Co-authored-by: Cursor --- codecov.yml | 3 --- projects/rocthrust/cmake/Dependencies.cmake | 15 ++------------- 2 files changed, 2 insertions(+), 16 deletions(-) diff --git a/codecov.yml b/codecov.yml index 48798920ecf7..0b053b577024 100644 --- a/codecov.yml +++ b/codecov.yml @@ -57,9 +57,6 @@ coverage: rocThrust: flags: [rocThrust] target: 80% - rocPRIM: - flags: [rocPRIM] - target: 80% hipFFT: flags: [hipFFT] target: 80% diff --git a/projects/rocthrust/cmake/Dependencies.cmake b/projects/rocthrust/cmake/Dependencies.cmake index 1e4bcd253392..5abf60e95430 100644 --- a/projects/rocthrust/cmake/Dependencies.cmake +++ b/projects/rocthrust/cmake/Dependencies.cmake @@ -329,22 +329,11 @@ if(BUILD_TEST OR BUILD_HIPSTDPAR_TEST) string(REPLACE "." "_" SQLITE_VER_UNDERSCORE ${SQLITE_MIN_VERSION}) if(SQLITE_USE_SYSTEM_PACKAGE) - # Prefer a system SQLite3, but do not hard-fail (REQUIRED) when it is missing - # or reports an unsuitable/unknown version (seen with some sysdeps-provided - # SQLite3 configs, e.g. TheRock coverage builds). Fall back to the bundled - # download below so configure stays robust instead of breaking the build. - find_package(SQLite3 ${SQLITE_MIN_VERSION} QUIET) - endif() - - if(SQLITE_USE_SYSTEM_PACKAGE AND SQLite3_FOUND) + find_package(SQLite3 ${SQLITE_MIN_VERSION} REQUIRED) list(APPEND static_depends PACKAGE SQLite3) set(ROCTHRUST_SQLITE_LIB SQLite::SQLite3) else() - if(SQLITE_USE_SYSTEM_PACKAGE) - message(STATUS "Suitable system SQLite3 (>= ${SQLITE_MIN_VERSION}) not found; downloading a local copy.") - else() - message(STATUS "Force download local copy of SQLite on. Downloading and building SQLite.") - endif() + message(STATUS "Force download local copy of SQLite on. Downloading and building SQLite.") if(DEFINED ENV{SQLITE_${SQLITE_VER_UNDERSCORE}_SRC_URL}) set(SQLITE_${SQLITE_VER_UNDERSCORE}_SRC_URL_INIT $ENV{SQLITE_${SQLITE_VER_UNDERSCORE}_SRC_URL}) else() From a13f790f762f75e15df823daa90c14ea4408e0db Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Tue, 30 Jun 2026 10:54:52 +0000 Subject: [PATCH 78/79] gate coverage solely on _ENABLE_COVERAGE Drop the legacy BUILD_CODE_COVERAGE / CODE_COVERAGE conditions from the instrumentation guards; the standardized _ENABLE_COVERAGE flag is the only switch needed to instrument each component. Co-authored-by: Cursor --- projects/hipcub/CMakeLists.txt | 2 +- projects/rocblas/library/CMakeLists.txt | 2 +- projects/rocfft/library/src/CMakeLists.txt | 4 ++-- projects/rocprim/CMakeLists.txt | 2 +- projects/rocrand/CMakeLists.txt | 4 +--- projects/rocthrust/CMakeLists.txt | 2 +- 6 files changed, 7 insertions(+), 9 deletions(-) diff --git a/projects/hipcub/CMakeLists.txt b/projects/hipcub/CMakeLists.txt index 95196d8ed436..aeae8a221f58 100644 --- a/projects/hipcub/CMakeLists.txt +++ b/projects/hipcub/CMakeLists.txt @@ -205,7 +205,7 @@ endif() # hipCUB library add_subdirectory(hipcub) -if(BUILD_CODE_COVERAGE OR HIPCUB_ENABLE_COVERAGE) +if(HIPCUB_ENABLE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-instr-generate -fcoverage-mapping" ) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-instr-generate") endif() diff --git a/projects/rocblas/library/CMakeLists.txt b/projects/rocblas/library/CMakeLists.txt index 17f2a757ab32..9c44f773c3c7 100644 --- a/projects/rocblas/library/CMakeLists.txt +++ b/projects/rocblas/library/CMakeLists.txt @@ -140,7 +140,7 @@ function( rocblas_library_settings lib_target_ ) set_target_properties( ${lib_target_} PROPERTIES PREFIX "lib" ) endif() - if(BUILD_CODE_COVERAGE OR ROCBLAS_ENABLE_COVERAGE) + if(ROCBLAS_ENABLE_COVERAGE) target_compile_options(${lib_target_} PRIVATE -fprofile-instr-generate -fcoverage-mapping) target_link_options(${lib_target_} PRIVATE -fprofile-instr-generate) endif() diff --git a/projects/rocfft/library/src/CMakeLists.txt b/projects/rocfft/library/src/CMakeLists.txt index 1df767fccb76..a6850936a806 100644 --- a/projects/rocfft/library/src/CMakeLists.txt +++ b/projects/rocfft/library/src/CMakeLists.txt @@ -46,7 +46,7 @@ endfunction() # Add code coverage flags to a library target, if enabled function( rocfft_add_coverage_flags target ) - if( BUILD_CODE_COVERAGE OR ROCFFT_ENABLE_COVERAGE ) + if( ROCFFT_ENABLE_COVERAGE ) target_compile_options( ${target} PRIVATE -g -O0 -fprofile-instr-generate -fcoverage-mapping ) target_link_options( ${target} INTERFACE -fprofile-instr-generate ) endif() @@ -419,7 +419,7 @@ endif() # rocFFT contains default implementations of callback functions that # need to be built as relocatable device code (causes failure at link # stage on Windows) -if( NOT WIN32 AND NOT BUILD_CODE_COVERAGE AND NOT ROCFFT_ENABLE_COVERAGE ) +if( NOT WIN32 AND NOT ROCFFT_ENABLE_COVERAGE ) target_compile_options( rocfft PRIVATE -fgpu-rdc ) target_link_options( rocfft PRIVATE -fgpu-rdc ) endif() diff --git a/projects/rocprim/CMakeLists.txt b/projects/rocprim/CMakeLists.txt index 1f73fde83fb4..b13bdf3eb9de 100644 --- a/projects/rocprim/CMakeLists.txt +++ b/projects/rocprim/CMakeLists.txt @@ -277,7 +277,7 @@ if (ROCPRIM_PROJECT_IS_TOP_LEVEL) ) endif() -if(BUILD_CODE_COVERAGE OR ROCPRIM_ENABLE_COVERAGE) +if(ROCPRIM_ENABLE_COVERAGE) target_compile_options(rocprim INTERFACE -w -fprofile-instr-generate diff --git a/projects/rocrand/CMakeLists.txt b/projects/rocrand/CMakeLists.txt index b56d38a6acb3..3226baa9f66f 100644 --- a/projects/rocrand/CMakeLists.txt +++ b/projects/rocrand/CMakeLists.txt @@ -161,10 +161,8 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") endif() # CI passes -DROCRAND_ENABLE_COVERAGE=ON (the standardized coverage flag). -# Gate instrumentation on it directly (alongside the legacy CODE_COVERAGE -# switch) rather than toggling a shared variable. option(ROCRAND_ENABLE_COVERAGE "Enable code coverage" OFF) -if(CODE_COVERAGE OR ROCRAND_ENABLE_COVERAGE) +if(ROCRAND_ENABLE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping") add_definitions(-DCODE_COVERAGE_ENABLED) endif() diff --git a/projects/rocthrust/CMakeLists.txt b/projects/rocthrust/CMakeLists.txt index d95cc129063e..869df7be0636 100644 --- a/projects/rocthrust/CMakeLists.txt +++ b/projects/rocthrust/CMakeLists.txt @@ -240,7 +240,7 @@ if(BUILD_TEST OR BUILD_BENCHMARK OR BUILD_HIPSTDPAR_TEST) rocm_package_setup_component(clients) endif() -if(CODE_COVERAGE OR ROCTHRUST_ENABLE_COVERAGE) +if(ROCTHRUST_ENABLE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -fprofile-instr-generate -fcoverage-mapping") endif() From ed256d94bc1320f55b6fb0cd068e0969ef0c839e Mon Sep 17 00:00:00 2001 From: Pradeep Kumar Jain Date: Thu, 9 Jul 2026 07:03:30 +0000 Subject: [PATCH 79/79] drop non-rocBLAS coverage components (keep only rocBLAS) Only rocBLAS currently builds and produces a coverage report. After the develop merge pulled in the primbench benchmark (which includes and does not compile in the coverage build), the Build Coverage stage fails for every other component (hipRAND, rocRAND, rocFFT, rocPRIM, hipCUB, rocThrust). Trim the PR to just the working rocBLAS shared-object coverage: - therock_configure_coverage.py: drop the six entries from COVERAGE_PROJECT_METADATA (the coverage job matrix is generated from it), leaving only rocblas. - test_categories_coverage.yaml: drop the six project configs, leaving only rocblas. - revert each removed component's CMakeLists.txt coverage instrumentation back to develop (its _ENABLE_COVERAGE gating and the hipRAND llvm-tool hints), so those files are no longer touched by this PR. Shared coverage infrastructure (workflows, coverage_runner.py, export_coverage_metadata.py) and codecov.yml are unchanged. Co-authored-by: Cursor --- .github/scripts/therock_configure_coverage.py | 33 ---------- projects/hipcub/CMakeLists.txt | 5 +- projects/hiprand/CMakeLists.txt | 6 +- projects/hiprand/test/CMakeLists.txt | 18 ++--- projects/rocfft/CMakeLists.txt | 4 -- projects/rocfft/library/src/CMakeLists.txt | 4 +- projects/rocprim/CMakeLists.txt | 5 +- projects/rocrand/CMakeLists.txt | 4 +- projects/rocthrust/CMakeLists.txt | 5 +- test_categories_coverage.yaml | 66 ------------------- 10 files changed, 18 insertions(+), 132 deletions(-) diff --git a/.github/scripts/therock_configure_coverage.py b/.github/scripts/therock_configure_coverage.py index 161fd244118b..e169359f6a50 100644 --- a/.github/scripts/therock_configure_coverage.py +++ b/.github/scripts/therock_configure_coverage.py @@ -17,44 +17,11 @@ # to just this project so the coverage job does not inherit the (possibly merged) # mega-group options that would otherwise build unrelated components. COVERAGE_PROJECT_METADATA = { - "hiprand": ( - "hipRAND", - "ml-libs/hipRAND", - "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF", - ), - "rocrand": ( - "rocRAND", - "math-libs/rocRAND", - "-DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF", - ), - "rocfft": ( - "rocFFT", - "math-libs/rocFFT", - "-DTHEROCK_ENABLE_FFT=ON -DTHEROCK_ENABLE_RAND=ON -DTHEROCK_ENABLE_ALL=OFF", - ), "rocblas": ( "rocBLAS", "math-libs/rocBLAS", "-DTHEROCK_ENABLE_BLAS=ON -DTHEROCK_ENABLE_ALL=OFF", ), - # Header-only libraries: coverage comes from the instrumented test binaries - # (there is no shared library to instrument). All three build together in - # TheRock's PRIM group. - "rocprim": ( - "rocPRIM", - "math-libs/rocPRIM", - "-DTHEROCK_ENABLE_PRIM=ON -DTHEROCK_ENABLE_ALL=OFF", - ), - "hipcub": ( - "hipCUB", - "math-libs/hipCUB", - "-DTHEROCK_ENABLE_PRIM=ON -DTHEROCK_ENABLE_ALL=OFF", - ), - "rocthrust": ( - "rocThrust", - "math-libs/rocThrust", - "-DTHEROCK_ENABLE_PRIM=ON -DTHEROCK_ENABLE_ALL=OFF", - ), } diff --git a/projects/hipcub/CMakeLists.txt b/projects/hipcub/CMakeLists.txt index aeae8a221f58..b152b21e8cd3 100644 --- a/projects/hipcub/CMakeLists.txt +++ b/projects/hipcub/CMakeLists.txt @@ -76,9 +76,6 @@ include(CMakeDependentOption) # Build options option(BUILD_TEST "Build tests (requires googletest)" OFF) option(BUILD_CODE_COVERAGE "Enable code coverage" OFF) -# CI passes -DHIPCUB_ENABLE_COVERAGE=ON (the standardized coverage flag); it is -# gated directly at the instrumentation site below (no shared variable toggled). -option(HIPCUB_ENABLE_COVERAGE "Enable code coverage" OFF) option(EXTERNAL_DEPS_FORCE_DOWNLOAD "Download non-ROCm dependencies and do not search for packages" OFF) option(DOWNLOAD_CUB "Download CUB and thrust. Do not search for CUB package" OFF) option(BUILD_BENCHMARK "Build benchmarks" OFF) @@ -205,7 +202,7 @@ endif() # hipCUB library add_subdirectory(hipcub) -if(HIPCUB_ENABLE_COVERAGE) +if(BUILD_CODE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-instr-generate -fcoverage-mapping" ) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-instr-generate") endif() diff --git a/projects/hiprand/CMakeLists.txt b/projects/hiprand/CMakeLists.txt index 9bf722597e10..cb444a32340d 100644 --- a/projects/hiprand/CMakeLists.txt +++ b/projects/hiprand/CMakeLists.txt @@ -58,7 +58,7 @@ project(hipRAND CXX) # Build options option(BUILD_ADDRESS_SANITIZER "Build with address sanitizer enabled" OFF) option(BUILD_BENCHMARK "Build benchmarks" OFF) -option(HIPRAND_ENABLE_COVERAGE "Build with code coverage enabled" OFF) +option(BUILD_CODE_COVERAGE "Build with code coverage enabled" OFF) option(BUILD_FORTRAN_WRAPPER "Build Fortran wrapper" OFF) option(BUILD_TEST "Build tests (requires googletest)" OFF) option(EXTERNAL_DEPS_FORCE_DOWNLOAD "Download non-ROCm dependencies and do not search for packages" OFF) @@ -244,7 +244,7 @@ else() set(package_name hiprand) endif() -if(HIPRAND_ENABLE_COVERAGE) +if(BUILD_CODE_COVERAGE) target_compile_options(hiprand PRIVATE -g -O0 -fprofile-instr-generate -fcoverage-mapping) target_link_options(hiprand PUBLIC -fprofile-instr-generate) endif() @@ -255,4 +255,4 @@ rocm_create_package( MAINTAINER "hipRAND Maintainer " LDCONFIG LDCONFIG_DIR ${HIPRAND_CONFIG_DIR} -) +) \ No newline at end of file diff --git a/projects/hiprand/test/CMakeLists.txt b/projects/hiprand/test/CMakeLists.txt index 6867b1ecc5bf..ad0dc409060b 100644 --- a/projects/hiprand/test/CMakeLists.txt +++ b/projects/hiprand/test/CMakeLists.txt @@ -67,7 +67,7 @@ function(add_relative_test test_name test_target) endif() file(RELATIVE_PATH rel_path "${CMAKE_CURRENT_BINARY_DIR}" "${EXE_PATH}/${EXE_NAME}") add_test(NAME "${test_name}" COMMAND "./${rel_path}") - if(HIPRAND_ENABLE_COVERAGE) + if(BUILD_CODE_COVERAGE) set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${PROFILE_DIR}/profraw/hiprand-coverage_%m.profraw" ) @@ -78,7 +78,7 @@ endfunction() # Get hipRAND tests source files file(GLOB hipRAND_TEST_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/test_hiprand*.cpp) -if(HIPRAND_ENABLE_COVERAGE) +if(BUILD_CODE_COVERAGE) add_custom_target( coverage_analysis DEPENDS hiprand @@ -93,7 +93,7 @@ if(HIPRAND_ENABLE_COVERAGE) LLVM_PROFDATA llvm-profdata REQUIRED - HINTS ${LLVM_TOOLS_SEARCH_PREFIX}/bin ${ROCM_PATH}/llvm/bin + HINTS ${ROCM_PATH}/llvm/bin PATHS /opt/rocm/llvm/bin ) @@ -101,7 +101,7 @@ if(HIPRAND_ENABLE_COVERAGE) LLVM_COV llvm-cov REQUIRED - HINTS ${LLVM_TOOLS_SEARCH_PREFIX}/bin ${ROCM_PATH}/llvm/bin + HINTS ${ROCM_PATH}/llvm/bin PATHS /opt/rocm/llvm/bin ) @@ -109,9 +109,9 @@ if(HIPRAND_ENABLE_COVERAGE) coverage DEPENDS coverage_analysis COMMAND ${LLVM_PROFDATA} merge -sparse ${PROFILE_DIR}/profraw/hiprand-coverage_*.profraw -o ${PROFILE_DIR}/hiprand.profdata - COMMAND ${LLVM_COV} report -object $ -instr-profile=${PROFILE_DIR}/hiprand.profdata - COMMAND ${LLVM_COV} show -object $ -instr-profile=${PROFILE_DIR}/hiprand.profdata -format=html -output-dir=${PROFILE_DIR} - COMMAND ${LLVM_COV} export -object $ -instr-profile=${PROFILE_DIR}/hiprand.profdata -format=lcov > ${PROFILE_DIR}/coverage.info + COMMAND ${LLVM_COV} report -object ${CMAKE_BINARY_DIR}/library/libhiprand-d.so -instr-profile=${PROFILE_DIR}/hiprand.profdata + COMMAND ${LLVM_COV} show -object ${CMAKE_BINARY_DIR}/library/libhiprand-d.so -instr-profile=${PROFILE_DIR}/hiprand.profdata -format=html -output-dir=${PROFILE_DIR} + COMMAND ${LLVM_COV} export -object ${CMAKE_BINARY_DIR}/library/libhiprand-d.so -instr-profile=${PROFILE_DIR}/hiprand.profdata -format=lcov > ${PROFILE_DIR}/coverage.info WORKING_DIRECTORY ${CMAKE_BINARY_DIR} ) endif() @@ -161,7 +161,7 @@ foreach(test_src ${hipRAND_TEST_SRCS}) RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/test" ) add_relative_test(${test_name} ${test_name}) - if(HIPRAND_ENABLE_COVERAGE) + if(BUILD_CODE_COVERAGE) set_tests_properties(${test_name} PROPERTIES ENVIRONMENT "LLVM_PROFILE_FILE=${PROFILE_DIR}/profraw/hiprand-coverage_%m.profraw" ) @@ -184,7 +184,7 @@ foreach(test_src ${hipRAND_TEST_SRCS}) endforeach( file_i ) endif() - if (HIPRAND_ENABLE_COVERAGE) + if (BUILD_CODE_COVERAGE) add_dependencies(coverage_analysis ${test_name}) endif() endforeach() diff --git a/projects/rocfft/CMakeLists.txt b/projects/rocfft/CMakeLists.txt index 7690c7c99d97..a9962d082d54 100644 --- a/projects/rocfft/CMakeLists.txt +++ b/projects/rocfft/CMakeLists.txt @@ -223,10 +223,6 @@ if( ROCFFT_MPI_ENABLE ) include_directories(SYSTEM ${MPI_INCLUDE_PATH}) endif() -# CI passes -DROCFFT_ENABLE_COVERAGE=ON (the standardized coverage flag); it is -# gated directly at the instrumentation sites (library/src) without toggling the -# shared BUILD_CODE_COVERAGE variable. -option(ROCFFT_ENABLE_COVERAGE "Enable code coverage" OFF) # Optional RCCL backend for single-node multi-GPU communication. option(ROCFFT_RCCL_ENABLE "Enable RCCL for optimized single-node multi-GPU communication" OFF) diff --git a/projects/rocfft/library/src/CMakeLists.txt b/projects/rocfft/library/src/CMakeLists.txt index fc4ca5951a0f..ea6ae08b9d72 100644 --- a/projects/rocfft/library/src/CMakeLists.txt +++ b/projects/rocfft/library/src/CMakeLists.txt @@ -46,7 +46,7 @@ endfunction() # Add code coverage flags to a library target, if enabled function( rocfft_add_coverage_flags target ) - if( ROCFFT_ENABLE_COVERAGE ) + if( BUILD_CODE_COVERAGE ) target_compile_options( ${target} PRIVATE -g -O0 -fprofile-instr-generate -fcoverage-mapping ) target_link_options( ${target} INTERFACE -fprofile-instr-generate ) endif() @@ -432,7 +432,7 @@ endif() # rocFFT contains default implementations of callback functions that # need to be built as relocatable device code (causes failure at link # stage on Windows) -if( NOT WIN32 AND NOT ROCFFT_ENABLE_COVERAGE ) +if( NOT WIN32 AND NOT BUILD_CODE_COVERAGE ) target_compile_options( rocfft PRIVATE -fgpu-rdc ) target_link_options( rocfft PRIVATE -fgpu-rdc ) endif() diff --git a/projects/rocprim/CMakeLists.txt b/projects/rocprim/CMakeLists.txt index b13bdf3eb9de..3cc662611908 100644 --- a/projects/rocprim/CMakeLists.txt +++ b/projects/rocprim/CMakeLists.txt @@ -77,9 +77,6 @@ cmake_dependent_option(BUILD_EXAMPLE "Build examples" OFF "NOT ONLY_INSTALL" OFF option(BUILD_NAIVE_BENCHMARK "Build naive benchmarks" OFF) cmake_dependent_option(BUILD_DOCS "Build documentation (requires sphinx)" OFF "NOT ONLY_INSTALL" OFF) option(BUILD_CODE_COVERAGE "Build with code coverage enabled" OFF) -# CI passes -DROCPRIM_ENABLE_COVERAGE=ON (the standardized coverage flag); it is -# gated directly at the instrumentation site below (no shared variable toggled). -option(ROCPRIM_ENABLE_COVERAGE "Enable code coverage" OFF) option(ROCPRIM_INSTALL "Enable installation of rocPRIM (projects embedding rocPRIM may want to turn this OFF)" ON) option(ROCPRIM_ENABLE_ASSERTS "Enable asserts in release build)" OFF) cmake_dependent_option(ROCPRIM_ENABLE_TOPK "Enable the device level topk and segmented topk algorithms" OFF BUILD_TEST ON) @@ -277,7 +274,7 @@ if (ROCPRIM_PROJECT_IS_TOP_LEVEL) ) endif() -if(ROCPRIM_ENABLE_COVERAGE) +if(BUILD_CODE_COVERAGE) target_compile_options(rocprim INTERFACE -w -fprofile-instr-generate diff --git a/projects/rocrand/CMakeLists.txt b/projects/rocrand/CMakeLists.txt index f463d9cafefb..6aefbbfbdfd5 100644 --- a/projects/rocrand/CMakeLists.txt +++ b/projects/rocrand/CMakeLists.txt @@ -160,9 +160,7 @@ if(DISABLE_WERROR) else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Werror") endif() -# CI passes -DROCRAND_ENABLE_COVERAGE=ON (the standardized coverage flag). -option(ROCRAND_ENABLE_COVERAGE "Enable code coverage" OFF) -if(ROCRAND_ENABLE_COVERAGE) +if(CODE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-instr-generate -fcoverage-mapping") add_definitions(-DCODE_COVERAGE_ENABLED) endif() diff --git a/projects/rocthrust/CMakeLists.txt b/projects/rocthrust/CMakeLists.txt index f611616ee3b1..467bb97f7549 100644 --- a/projects/rocthrust/CMakeLists.txt +++ b/projects/rocthrust/CMakeLists.txt @@ -58,9 +58,6 @@ include(CMakeDependentOption) option(DISABLE_WERROR "Disable building with Werror" ON) option(BUILD_TEST "Build tests" OFF) option(CODE_COVERAGE "Enable code coverage" OFF) -# CI passes -DROCTHRUST_ENABLE_COVERAGE=ON (the standardized coverage flag); it is -# gated directly at the instrumentation site below (no shared variable toggled). -option(ROCTHRUST_ENABLE_COVERAGE "Enable code coverage" OFF) option(BUILD_HIPSTDPAR_TEST "Build hipstdpar tests" OFF) option(BUILD_HIPSTDPAR_TEST_WITH_TBB "Build hipstdpar tests with TBB" OFF) option(BUILD_EXAMPLE "Build example" OFF) @@ -240,7 +237,7 @@ if(BUILD_TEST OR BUILD_BENCHMARK OR BUILD_HIPSTDPAR_TEST) rocm_package_setup_component(clients) endif() -if(ROCTHRUST_ENABLE_COVERAGE) +if(CODE_COVERAGE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0 -fprofile-instr-generate -fcoverage-mapping") endif() diff --git a/test_categories_coverage.yaml b/test_categories_coverage.yaml index 0b8106f5adea..41aa3aaed7ac 100644 --- a/test_categories_coverage.yaml +++ b/test_categories_coverage.yaml @@ -14,39 +14,6 @@ # per instrumented binary so parallel tests do not clobber each other. # * `test_category` is the ctest label coverage tests run under. projects: - hiprand: - enabled: true - coverage_objects: - # hipRAND is a thin wrapper; coverage is collected from the wrapper lib. - libraries: - - libhiprand.so - test_binaries: [] - ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/_deps/.*|.*deps.*' - llvm_profile_pattern: '%m' - test_category: quick - - rocrand: - enabled: true - coverage_objects: - # Coverage is collected from the rocRAND device library. - libraries: - - librocrand.so - test_binaries: [] - ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/benchmark/.*|.*/_deps/.*|.*deps.*' - llvm_profile_pattern: '%m' - test_category: quick - - rocfft: - enabled: true - coverage_objects: - # Coverage is collected from the rocFFT library. - libraries: - - librocfft.so - test_binaries: [] - ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/clients/.*|.*/_deps/.*|.*deps.*' - llvm_profile_pattern: '%m' - test_category: quick - rocblas: enabled: true coverage_objects: @@ -57,36 +24,3 @@ projects: ignore_filename_regex: '.*/test/.*|.*/tests/.*|.*/clients/.*|.*[Tt]ensile.*|.*/_deps/.*|.*deps.*' llvm_profile_pattern: '%m' test_category: quick - - # Header-only libraries: there is no shared library to instrument, so coverage - # is collected from the instrumented test binaries (matched by name prefix and - # staged from the build tree). test_binaries entries are name prefixes. - rocprim: - enabled: true - coverage_objects: - libraries: [] - test_binaries: - - test_ - ignore_filename_regex: '.*/test/.*|.*/benchmark/.*|.*/gtest/.*|.*/_deps/.*|.*deps.*' - llvm_profile_pattern: '%m' - test_category: quick - - hipcub: - enabled: true - coverage_objects: - libraries: [] - test_binaries: - - test_hipcub_ - ignore_filename_regex: '.*/test/.*|.*/benchmark/.*|.*/gtest/.*|.*/_deps/.*|.*deps.*' - llvm_profile_pattern: '%m' - test_category: quick - - rocthrust: - enabled: true - coverage_objects: - libraries: [] - test_binaries: - - test_thrust_ - ignore_filename_regex: '.*/testing/.*|.*/test/.*|.*/benchmark/.*|.*/gtest/.*|.*/_deps/.*|.*deps.*' - llvm_profile_pattern: '%m' - test_category: quick