[libc-commits] [libc] [llvm] Implement Automated Line and MC/DC Coverage CI Workflows (PR #219165)

via libc-commits libc-commits at lists.llvm.org
Wed Sep 2 10:06:16 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-libc

Author: Tapiwa Gonga (tapiwagonga)

<details>
<summary>Changes</summary>

 I previously wrote an RFC regarding [Enabling Code Coverage in LLVM-libc](https://discourse.llvm.org/t/rfc-libc-enabling-code-coverage-in-llvm-libc/91355) to  address the circular dependencies and link-time failures caused by standard compiler-rt profiling in hermetic (-nostdlib) testing environments. After incorporating community feedback, the core freestanding instrumentation was merged in [Code Coverage via Linux Syscalls](https://github.com/llvm/llvm-project/pull/213271).

Following that integration, I evaluated how best to surface this coverage data automatically within the monorepo. This resulted in a second RFC proposing an [Automated Code Coverage Infrastructure](https://discourse.llvm.org/t/rfc-libc-automated-code-coverage-infrastructure-and-ci-workflows/91534) utilising GitHub Actions to track coverage on commit. This pull request implements that infrastructure.

Developer instructions on how to run coverage locally have been published in [How To Run Code Coverage](https://github.com/llvm/llvm-project/pull/214692).

**Implementation Details**
The architecture of this infrastructure is explicitly decoupled into execution workflows and zero-dependency analytical scripts. The pipeline is entirely self-contained within the monorepo. The GitHub Actions workflows compile the test suite, generate the raw coverage payloads using` llvm-cov`, and pipe that data into the Python analysers to render native Markdown summaries. 
This submission consists of 8 cohesive files:

_GitHub Actions Workflows (`.github/workflows/`):_
Execution Model:These workflows leverage the official `ghcr.io/llvm/libc-ubuntu-24.04` container. By using a pre-installed toolchain and building exclusively at the runtimes layer (`-DLLVM_ENABLE_RUNTIMES=libc`), they eliminate the overhead of compiling Clang from source.

Pre-commit bots (`libc-patch-coverage.yml, libc-patch-mcdc.yml)` that evaluate patch diffs and provide actionable diagnostics regarding unexecuted lines and unverified boolean conditions on pull requests.

Post-commit bots (`libc-full-coverage.yml, libc-full-mcdc.yml`) that aggregate repository-wide metrics across all directories on a daily schedule.

_In-Tree Reporting Analysers (`libc/utils/coverage/`):_
`diff_coverage.py`: A Python utility that intercepts llvm-cov JSON exports, correlates them against unified Git diffs, filters out non-executable code lines (comments, macros, braces), and strictly evaluates MC/DC bitmasks to determine patch completeness.

`codebase_coverage.py`: Aggregates full repository execution segments into top-level directories (e.g., `src/math, src/string)`, It implements explicit path filtering to drop internal mock dependencies and test infrastructure (`libc/test/`), ensuring the final metrics accurately reflect the core library implementation.

**Unit Tests**
The Python reporting scripts are supported by fast-executing unit test suites that verify the underlying analysis algorithms using synthetic, in-memory data structures:

`test_diff_coverage.py`: Verifies the integrity of the patch evaluation pipeline, including Git diff parsing, C++ heuristic filtering, segment intersection math, and MC/DC boolean extraction.

`test_codebase_coverage.py`: Verifies the global repository tracking logic, specifically asserting directory-level metric aggregation and infrastructure path exclusion.



---

Patch is 95.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/219165.diff


8 Files Affected:

- (added) .github/workflows/libc-full-coverage.yml (+143) 
- (added) .github/workflows/libc-full-mcdc.yml (+149) 
- (added) .github/workflows/libc-patch-coverage.yml (+362) 
- (added) .github/workflows/libc-patch-mcdc.yml (+370) 
- (added) libc/utils/coverage/codebase_coverage.py (+308) 
- (added) libc/utils/coverage/diff_coverage.py (+661) 
- (added) libc/utils/coverage/test_codebase_coverage.py (+82) 
- (added) libc/utils/coverage/test_diff_coverage.py (+256) 


``````````diff
diff --git a/.github/workflows/libc-full-coverage.yml b/.github/workflows/libc-full-coverage.yml
new file mode 100644
index 0000000000000..ebaa9f2a39fb6
--- /dev/null
+++ b/.github/workflows/libc-full-coverage.yml
@@ -0,0 +1,143 @@
+name: Libc Full Codebase Coverage
+
+permissions:
+  contents: write # Required to publish live HTML dashboard to gh-pages branch
+
+env:
+  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
+
+on:
+  # Daily overnight run at 02:00 UTC
+  schedule:
+    - cron: '0 2 * * *'
+
+  # Allow manual on-demand execution from GitHub Actions UI
+  workflow_dispatch:
+
+  # Trigger on pushes to main / libc-coverage-ci-bots / post-commit-bot
+  push:
+    branches:
+      - main
+      - libc-coverage-ci-bots
+      - post-commit-bot
+    paths:
+      - 'libc/**'
+      - '.github/workflows/libc-full-coverage.yml'
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  full-coverage:
+    timeout-minutes: 60
+    name: libc-full-coverage
+    runs-on: ubuntu-24.04
+    container:
+      image: ghcr.io/llvm/libc-ubuntu-24.04:latest at sha256:8fee4c9ce5a1fd095686593cd36e032c48a31b6ae575378c82accd1d86a08d59
+      options: --privileged
+    defaults:
+      run:
+        shell: bash
+    steps:
+    - name: Checkout Code
+      uses: actions/checkout at v4
+      with:
+        fetch-depth: 1
+        persist-credentials: false
+
+    - name: Setup Compiler Cache (sccache)
+      uses: hendrikmuhs/ccache-action at v1.2.23
+      with:
+        max-size: 1G
+        key: libc_coverage_unified_v2_x86_64
+        variant: sccache
+
+    - name: Configure CMake
+      run: |
+        echo "=== [STAGE 1/4] Starting CMake Configuration at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+        START_TIME=$(date +%s)
+
+        export CMAKE_FLAGS="
+          -G Ninja
+          -S runtimes
+          -B build-cov
+          -DCMAKE_C_COMPILER=clang-23
+          -DCMAKE_CXX_COMPILER=clang++-23
+          -DCMAKE_BUILD_TYPE=Debug
+          -DCMAKE_C_COMPILER_LAUNCHER=sccache
+          -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
+          -DLLVM_USE_LINKER=lld-23
+          -DLLVM_ENABLE_RUNTIMES=libc
+          -DLLVM_LIBC_FULL_BUILD=ON
+          -DLIBC_ENABLE_COVERAGE=ON
+          -DLIBC_TEST_UNIT_TEST_ONLY=ON
+          -DLIBC_TEST_SKIP_DEATH_TESTS=ON
+          -DLIBC_TEST_SKIP_SHARED_TESTS=ON
+        "
+        cmake $CMAKE_FLAGS
+
+        END_TIME=$(date +%s)
+        echo "=== [STAGE 1/4] CMake Configuration Completed in $((END_TIME - START_TIME))s ==="
+
+    - name: Run Full Codebase Unit Tests
+      run: |
+        echo "=== [STAGE 2/4] Running Full Unit Test Suite at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+        START_TIME=$(date +%s)
+
+        export LLVM_PROFILE_FILE="libc_cov_%p.profraw"
+        ninja -k 0 -C build-cov libc-unit-tests || true
+
+        END_TIME=$(date +%s)
+        echo "=== [STAGE 2/4] libc-unit-tests Completed in $((END_TIME - START_TIME))s ==="
+
+    - name: Merge Profiles
+      run: |
+        echo "=== [STAGE 3/4] Merging Raw Profiles at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+        find . build-cov -name "libc_cov_*.profraw" > profraw_list.txt
+        NUM_PROFS=$(wc -l < profraw_list.txt || echo 0)
+        echo "[LOG] Discovered $NUM_PROFS raw profile data files."
+        llvm-profdata-23 merge -sparse --input-files=profraw_list.txt -o libc_full.profdata
+        echo "[LOG] Merged full codebase profile into libc_full.profdata."
+
+    - name: Generate Reports and Summary
+      env:
+        COMMIT_SHA: ${{ github.sha }}
+        BRANCH_REF: ${{ github.ref_name }}
+      run: |
+        echo "=== [STAGE 4/4] Generating Full Codebase Coverage Reports at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+        EXECUTABLES=($(find build-cov -type f -executable -name "*__build__"))
+        OBJECTS=("${EXECUTABLES[@]:1}")
+        OBJECTS=("${OBJECTS[@]/#/-object=}")
+
+        echo "[LOG] Exporting coverage data across ${#EXECUTABLES[@]} test binaries."
+
+        # 1. Generate JSON export for Full Coverage Analyzer
+        llvm-cov-23 export -format=text -instr-profile=libc_full.profdata "${EXECUTABLES[0]}" "${OBJECTS[@]}" > coverage.json
+
+        # 2. Generate HTML Coverage Report with directory hierarchy and branch tracking
+        llvm-cov-23 show -format=html \
+          -output-dir=coverage_html \
+          -instr-profile=libc_full.profdata \
+          "${EXECUTABLES[0]}" "${OBJECTS[@]}" \
+          --show-directory-coverage \
+          --show-branches=count \
+          --compilation-dir=. \
+          --path-equivalence="$GITHUB_WORKSPACE,." \
+          -ignore-filename-regex=".*(test|utils).*"
+        touch coverage_html/.nojekyll
+
+        # 3. Run Codebase Coverage Analyzer
+        PYTHONPATH="libc/utils/coverage" python3 libc/utils/coverage/codebase_coverage.py coverage.json "$COMMIT_SHA" "$BRANCH_REF" >> $GITHUB_STEP_SUMMARY
+        echo "[LOG] Post-commit summary report written to GITHUB_STEP_SUMMARY."
+
+    - name: Deploy Coverage Dashboard to GitHub Pages
+      if: github.repository != 'llvm/llvm-project'
+      continue-on-error: true
+      uses: peaceiris/actions-gh-pages at v4
+      with:
+        github_token: ${{ secrets.GITHUB_TOKEN }}
+        publish_dir: ./coverage_html
+        keep_files: true
+        enable_jekyll: false
+        force_orphan: false
diff --git a/.github/workflows/libc-full-mcdc.yml b/.github/workflows/libc-full-mcdc.yml
new file mode 100644
index 0000000000000..fdebc1c66f399
--- /dev/null
+++ b/.github/workflows/libc-full-mcdc.yml
@@ -0,0 +1,149 @@
+name: Libc Full Codebase MC/DC Coverage
+
+permissions:
+  contents: write
+
+env:
+  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
+
+on:
+  # Daily overnight run at 02:30 UTC (staggered by 30 mins from baseline sweep)
+  schedule:
+    - cron: '30 2 * * *'
+
+  # Allow manual on-demand execution from GitHub Actions UI ("Run workflow" button)
+  workflow_dispatch:
+
+  # Trigger on pushes to main / libc-mcdc-coverage / post-commit-bot
+  push:
+    branches:
+      - main
+      - libc-mcdc-coverage
+      - post-commit-bot
+    paths:
+      - 'libc/**'
+      - '.github/workflows/libc-full-mcdc.yml'
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  full-mcdc-coverage:
+    timeout-minutes: 60
+    name: libc-full-mcdc-coverage
+    runs-on: ubuntu-24.04
+    container:
+      image: ghcr.io/llvm/libc-ubuntu-24.04:latest at sha256:8fee4c9ce5a1fd095686593cd36e032c48a31b6ae575378c82accd1d86a08d59
+      options: --privileged
+    defaults:
+      run:
+        shell: bash
+    steps:
+      - name: Checkout Code
+        uses: actions/checkout at v4
+        with:
+          fetch-depth: 1
+          persist-credentials: false
+
+      - name: Setup Compiler Cache (sccache)
+        uses: hendrikmuhs/ccache-action at v1.2.23
+        with:
+          max-size: 1G
+          key: libc_mcdc_coverage_unified_x86_64
+          variant: sccache
+
+      - name: Configure CMake with MC/DC
+        run: |
+          echo "=== [STAGE 1/4] Starting CMake Configuration (MC/DC) at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+          START_TIME=$(date +%s)
+
+          export CMAKE_FLAGS="
+            -G Ninja
+            -S runtimes
+            -B build-cov
+            -DCMAKE_C_COMPILER=clang-23
+            -DCMAKE_CXX_COMPILER=clang++-23
+            -DCMAKE_BUILD_TYPE=Debug
+            -DCMAKE_C_COMPILER_LAUNCHER=sccache
+            -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
+            -DLLVM_USE_LINKER=lld-23
+            -DLLVM_ENABLE_RUNTIMES=libc
+            -DLLVM_LIBC_FULL_BUILD=ON
+            -DLIBC_ENABLE_COVERAGE=ON
+            -DLIBC_ENABLE_MCDC=ON
+            -DLIBC_TEST_UNIT_TEST_ONLY=ON
+            -DLIBC_TEST_SKIP_DEATH_TESTS=ON
+            -DLIBC_TEST_SKIP_SHARED_TESTS=ON
+          "
+          cmake $CMAKE_FLAGS
+
+          END_TIME=$(date +%s)
+          echo "=== [STAGE 1/4] CMake Configuration Completed in $((END_TIME - START_TIME))s ==="
+
+      - name: Run Full Codebase Unit Tests
+        run: |
+          echo "=== [STAGE 2/4] Running Full Unit Test Suite at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+          START_TIME=$(date +%s)
+
+          export LLVM_PROFILE_FILE="libc_cov_%p.profraw"
+          ninja -k 0 -C build-cov libc-unit-tests || true
+
+          END_TIME=$(date +%s)
+          echo "=== [STAGE 2/4] libc-unit-tests Completed in $((END_TIME - START_TIME))s ==="
+
+      - name: Merge Profiles
+        run: |
+          echo "=== [STAGE 3/4] Merging Raw Profiles at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+          find build-cov -name "libc_cov_*.profraw" > profraw_list.txt
+          NUM_PROFS=$(wc -l < profraw_list.txt || echo 0)
+          echo "[LOG] Discovered $NUM_PROFS raw profile data files."
+          llvm-profdata-23 merge -sparse --input-files=profraw_list.txt -o libc_full.profdata
+          echo "[LOG] Merged full codebase profile into libc_full.profdata."
+
+      - name: Generate Reports and Summary
+        env:
+          COMMIT_SHA: ${{ github.sha }}
+          BRANCH_REF: ${{ github.ref_name }}
+        run: |
+          echo "=== [STAGE 4/4] Generating Full Codebase MC/DC Coverage Reports at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+          EXECUTABLES=($(find build-cov -type f -executable -name "*__build__"))
+          OBJECTS=("${EXECUTABLES[@]:1}")
+          OBJECTS=("${OBJECTS[@]/#/-object=}")
+
+          echo "[LOG] Exporting coverage data across ${#EXECUTABLES[@]} test binaries."
+
+          # 1. Generate JSON export for Full Coverage Analyzer (contains mcdc_records)
+          llvm-cov-23 export -format=text -instr-profile=libc_full.profdata "${EXECUTABLES[0]}" "${OBJECTS[@]}" > coverage.json
+
+          # 2. Generate HTML Coverage Report with directory hierarchy, branch tracking, and MC/DC truth tables
+          llvm-cov-23 show -format=html \
+            -output-dir=coverage_mcdc_html \
+            -instr-profile=libc_full.profdata \
+            "${EXECUTABLES[0]}" "${OBJECTS[@]}" \
+            --show-directory-coverage \
+            --show-branches=count \
+            --show-mcdc \
+            --show-mcdc-summary \
+            --compilation-dir=. \
+            --path-equivalence="$GITHUB_WORKSPACE,." \
+            -ignore-filename-regex=".*(test|utils).*"
+          touch coverage_mcdc_html/.nojekyll
+
+          # 3. Run Codebase Coverage Analyzer
+          PYTHONPATH="libc/utils/coverage" python3 libc/utils/coverage/codebase_coverage.py coverage.json "$COMMIT_SHA" "$BRANCH_REF" >> $GITHUB_STEP_SUMMARY
+          echo "[LOG] Post-commit summary report written to GITHUB_STEP_SUMMARY."
+
+      - name: Deploy MC/DC Coverage Report to GitHub Pages
+        if: github.repository != 'llvm/llvm-project'
+        continue-on-error: true
+        uses: peaceiris/actions-gh-pages at v4
+        with:
+          github_token: ${{ secrets.GITHUB_TOKEN }}
+          publish_dir: ./coverage_mcdc_html
+          destination_dir: mcdc
+          keep_files: true
+          enable_jekyll: false
+          force_orphan: false
+
+
diff --git a/.github/workflows/libc-patch-coverage.yml b/.github/workflows/libc-patch-coverage.yml
new file mode 100644
index 0000000000000..5cd2b723862e1
--- /dev/null
+++ b/.github/workflows/libc-patch-coverage.yml
@@ -0,0 +1,362 @@
+name: Libc Patch Code Coverage
+
+permissions:
+  contents: read
+  pull-requests: write # Required to post/update patch coverage comments
+
+env:
+  FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: 'true'
+
+on:
+  workflow_dispatch:
+  push:
+    branches:
+      - pre-commit-bot
+      - libc-coverage-ci-bots
+      - main
+    paths:
+      - 'libc/src/**'
+      - 'libc/include/**'
+      - 'libc/test/**'
+      - 'libc/CMakeLists.txt'
+      - '.github/workflows/libc-patch-coverage.yml'
+      - '!libc/docs/**'
+      - '!libc/benchmarks/**'
+      - '!libc/fuzzing/**'
+      - '!libc/utils/**'
+      - '!**.md'
+  pull_request:
+    paths:
+      - 'libc/src/**'
+      - 'libc/include/**'
+      - 'libc/test/**'
+      - 'libc/CMakeLists.txt'
+      - '.github/workflows/libc-patch-coverage.yml'
+      - '!libc/docs/**'
+      - '!libc/benchmarks/**'
+      - '!libc/fuzzing/**'
+      - '!libc/utils/**'
+      - '!**.md'
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
+  cancel-in-progress: true
+
+jobs:
+  pre-commit-coverage:
+    timeout-minutes: 60
+    name: libc-pre-commit-coverage
+    runs-on: ubuntu-24.04
+    container:
+      image: ghcr.io/llvm/libc-ubuntu-24.04:latest at sha256:8fee4c9ce5a1fd095686593cd36e032c48a31b6ae575378c82accd1d86a08d59
+      options: >-
+        --privileged
+    defaults:
+      run:
+        shell: bash
+    steps:
+    - name: Checkout Code
+      uses: actions/checkout at v4
+      with:
+        ref: ${{ github.event.pull_request.head.sha || github.sha }}
+        fetch-depth: 2
+        persist-credentials: false
+
+    - name: Setup Compiler Cache (sccache)
+      uses: hendrikmuhs/ccache-action at v1.2.23
+      with:
+        max-size: 1G
+        key: libc_coverage_unified_v2_x86_64
+        variant: sccache
+
+    - name: Configure CMake
+      run: |
+        echo "=== [STAGE 1/4] Starting CMake Configuration at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+        START_TIME=$(date +%s)
+
+        export CMAKE_FLAGS="
+          -G Ninja
+          -S runtimes
+          -B build-cov
+          -DCMAKE_C_COMPILER=clang-23
+          -DCMAKE_CXX_COMPILER=clang++-23
+          -DCMAKE_BUILD_TYPE=Debug
+          -DCMAKE_C_COMPILER_LAUNCHER=sccache
+          -DCMAKE_CXX_COMPILER_LAUNCHER=sccache
+          -DLLVM_USE_LINKER=lld-23
+          -DLLVM_ENABLE_RUNTIMES=libc
+          -DLLVM_LIBC_FULL_BUILD=ON
+          -DLIBC_ENABLE_COVERAGE=ON
+          -DLIBC_TEST_UNIT_TEST_ONLY=ON
+          -DLIBC_TEST_SKIP_DEATH_TESTS=ON
+          -DLIBC_TEST_SKIP_SHARED_TESTS=ON
+        "
+        cmake $CMAKE_FLAGS
+
+        END_TIME=$(date +%s)
+        echo "=== [STAGE 1/4] CMake Configuration Completed in $((END_TIME - START_TIME))s ==="
+
+    - name: Build and Run Targeted Tests
+      env:
+        EVENT_NAME: ${{ github.event_name }}
+        PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
+        PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
+        PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
+        PR_HEAD_REF: ${{ github.event.pull_request.head.ref }}
+        PR_BASE_REPO: ${{ github.event.pull_request.base.repo.full_name }}
+        PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
+        COMMIT_SHA: ${{ github.sha }}
+        BRANCH_REF: ${{ github.ref_name }}
+        REPO_NAME: ${{ github.repository }}
+      run: |
+        echo "=== [STAGE 2/4] Starting Targeted Test Discovery at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+        START_TIME=$(date +%s)
+
+        # Ensure upstream llvm-project remote is configured
+        git remote add upstream https://github.com/llvm/llvm-project.git 2>/dev/null || true
+
+        # 1. Deterministically resolve Base and Head references against upstream llvm-project
+        if [ "$EVENT_NAME" == "pull_request" ]; then
+          BASE_SHA="$PR_BASE_SHA"
+          HEAD_SHA="$PR_HEAD_SHA"
+          BASE_REF="$PR_BASE_REF"
+          HEAD_REF="$PR_HEAD_REF"
+          BASE_REPO="${PR_BASE_REPO:-llvm/llvm-project}"
+          HEAD_REPO="${PR_HEAD_REPO:-$REPO_NAME}"
+          git fetch upstream "$BASE_SHA" --depth=1 2>/dev/null || git fetch origin "$BASE_SHA" --depth=1 2>/dev/null || git fetch origin "$BASE_REF" --depth=1 2>/dev/null || true
+          DIFF_BASE="$BASE_SHA"
+        else
+          # For direct pushes, compare the pushed commit against its parent (HEAD~1)
+          BASE_SHA=$(git rev-parse HEAD~1 2>/dev/null || echo "HEAD~1")
+          HEAD_SHA="$COMMIT_SHA"
+          BASE_REF="main"
+          HEAD_REF="$BRANCH_REF"
+          BASE_REPO="llvm/llvm-project"
+          HEAD_REPO="$REPO_NAME"
+          DIFF_BASE="HEAD~1"
+        fi
+
+        # Persist resolved commit references for all downstream steps
+        echo "DIFF_BASE=$DIFF_BASE" >> $GITHUB_ENV
+        echo "BASE_SHA=$BASE_SHA" >> $GITHUB_ENV
+        echo "HEAD_SHA=$HEAD_SHA" >> $GITHUB_ENV
+        echo "BASE_REF=$BASE_REF" >> $GITHUB_ENV
+        echo "HEAD_REF=$HEAD_REF" >> $GITHUB_ENV
+        echo "BASE_REPO=$BASE_REPO" >> $GITHUB_ENV
+        echo "HEAD_REPO=$HEAD_REPO" >> $GITHUB_ENV
+
+        echo "[LOG] Resolved Base: ${BASE_REF} (${BASE_SHA:0:7}) in ${BASE_REPO}"
+        echo "[LOG] Resolved Head: ${HEAD_REF} (${HEAD_SHA:0:7}) in ${HEAD_REPO}"
+
+        MODIFIED_FILES=$(git diff --name-only "$DIFF_BASE" HEAD -- libc/src/ || true)
+        echo "[LOG] Modified files in libc/src/:"
+        echo "$MODIFIED_FILES"
+
+        if [ -z "$MODIFIED_FILES" ]; then
+          echo "[LOG] No source files modified in libc/src/. Exiting successfully."
+          echo "TARGETS=" >> $GITHUB_ENV
+
+          echo "## LLVM-libc Patch Coverage Report" > coverage_report.md
+          echo "" >> coverage_report.md
+          echo "- **Base Branch:** [\`${BASE_REF}\` (${BASE_SHA:0:7})](https://github.com/${BASE_REPO}/commit/${BASE_SHA})" >> coverage_report.md
+          echo "- **Head Commit:** [\`${HEAD_REF}\` (${HEAD_SHA:0:7})](https://github.com/${HEAD_REPO}/commit/${HEAD_SHA})" >> coverage_report.md
+          echo "---" >> coverage_report.md
+          echo "" >> coverage_report.md
+          echo "**Coverage Validated**" >> coverage_report.md
+          echo "No \`.cpp\` source files in \`libc/src/\` were modified in this patch." >> coverage_report.md
+
+          cat coverage_report.md >> $GITHUB_STEP_SUMMARY
+          exit 0
+        fi
+
+        # Get all valid ninja targets
+        ninja -C build-cov -t targets > all_targets.txt
+
+        TARGETS=""
+
+        for FILE in $MODIFIED_FILES; do
+          # Skip core support files from direct target mapping (tested transitively)
+          if [[ "$FILE" == *"__support/"* ]]; then
+            echo "[LOG] -> Support file ($FILE) will be tested transitively."
+            continue
+          fi
+
+          if [[ "$FILE" =~ ^libc/src/([^/]+)/(.*/)?([^/]+)\.cpp$ ]]; then
+            DIR="${BASH_REMATCH[1]}"
+            FUNC="${BASH_REMATCH[3]}"
+            ALL_MATCHES=$(grep -oE "^libc\.test\.src\.${DIR}\.([a-zA-Z0-9_]+\.)*${FUNC}_test\.__unit__" all_targets.txt || true)
+            FOUND_TARGET=$(echo "$ALL_MATCHES" | head -n 1 | tr -d '\r\n ' || true)
+            if [ -n "$FOUND_TARGET" ]; then
+              echo "[LOG] -> Matched $FILE -> $FOUND_TARGET"
+              TARGETS="$TARGETS $FOUND_TARGET"
+            else
+              echo "[LOG] -> Notice: No direct unit test target found for $FILE."
+            fi
+          fi
+        done
+
+        # Remove duplicate targets
+        TARGETS=$(echo "$TARGETS" | xargs -n1 | sort -u | xargs || true)
+        echo "[LOG] Executing Ninja targets: $TARGETS"
+
+        if [ -n "$TARGETS" ]; then
+          export LLVM_PROFILE_FILE="libc_cov_%p.profraw"
+          ninja -C build-cov $TARGETS
+          echo "TARGETS=$TARGETS" >> $GITHUB_ENV
+        else
+          echo "[LOG] No standalone unit test targets to run."
+          echo "TARGETS=" >> $GITHUB_ENV
+
+          echo "## LLVM-libc Patch Coverage Report" > coverage_report.md
+          echo "" >> coverage_report.md
+          echo "- **Base Branch:** [\`${BASE_REF}\` (${BASE_SHA:0:7})](https://github.com/${BASE_REPO}/commit/${BASE_SHA})" >> coverage_report.md
+          echo "- **Head Commit:** [\`${HEAD_REF}\` (${HEAD_SHA:0:7})](https://github.com/${HEAD_REPO}/commit/${HEAD_SHA})" >> coverage_report.md
+          echo "---" >> coverage_report.md
+          echo "" >> coverage_report.md
+          echo "**Coverage Validated**" >> coverage_report.md
+          echo "Modified files do not have standalone unit test targets." >> coverage_report.md
+
+          cat coverage_report.md >> $GITHUB_STEP_SUMMARY
+        fi
+
+        END_TIME=$(date +%s)
+        echo "=== [STAGE 2/4] Targeted Tests Completed in $((END_TIME - START_TIME))s ==="
+
+    - name: Merge Profiles
+      if: env.TARGETS != ''
+      run: |
+        echo "=== [STAGE 3/4] Merging Raw Profiles at $(date -u '+%Y-%m-%d %H:%M:%S UTC') ==="
+        find build-cov -name "libc_cov_*.profraw" > profraw_list.txt
+        NUM_PROFS=$(wc -l < profraw_li...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/219165


More information about the libc-commits mailing list