Skip to content

[ci] Build ROOT against the CppInterOp PR.#932

Open
vgvassilev wants to merge 1 commit intocompiler-research:mainfrom
vgvassilev:ci-root-integration
Open

[ci] Build ROOT against the CppInterOp PR.#932
vgvassilev wants to merge 1 commit intocompiler-research:mainfrom
vgvassilev:ci-root-integration

Conversation

@vgvassilev
Copy link
Copy Markdown
Contributor

ROOT (root-project/root) carries an in-tree copy of CppInterOp under interpreter/CppInterOp that it builds and links Cling against. Breaking changes that diverge from what ROOT relies on currently surface only after merge, when the CppInterOp bump through ROOT's vendored copy lands and the ROOT CI breaks. Add a PR-time integration job that overrides ROOT's bundled CppInterOp with the PR's tree and builds ROOT minimally, so the breakage is visible on the PR that introduces it.

The job's matrix row pins the same axes as
ubu24-x86-gcc14-cling-llvm20-cppyy in main.yml: same OS, same host compiler, same clang-runtime, same root-llvm-tag. The cache key expression is copied verbatim from main.yml's restore step, so on a normal run the job free-rides the LLVM/Cling artifact the cppyy cling row populated and skips the ~30 minute LLVM build. On a cache miss it falls through to the existing Build_LLVM action; a workspace-root symlink keeps the patches at the path Build_LLVM and hashFiles both expect.

ROOT itself is built with -Dminimal=ON -Dtesting=OFF and uses the cached external LLVM/Clang (builtin_llvm and builtin_clang both Off). Cling is rebuilt from ROOT's bundled
interpreter/cling sources -- those sources are what ROOT's own version of CppInterOp is wired against, so letting ROOT do that rebuild keeps the integration honest. Triggers are pull_request and workflow_dispatch; no schedule or push, no
continue-on-error -- a failure here is the desired signal.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 26, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.87%. Comparing base (fb595ac) to head (2e51da5).

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##             main     #932   +/-   ##
=======================================
  Coverage   80.87%   80.87%           
=======================================
  Files          15       15           
  Lines        4707     4707           
=======================================
  Hits         3807     3807           
  Misses        900      900           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@vgvassilev vgvassilev force-pushed the ci-root-integration branch 2 times, most recently from 4247139 to 2e51da5 Compare April 26, 2026 06:59
ROOT (root-project/root) carries an in-tree copy of CppInterOp
under `interpreter/CppInterOp` that it builds and links Cling
against. Breaking changes that diverge from what ROOT relies on
currently surface only after merge, when the next CppInterOp bump
through ROOT's vendored copy lands and the ROOT CI breaks. Add a
PR-time integration job that overrides ROOT's bundled CppInterOp
with the PR's tree and builds ROOT minimally, so the breakage is
visible on the PR that introduces it.

Read-only against the LLVM/Cling cache. The matrix row pins the
same axes as `ubu24-x86-gcc14-cling-llvm20-cppyy` in main.yml
(same OS, host compiler, clang-runtime, root-llvm-tag) and copies
that workflow's cache key verbatim, so a normal run free-rides
the LLVM/Cling artifact main.yml's cppyy cling row populates --
skipping the ~30-minute Build_LLVM. The job deliberately does
*not* build or save the cache: a missing entry fails the job
explicitly with a `::error::` pointing at main.yml's row as the
populator. Owning the build in one place keeps the contract
explicit and avoids two parallel ~30-minute builds racing to
populate the same key.

Wiring ROOT to consume our cached LLVM 20 needs three knobs.
`interpreter/CMakeLists.txt:63` clobbers any incoming `-DLLVM_DIR`
with an empty path before `find_package(LLVM REQUIRED CONFIG)`,
so steering find_package goes through `-DCMAKE_PREFIX_PATH`
instead. The ubuntu-24.04 runner image ships `llvm-17-dev`, whose
`/usr/lib/llvm-17/lib/cmake/llvm` would win the standard search
ahead of CMAKE_PREFIX_PATH; we apt-purge `llvm-17* clang-17*
libclang-17* libllvm17*` so only our cached LLVM 20 is reachable.
Finally `core/clingutils/CMakeLists.txt:87` references
`${CLANG_INSTALL_PREFIX}/lib/clang`, but the build-tree
`ClangConfig.cmake` we cache leaves `CLANG_INSTALL_PREFIX`
undefined (`find_prefix_from_config` only emits its prefix-walking
snippet into the install-tree variant). With the variable empty
the glob resolves to `/lib/clang -> /usr/lib/clang` and picks up
the runner's residual system clangs; pass
`-DCLANG_INSTALL_PREFIX=$GITHUB_WORKSPACE/llvm-project/build` so
the glob hits the lone `lib/clang/20` from our build.

A pre-configure verify step asserts `lib/cmake/llvm/LLVMConfig.cmake`,
`lib/cmake/clang/ClangConfig.cmake`, `lib/libclangInterpreter.a`,
and exactly one entry under `lib/clang/`. If the cache layout ever
drifts (eviction, key-formula divergence, or `Build_LLVM` trim
regression), the step fails fast with `::error::` annotations
instead of cascading into an opaque ROOT cmake or link failure
several steps later.

ROOT itself is built with `-Dminimal=ON -Dtesting=OFF
-Dfail-on-missing=ON` (the latter mirrors the nixpkgs ROOT
recipe -- silently disabled features become configure-time
errors). System dependencies (LibLZMA, libssl, X11 headers,
nlohmann-json, etc.) follow the documented Ubuntu set from
https://root.cern/install/build_from_source/. `nlohmann-json3-dev`
is required even with `minimal=ON` because it's the link interface
of `ROOT::ROOTEve`. Cling is rebuilt from ROOT's bundled
`interpreter/cling` sources; those sources are what ROOT's own
version of CppInterOp is wired against, so letting ROOT do that
rebuild keeps the integration honest. Triggers are `pull_request`
and `workflow_dispatch`; no schedule or push, no
`continue-on-error` -- a failure here is the desired signal.

Cache-side hygiene riding along (touches Build_LLVM and friends
because the ROOT job depends on the new cache shape):

  - Add `clangInterpreter` to the cling-case ninja line. ROOT's
    bundled `interpreter/cling/lib/Interpreter/CMakeLists.txt:14`
    lists `clangInterpreter` in its `LIBS`, but cling v1.3 (the
    version we cache against) does not. Without it, ROOT's link
    fails with `libclangInterpreter.a ... missing and no known
    rule to make it` and the trim-removed top-level
    `llvm/CMakeLists.txt` makes it impossible to ninja from the
    cache after the fact -- it must be built when the cache is
    populated.
  - Drop `! -name "lib"` from the source-tree trim in `Build_LLVM`
    and `Build_LLVM_WASM`. The source `lib/` dirs of
    `llvm-project/{llvm,clang}` hold `.cpp` already linked into
    `build/lib/*.a`; nothing on the consumer include path
    references them. Saves ~50-100 MB compressed per cache row.
  - Pass `-DLLVM_INCLUDE_BENCHMARKS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF`
    to the cling cmake call. Notably *not*
    `-DLLVM_INCLUDE_TESTS=OFF`: cling's
    `CMakeLists.txt:437-452` builds its runtime
    `CLING_INCLUDE_PATHS` (used at runtime to find
    `cling/Interpreter/RuntimeUniverse.h`) inside an
    `if(CLING_INCLUDE_TESTS)` block, and that variable defaults
    to `${LLVM_INCLUDE_TESTS}`. Disabling it leaves the path list
    empty and cling can't bootstrap.
  - Fix `Build_LLVM_WASM`'s source-tree `find` substitution that
    was missing its closing `)` since the action was last
    refactored, leaving the cling-on-WASM trim semantically
    broken.
  - Clean up CLING_HASH and LLVM_HASH in `Save_PR_Info` so the
    cache key reads `cling-v1.3-c2beed49` instead of leaking
    `git ls-remote` internals as `<40-char-sha>-refs/tags/v1.3`.
  - Quote `cling: 'On'` on every matrix row. YAML 1.1 parsers
    (notably nektos/act) interpret bare `On` as boolean true,
    which short-circuits Save_PR_Info's CLING_HASH computation
    and pushes the row to `CLING_HASH=Repl`. Real GHA was
    unaffected; quoting eliminates the act-only divergence.

Two ergonomic fixes ride along. `Install_Dependencies` now passes
`-y` to every apt-get call so it works on catthehacker/nektos-act
images that lack the GHA `Assume-Yes` config. The workflow's
display name is `ROOT` (rather than `ROOT integration`) so the PR
check column is short and matches what the project is actually
called.
@vgvassilev vgvassilev force-pushed the ci-root-integration branch from 2e51da5 to b64631f Compare April 26, 2026 09:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant