Skip to content

Commit e4226dc

Browse files
committed
ci: Test with LLVM downloaded from Rust CI, test static linking
We are planning to use libLLVM from Rust CI to produce static binaries. This change makes sure that tests work with Rust's libLLVM artifacts and libLLVM linked statically (from any source). Rust CI ships only one flavor of libLLVM, shared or static, per target. Linux GNU targets come with shared ones. Apple and Linux musl targets come with dynamic ones. To save disk space, run `cargo hack --feature-powerset` only when shared libraries are used. Otherwise, run cargo with a single feature set.
1 parent c83034f commit e4226dc

File tree

1 file changed

+126
-24
lines changed

1 file changed

+126
-24
lines changed

.github/workflows/ci.yml

Lines changed: 126 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,32 @@ jobs:
6565
llvm: 21
6666
exclude-features: llvm-20,rust-llvm-20
6767
platform:
68+
# Rust CI ships only one flavor of libLLVM, dynamic or static, per
69+
# target. Linux GNU targets come with dynamic ones. Apple and Linux
70+
# musl targets come with static ones.
6871
- os: macos-latest
72+
static-target: aarch64-apple-darwin
73+
# Rust does not provide a dynamic libLLVM library on macOS,
74+
# therefore we exclude `default` and `rust-llvm-*`.
75+
# macOS does not provide static libc++ and zlib and the ones
76+
# provided by homebrew might be ABI-incompatible, therefore we
77+
# exclude `llvm-deps-link-static`.
78+
exclude-features: default,llvm-deps-link-static,rust-llvm-19,rust-llvm-20,rust-llvm-21
6979
- os: macos-15-intel
80+
static-target: x86_64-apple-darwin
81+
exclude-features: default,llvm-deps-link-static,rust-llvm-19,rust-llvm-20,rust-llvm-21
7082
- os: ubuntu-22.04
83+
dynamic-target: x86_64-unknown-linux-gnu
84+
static-target: x86_64-unknown-linux-musl
85+
# Link dependencies like libc++, zlib, zstd statically on Linux.
86+
llvm-features-static: llvm-deps-link-static
7187
- os: ubuntu-22.04-arm
88+
dynamic-target: aarch64-unknown-linux-gnu
89+
static-target: aarch64-unknown-linux-musl
90+
llvm-features-static: llvm-deps-link-static
7291
llvm-from:
7392
- packages
93+
- rust-ci
7494
include:
7595
# Currently we build LLVM from source only for Linux x86_64.
7696
- toolchain:
@@ -85,8 +105,15 @@ jobs:
85105

86106
env:
87107
RUST_BACKTRACE: full
88-
LLVM_FEATURES: llvm-${{ matrix.toolchain.llvm }}
89-
LLVM_EXCLUDE_FEATURES: llvm-deps-link-static,llvm-link-static,no-llvm-linking
108+
# Features that have to be included for dynamic linking.
109+
LLVM_FEATURES_DYNAMIC: llvm-${{ matrix.toolchain.llvm }}
110+
# Features that have to be included for static linking.
111+
LLVM_FEATURES_STATIC: llvm-${{ matrix.toolchain.llvm }},llvm-link-static
112+
# Features that have to be excluded when running `cargo hack --feature-powerset`
113+
# and intending to link dynamically.
114+
LLVM_EXCLUDE_FEATURES_DYNAMIC: llvm-deps-link-static,llvm-link-static,no-llvm-linking
115+
RUSTC_LLVM_INSTALL_DIR_DYNAMIC: /tmp/rustc-llvm-dynamic
116+
RUSTC_LLVM_INSTALL_DIR_STATIC: /tmp/rustc-llvm-static
90117

91118
steps:
92119
- uses: actions/checkout@v6
@@ -118,16 +145,19 @@ jobs:
118145
set -euxo pipefail
119146
echo /usr/lib/llvm-15/bin >> $GITHUB_PATH
120147
121-
- name: Install LLVM (Linux, packages)
122-
if: matrix.llvm-from == 'packages' && runner.os == 'Linux'
148+
- name: Add LLVM APT repository
149+
if: runner.os == 'Linux'
123150
run: |
124151
set -euxo pipefail
125152
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
126153
echo -e deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.toolchain.llvm }} main | sudo tee /etc/apt/sources.list.d/llvm.list
127-
128154
sudo apt update
129-
sudo apt -y install llvm-${{ matrix.llvm-version }}-dev
130-
echo /usr/lib/llvm-${{ matrix.llvm-version }}/bin >> $GITHUB_PATH
155+
156+
- name: Install LLVM (Linux, packages)
157+
if: matrix.llvm-from == 'packages' && runner.os == 'Linux'
158+
run: |
159+
set -euxo pipefail
160+
sudo apt -y install llvm-${{ matrix.toolchain.llvm }}-dev
131161
echo /usr/lib/llvm-${{ matrix.toolchain.llvm }}/bin >> $GITHUB_PATH
132162
133163
- name: Install LLVM (macOS, packages)
@@ -138,7 +168,35 @@ jobs:
138168
echo $(brew --prefix llvm@${{ matrix.toolchain.llvm }})/bin >> $GITHUB_PATH
139169
echo "DYLD_LIBRARY_PATH=$(brew --prefix llvm@${{ matrix.toolchain.llvm }})/lib" >> $GITHUB_ENV
140170
141-
- name: Restore LLVM
171+
- name: Install LLVM from Rust CI
172+
if: matrix.llvm-from == 'rust-ci'
173+
run: |
174+
set -euxo pipefail
175+
mkdir -p $RUSTC_LLVM_INSTALL_DIR
176+
rustc_sha=$(cargo xtask rustc-llvm-commit --github-token "${{ secrets.GITHUB_TOKEN }}")
177+
download_llvm() {
178+
local target=$1
179+
local install_dir=$2
180+
wget -q -O - "https://ci-artifacts.rust-lang.org/rustc-builds/$rustc_sha/rust-dev-nightly-$target.tar.xz" | \
181+
tar -xJ --strip-components 2 -C $install_dir
182+
}
183+
if [[ -n "${{ matrix.platform['dynamic-target'] }}" ]]; then
184+
download_llvm "${{ matrix.platform['dynamic-target'] }}"
185+
echo "LD_LIBRARY_PATH=${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/lib" >> $GITHUB_ENV
186+
# Add the dynamic libraries to `PATH` by default. All steps expected
187+
# to link statically should overwrite `PATH` on their own.
188+
echo "${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/bin" >> $GITHUB_PATH
189+
fi
190+
if [[ -n "${{ matrix.platform['static-target'] }}" ]]; then
191+
download_llvm "${{ matrix.platform['static-target'] }}"
192+
if [[ "${{ runner.os }}" == "Linux" ]]; then
193+
# `FileCheck` binary shipped in musl tarballs is linked dynamically
194+
# to musl, we can't execute it on Ubuntu.
195+
rm -f "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin/FileCheck"
196+
fi
197+
fi
198+
199+
- name: Restore LLVM from GitHub Actions
142200
if: matrix.llvm-from == 'source'
143201
uses: actions/cache/restore@v4
144202
with:
@@ -165,17 +223,17 @@ jobs:
165223
166224
- uses: taiki-e/install-action@cargo-hack
167225

168-
- name: Check
226+
- name: Check (dynamic linking, feature powerset)
169227
run: |
170-
cargo hack check --feature-powerset \
171-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
172-
--features ${{ env.LLVM_FEATURES }}
228+
cargo hack check --feature-powerset --exclude-features \
229+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }},${{ matrix.platform.exclude-features }} \
230+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
173231
174-
- name: Build
232+
- name: Build (dynamic linking, feature powerset)
175233
run: |
176-
cargo hack build --feature-powerset \
177-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
178-
--features ${{ env.LLVM_FEATURES }}
234+
cargo hack build --feature-powerset --exclude-features \
235+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }},${{ matrix.platform.exclude-features }} \
236+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
179237
180238
# Toolchains provided by rustup include standard library artifacts
181239
# only for Tier 1 targets, which do not include BPF targets.
@@ -185,11 +243,12 @@ jobs:
185243
# running compiler tests.
186244
#
187245
# `RUSTC_BOOTSTRAP` is needed to use `rustc-build-sysroot` on stable Rust.
188-
- name: Test (sysroot built on demand)
246+
- name: Test (sysroot built on demand, dynamic linking)
189247
run: |
190248
RUSTC_BOOTSTRAP=1 cargo hack test --feature-powerset \
191-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
192-
--features ${{ env.LLVM_FEATURES }}
249+
--exclude-features \
250+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }},${{ matrix.platform.exclude-features }} \
251+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
193252
194253
# To make things easier for package maintainers, the step of building a
195254
# custom sysroot can be skipped by setting the `BPFEL_SYSROOT_DIR`
@@ -200,7 +259,7 @@ jobs:
200259
#
201260
# `RUSTC_BOOTSTRAP` is needed to make `xtask build-std` work on stable
202261
# Rust.
203-
- name: Test (prebuilt BPF standard library)
262+
- name: Build BPF standard library
204263
run: |
205264
set -euxo pipefail
206265
@@ -211,9 +270,12 @@ jobs:
211270
--sysroot-dir "$BPFEL_SYSROOT_DIR" \
212271
--target bpfel-unknown-none
213272
214-
BPFEL_SYSROOT_DIR="$BPFEL_SYSROOT_DIR" cargo hack test --feature-powerset \
215-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
216-
--features ${{ env.LLVM_FEATURES }}
273+
- name: Test (prebuilt BPF standard libary, dynamic linking)
274+
run: |
275+
BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \
276+
cargo hack test --feature-powerset --exclude-features \
277+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }},${{ matrix.platform.exclude-features }} \
278+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
217279
218280
- uses: actions/checkout@v6
219281
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
@@ -224,13 +286,53 @@ jobs:
224286

225287
- name: Install
226288
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
227-
run: cargo install --path . --no-default-features --features ${{ env.LLVM_FEATURES }}
289+
run: |
290+
cargo install --path . --no-default-features --features \
291+
${{ env.LLVM_FEATURES_DYNAMIC }}
228292
229293
- name: Run aya integration tests
230294
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
231295
working-directory: aya
232296
run: cargo xtask integration-test local
233297

298+
- name: Prepare for static linking (macOS)
299+
if: runner.os == 'macOS'
300+
# macOS does not provide any static libraries. Homebrew does provide
301+
# them, but in custom paths that the system-wide clang is not aware of.
302+
# Point build.rs to them by setting environment variables.
303+
run: |
304+
echo "CXXSTDLIB_PATH=$(brew --prefix llvm@17)/lib/c++" >> $GITHUB_ENV
305+
echo "ZLIB_PATH=$(brew --prefix zlib)/lib" >> $GITHUB_ENV
306+
307+
- name: Prepare for static linking (LLVM from Rust CI)
308+
if: matrix.llvm-from == 'rust-ci'
309+
run: |
310+
echo "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin" >> $GITHUB_PATH
311+
312+
- name: Check (static linking, single feature set)
313+
# Static linking in combination with `cargo hack --feature-powerset`
314+
# (multiple builds) increases the disk usage massively. Therefore we
315+
# perform all static builds with only one fixed feature set.
316+
run: |
317+
cargo check --no-default-features --features \
318+
${{ env.LLVM_FEATURES_STATIC }},${{ matrix.platform.llvm-features-static }}
319+
320+
- name: Build (static linking, single feature set)
321+
run: |
322+
cargo build --no-default-features --features \
323+
${{ env.LLVM_FEATURES_STATIC }},${{ matrix.platform.llvm-features-static }}
324+
325+
- name: Test (sysroot built on demand, static linking)
326+
run: |
327+
RUSTC_BOOTSTRAP=1 cargo test --no-default-features --features \
328+
${{ env.LLVM_FEATURES_STATIC }},${{ matrix.platform.llvm-features-static }}
329+
330+
- name: Test (prebuilt BPF standard library, static linking)
331+
run: |
332+
BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \
333+
cargo test --no-default-features --features \
334+
${{ env.LLVM_FEATURES_STATIC }},${{ matrix.platform.llvm-features-static }}
335+
234336
- name: Report disk usage
235337
if: ${{ always() }}
236338
uses: ./.github/actions/report-disk-usage

0 commit comments

Comments
 (0)