Skip to content

Commit 92d78b0

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 5efbab0 commit 92d78b0

File tree

1 file changed

+143
-24
lines changed

1 file changed

+143
-24
lines changed

.github/workflows/ci.yml

Lines changed: 143 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,39 @@ 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_DYNAMIC $RUSTC_LLVM_INSTALL_DIR_STATIC
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 \
185+
"${{ matrix.platform['dynamic-target'] }}" \
186+
${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}
187+
echo "LD_LIBRARY_PATH=${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/lib" >> $GITHUB_ENV
188+
# We start with steps that use dynamic linking. Add llvm-config
189+
# associated with dynamic target to `PATH`.
190+
echo "${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/bin" >> $GITHUB_PATH
191+
fi
192+
if [[ -n "${{ matrix.platform['static-target'] }}" ]]; then
193+
download_llvm \
194+
"${{ matrix.platform['static-target'] }}" \
195+
${RUSTC_LLVM_INSTALL_DIR_STATIC}
196+
if [[ "${{ runner.os }}" == "Linux" ]]; then
197+
# `FileCheck` binary shipped in musl tarballs is linked dynamically
198+
# to musl, we can't execute it on Ubuntu.
199+
rm -f "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin/FileCheck"
200+
fi
201+
fi
202+
203+
- name: Restore LLVM from GitHub Actions
142204
if: matrix.llvm-from == 'source'
143205
uses: actions/cache/restore@v4
144206
with:
@@ -165,17 +227,19 @@ jobs:
165227
166228
- uses: taiki-e/install-action@cargo-hack
167229

168-
- name: Check
230+
- name: Check (dynamic linking, feature powerset)
231+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
169232
run: |
170-
cargo hack check --feature-powerset \
171-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
172-
--features ${{ env.LLVM_FEATURES }}
233+
cargo hack check --feature-powerset --exclude-features \
234+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }},${{ matrix.platform.exclude-features }} \
235+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
173236
174-
- name: Build
237+
- name: Build (dynamic linking, feature powerset)
238+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
175239
run: |
176-
cargo hack build --feature-powerset \
177-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
178-
--features ${{ env.LLVM_FEATURES }}
240+
cargo hack build --feature-powerset --exclude-features \
241+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }},${{ matrix.platform.exclude-features }} \
242+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
179243
180244
# Toolchains provided by rustup include standard library artifacts
181245
# only for Tier 1 targets, which do not include BPF targets.
@@ -185,11 +249,13 @@ jobs:
185249
# running compiler tests.
186250
#
187251
# `RUSTC_BOOTSTRAP` is needed to use `rustc-build-sysroot` on stable Rust.
188-
- name: Test (sysroot built on demand)
252+
- name: Test (sysroot built on demand, dynamic linking)
253+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
189254
run: |
190255
RUSTC_BOOTSTRAP=1 cargo hack test --feature-powerset \
191-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
192-
--features ${{ env.LLVM_FEATURES }}
256+
--exclude-features \
257+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }},${{ matrix.platform.exclude-features }} \
258+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
193259
194260
# To make things easier for package maintainers, the step of building a
195261
# custom sysroot can be skipped by setting the `BPFEL_SYSROOT_DIR`
@@ -200,7 +266,7 @@ jobs:
200266
#
201267
# `RUSTC_BOOTSTRAP` is needed to make `xtask build-std` work on stable
202268
# Rust.
203-
- name: Test (prebuilt BPF standard library)
269+
- name: Build BPF standard library
204270
run: |
205271
set -euxo pipefail
206272
@@ -211,9 +277,36 @@ jobs:
211277
--sysroot-dir "$BPFEL_SYSROOT_DIR" \
212278
--target bpfel-unknown-none
213279
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 }}
280+
- name: Test (prebuilt BPF standard libary, dynamic linking)
281+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
282+
run: |
283+
BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \
284+
cargo hack test --feature-powerset --exclude-features \
285+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }},${{ matrix.platform.exclude-features }} \
286+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
287+
288+
- name: Prepare for static linking (LLVM from Rust CI)
289+
if: matrix.llvm-from == 'rust-ci'
290+
run: |
291+
echo "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin" >> $GITHUB_PATH
292+
293+
- name: Install static libraries (macOS)
294+
if: runner.os == 'macOS'
295+
# macOS does not provide any static libraries. Homebrew does provide
296+
# them, but in custom paths that the system-wide clang is not aware of.
297+
# Point build.rs to them by setting environment variables.
298+
#
299+
# We install llvm package only for libc++.
300+
#
301+
# libLLVM from homebrew requires zstd.
302+
run: |
303+
brew install llvm zlib
304+
echo "CXXSTDLIB_PATH=$(brew --prefix llvm)/lib/c++" >> $GITHUB_ENV
305+
echo "ZLIB_PATH=$(brew --prefix zlib)/lib" >> $GITHUB_ENV
306+
if [[ "${{ matrix.llvm-from }}" == "packages" ]]; then
307+
brew install zstd
308+
echo "LIBZSTD_PATH=$(brew --prefix zstd)/lib" >> $GITHUB_ENV
309+
fi
217310
218311
- uses: actions/checkout@v6
219312
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
@@ -224,13 +317,39 @@ jobs:
224317

225318
- name: Install
226319
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
227-
run: cargo install --path . --no-default-features --features ${{ env.LLVM_FEATURES }}
320+
run: |
321+
cargo install --path . --no-default-features --features \
322+
${{ env.LLVM_FEATURES_STATIC }}
228323
229324
- name: Run aya integration tests
230325
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
231326
working-directory: aya
232327
run: cargo xtask integration-test local
233328

329+
- name: Check (static linking, single feature set)
330+
# Static linking in combination with `cargo hack --feature-powerset`
331+
# (multiple builds) increases the disk usage massively. Therefore we
332+
# perform all static builds with only one fixed feature set.
333+
run: |
334+
cargo check --no-default-features --features \
335+
${{ env.LLVM_FEATURES_STATIC }},${{ matrix.platform.llvm-features-static }}
336+
337+
- name: Build (static linking, single feature set)
338+
run: |
339+
cargo build --no-default-features --features \
340+
${{ env.LLVM_FEATURES_STATIC }},${{ matrix.platform.llvm-features-static }}
341+
342+
- name: Test (sysroot built on demand, static linking)
343+
run: |
344+
RUSTC_BOOTSTRAP=1 cargo test --no-default-features --features \
345+
${{ env.LLVM_FEATURES_STATIC }},${{ matrix.platform.llvm-features-static }}
346+
347+
- name: Test (prebuilt BPF standard library, static linking)
348+
run: |
349+
BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \
350+
cargo test --no-default-features --features \
351+
${{ env.LLVM_FEATURES_STATIC }},${{ matrix.platform.llvm-features-static }}
352+
234353
- name: Report disk usage
235354
if: ${{ always() }}
236355
uses: ./.github/actions/report-disk-usage

0 commit comments

Comments
 (0)