-
Notifications
You must be signed in to change notification settings - Fork 61
246 lines (228 loc) · 10.9 KB
/
Copy pathroot.yml
File metadata and controls
246 lines (228 loc) · 10.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
name: ROOT
# Build ROOT (root-project/root master) against the CppInterOp tree
# carried by the PR, by overwriting `interpreter/CppInterOp` in ROOT
# with our checkout. Any breaking change CppInterOp introduces that
# ROOT relies on shows up here as a configure or compile error.
#
# The job pins to the same axes as `main.yml`'s
# ubu24-x86-gcc14-cling-llvm20-cppyy row so the LLVM/Cling cache key
# resolves to the same string and the artifact is shared.
on:
pull_request:
branches: [main]
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
jobs:
build-root:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- { name: ubu24-x86-gcc14-cling-llvm20-root, os: ubuntu-24.04, compiler: gcc-14, clang-runtime: '20' }
steps:
- name: Checkout CppInterOp PR
uses: actions/checkout@v6
with:
path: cppinterop
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: Setup default Build Type
uses: ./cppinterop/.github/actions/Miscellaneous/Select_Default_Build_Type
- name: Setup compiler
uses: ./cppinterop/.github/actions/Miscellaneous/Setup_Compiler
with:
compiler: ${{ matrix.compiler }}
- name: Install dependencies
uses: ./cppinterop/.github/actions/Miscellaneous/Install_Dependencies
# ROOT consumes the same llvm-root tree the cling-on-top rows in
# main.yml use. The setup-llvm action pulls llvm-root with the
# ROOT-llvm20 flavor (cling's patches plus ROOT's extra clang
# patches) and builds cling on top. ROOT's bundled cling sources
# in the substituted CppInterOp tree below pick this install up
# via CMAKE_PREFIX_PATH.
- name: Setup LLVM 20 [cling, ROOT-llvm20]
uses: compiler-research/ci-workflows/actions/setup-llvm@main
with:
version: '20'
os: ${{ matrix.os }}
arch: x86_64
flavor: cling
flavor-version: 'ROOT-llvm20'
- name: Verify cached LLVM/Clang layout
shell: bash
run: |
# Fail loud on recipe-trim drift (missing cmake configs,
# multiple lib/clang/<version> dirs, stripped clang headers)
# so the error surfaces here rather than as an opaque ROOT
# cmake/link failure several steps later.
LLVM="$(dirname "$(dirname "$(dirname "$LLVM_DIR")")")"
fail=0
for f in \
"$LLVM/lib/cmake/llvm/LLVMConfig.cmake" \
"$LLVM/lib/cmake/clang/ClangConfig.cmake" \
"$LLVM/lib/libclangInterpreter.a" \
"$LLVM/include/clang/Basic/Module.h"; do
if [[ ! -f "$f" ]]; then
echo "::error::missing $f"
fail=1
else
echo "ok: $f"
fi
done
if [[ ! -d "$LLVM/lib/clang" ]]; then
echo "::error::missing $LLVM/lib/clang"
fail=1
else
versions=$(ls "$LLVM/lib/clang" 2>/dev/null | tr '\n' ' ')
echo "lib/clang/ entries: ${versions:-<empty>}"
# ROOT requires exactly one entry in this directory.
count=$(ls "$LLVM/lib/clang" 2>/dev/null | wc -l)
if [[ "$count" -ne 1 ]]; then
echo "::error::expected exactly 1 entry under $LLVM/lib/clang, found $count"
fail=1
fi
fi
exit $fail
- name: Install ROOT system dependencies
shell: bash
run: |
# Per https://root.cern/install/build_from_source/. Even with
# `-Dminimal=ON`, ROOT still requires LibLZMA, libssl, X11 dev
# headers, etc. Install the documented Ubuntu set rather than
# opting in to ROOT's `-Dbuiltin_*` fallbacks (slower build).
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
dpkg-dev binutils \
libx11-dev libxpm-dev libxft-dev libxext-dev \
libssl-dev liblzma-dev libpcre3-dev libpcre2-dev \
libxxhash-dev libzstd-dev liblz4-dev libtbb-dev libxml2-dev \
nlohmann-json3-dev \
libgtest-dev libgmock-dev
# The ubuntu-24.04 runner image ships llvm-17 dev packages,
# whose `/usr/lib/llvm-17/lib/cmake/llvm` is found by ROOT's
# `find_package(LLVM)` before our `-DLLVM_DIR` hint takes
# effect (ROOT's interpreter subtree re-invokes find_package
# in nested scopes). Purge them so only our cached LLVM 20
# remains visible.
sudo apt-get purge -y 'llvm-17*' 'clang-17*' 'libclang-17*' 'libllvm17*' || true
sudo apt-get autoremove -y
# CCACHE_DIR is pinned inside $github.workspace so the cache state
# survives container teardowns under nektos/act (which bind-mounts
# the workspace). On github-hosted runners the workspace is wiped
# at job end so ccache stays cold; this is a local-iteration
# speedup, not a CI optimization.
- name: Setup ccache
shell: bash
run: |
mkdir -p "${{ github.workspace }}/.ccache"
echo "CCACHE_DIR=${{ github.workspace }}/.ccache" >> "$GITHUB_ENV"
ccache --max-size=5G
- name: Substitute the PR's CppInterOp into ROOT
shell: bash
run: |
rm -rf root
git clone --depth=1 --branch master https://github.com/root-project/root.git
# ROOT bundles a copy of CppInterOp under interpreter/CppInterOp.
# Replace it with the PR's tree so the integration build exercises
# this PR's headers, sources, and CMake glue.
rm -rf root/interpreter/CppInterOp
cp -a cppinterop root/interpreter/CppInterOp
# Strip the nested `.git` so ROOT's CMake doesn't get confused by
# a sub-repository inside its own source tree.
rm -rf root/interpreter/CppInterOp/.git
# ROOT's interpreter/CMakeLists.txt FORCE-overrides
# CPPINTEROP_ENABLE_TESTING from its own `-Dtesting` flag, defeating
# the -DCPPINTEROP_ENABLE_TESTING=ON we pass in Configure ROOT below
# and silently skipping the unittests subdir (no `check-cppinterop`
# target). Drop FORCE so a user-set cache value wins, while the
# ROOT-default initialization is preserved for non-CI builds.
sed -i '/CPPINTEROP_ENABLE_TESTING.*Enable gtest in CppInterOp/s/ FORCE)/)/' \
root/interpreter/CMakeLists.txt
# ROOT's interpreter/CMakeLists.txt hardcodes the list of headers
# it stages into ${CMAKE_BINARY_DIR}/etc/cppinterop/CppInterOp/.
# That list (search "set(cppinterop_src_files") names only the
# original three public headers and three generated .inc files.
# CppInterOp.h now also #includes <CppInterOp/Box.h>; without
# Box.h next to the staged CppInterOp.h, metacling fails to
# compile TCling.cxx with "CppInterOp/Box.h: No such file or
# directory". Inject the missing header so the staged set is
# complete -- the upstream fix lives in ROOT and is tracked
# there; this is a CI-only shim until that lands.
sed -i '\|CppInterOp/CppInterOp\.h$|a\ ${CMAKE_CURRENT_SOURCE_DIR}/CppInterOp/include/CppInterOp/Box.h' \
root/interpreter/CMakeLists.txt
- name: Configure ROOT
shell: bash
run: |
rm -rf root-build
mkdir root-build
cd root-build
# ROOT uses our cached external LLVM and Clang (builtin_llvm /
# builtin_clang off) but rebuilds cling from its own bundled
# sources under interpreter/cling -- the bundled sources are
# what ROOT's own version of CppInterOp is wired against, so
# letting ROOT do that rebuild keeps the integration honest.
# `-DLLVM_DIR` would be wiped by `interpreter/CMakeLists.txt:63`
# (`set(LLVM_DIR "${CMAKE_CURRENT_BINARY_DIR}/llvm-project/llvm")`)
# before ROOT's `find_package(LLVM REQUIRED CONFIG)` runs, so we
# don't pass it. Resolution happens via CMAKE_PREFIX_PATH instead.
# `fail-on-missing=ON` mirrors the nixpkgs ROOT recipe so any
# silently-disabled feature surfaces as a configure-time error.
# `-DCLANG_INSTALL_PREFIX` points at the recipe's install root
# so ROOT's `core/clingutils/CMakeLists.txt` resolves
# `${CLANG_INSTALL_PREFIX}/lib/clang` to the recipe-installed
# clang (rather than globbing `/usr/lib/clang/*`).
# CppInterOp's `.td`-driven dispatch emits `CppInterOpDecl.inc` etc.
# via cppinterop-tblgen into `${CMAKE_CURRENT_BINARY_DIR}/include/
# CppInterOp/` (CppInterOp's own subtree). ROOT master doesn't yet
# know to put that on MetaCling's compile rules, so
# `TClingCallFunc.h`'s `#include "CppInterOp/CppInterOpDecl.inc"`
# fails without help. Inject the path globally via `CMAKE_CXX_FLAGS`
# until ROOT lands the companion etc/cppinterop staging change.
CPPINTEROP_GEN_INC="$PWD/interpreter/CppInterOp/include"
cmake -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-Dminimal=ON \
-Dtesting=OFF \
-Dtestsupport=ON \
-Dbuiltin_gtest=OFF \
-DCPPINTEROP_ENABLE_TESTING=ON \
-Dfail-on-missing=ON \
-Dbuiltin_llvm=OFF \
-Dbuiltin_clang=OFF \
-DCMAKE_PREFIX_PATH="$(dirname "$(dirname "$(dirname "$LLVM_DIR")")")" \
-DClang_DIR="$Clang_DIR" \
-DCLANG_INSTALL_PREFIX="$(dirname "$(dirname "$(dirname "$LLVM_DIR")")")" \
-DCMAKE_CXX_FLAGS="-I${CPPINTEROP_GEN_INC}" \
../root
- name: Build ROOT
shell: bash
run: |
# ROOT's `core/clingutils` target is configured against LLVM's
# public include dirs but doesn't propagate `CLANG_INCLUDE_DIRS`
# to its compile rules, so `TClingUtils.h`'s
# `#include "clang/Basic/Module.h"` resolves only via
# `CPLUS_INCLUDE_PATH` -- the same way main.yml's cling rows
# resolve clang headers in `Build_and_Test_CppInterOp/action.yml`.
# Mirror that env here so `RStl.cxx` and friends find their
# clang/cling headers from the recipe's install tree.
# ROOT-specific: see CPLUS_INCLUDE_PATH comment above.
export CPLUS_INCLUDE_PATH="$(dirname "$(dirname "$(dirname "$LLVM_DIR")")")/include"
cmake --build root-build --parallel ${{ env.ncpus }}
# ROOT's top-level enable_testing() is gated on -Dtesting=ON, so a
# bare `ctest` from root-build can't see CppInterOp's subdir tests.
# The check-cppinterop custom target (CppInterOp's
# unittests/CMakeLists.txt:106) calls ctest with WORKING_DIRECTORY
# set to the unittests binary dir, where the CTestTestfile.cmake
# actually lives.
- name: Run CppInterOp unittests
shell: bash
run: |
cmake --build root-build --target check-cppinterop --parallel ${{ env.ncpus }}