Skip to content

Commit d8bad80

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 5baef96 commit d8bad80

File tree

1 file changed

+129
-20
lines changed

1 file changed

+129
-20
lines changed

.github/workflows/ci.yml

Lines changed: 129 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,23 @@ jobs:
7979
llvm: 21
8080
exclude-features: llvm-20,rust-llvm-20
8181
platform:
82+
# Rust CI ships only one flavor of libLLVM, dynamic or static, per
83+
# target. Linux GNU targets come with dynamic ones. Apple and Linux
84+
# musl targets come with static ones.
8285
- os: macos-latest
86+
static-target: aarch64-apple-darwin
8387
- os: macos-15-intel
88+
static-target: x86_64-apple-darwin
8489
# We don't use ubuntu-latest because we care about the apt packages available.
8590
- os: ubuntu-22.04
91+
dynamic-target: x86_64-unknown-linux-gnu
92+
static-target: x86_64-unknown-linux-musl
8693
- os: ubuntu-22.04-arm
94+
dynamic-target: aarch64-unknown-linux-gnu
95+
static-target: aarch64-unknown-linux-musl
8796
llvm-from:
8897
- packages
98+
- rust-ci
8999
include:
90100
# Currently we build LLVM from source only for Linux x86_64.
91101
- toolchain:
@@ -100,8 +110,15 @@ jobs:
100110

101111
env:
102112
RUST_BACKTRACE: full
103-
LLVM_FEATURES: llvm-${{ matrix.toolchain.llvm }}
104-
LLVM_EXCLUDE_FEATURES: llvm-link-static,no-llvm-linking
113+
# Features that have to be included for dynamic linking.
114+
LLVM_FEATURES_DYNAMIC: llvm-${{ matrix.toolchain.llvm }}
115+
# Features that have to be included for static linking.
116+
LLVM_FEATURES_STATIC: llvm-${{ matrix.toolchain.llvm }},llvm-link-static
117+
# Features that have to be excluded when running `cargo hack --feature-powerset`
118+
# and intending to link dynamically.
119+
LLVM_EXCLUDE_FEATURES_DYNAMIC: llvm-link-static,no-llvm-linking
120+
RUSTC_LLVM_INSTALL_DIR_DYNAMIC: /tmp/rustc-llvm-dynamic
121+
RUSTC_LLVM_INSTALL_DIR_STATIC: /tmp/rustc-llvm-static
105122

106123
steps:
107124
- uses: actions/checkout@v6
@@ -150,11 +167,45 @@ jobs:
150167
set -euxo pipefail
151168
brew install llvm@${{ matrix.toolchain.llvm }}
152169
echo $(brew --prefix llvm@${{ matrix.toolchain.llvm }})/bin >> $GITHUB_PATH
153-
# LD_LIBRARY_PATH is needed because we're going to link everything dynamically below. This
170+
# DYLD_LIBRARY_PATH is needed because we're going to link everything dynamically below. This
154171
# doesn't affect behavior, but greatly reduces disk usage.
155172
echo "DYLD_LIBRARY_PATH=$(brew --prefix llvm@${{ matrix.toolchain.llvm }})/lib" >> $GITHUB_ENV
156173
157-
- name: Restore LLVM
174+
- name: Install LLVM from Rust CI
175+
if: matrix.llvm-from == 'rust-ci'
176+
run: |
177+
set -euxo pipefail
178+
mkdir -p $RUSTC_LLVM_INSTALL_DIR_DYNAMIC $RUSTC_LLVM_INSTALL_DIR_STATIC
179+
rustc_sha=$(cargo xtask rustc-llvm-commit --github-token "${{ secrets.GITHUB_TOKEN }}")
180+
download_llvm() {
181+
local target=$1
182+
local install_dir=$2
183+
wget -q -O - "https://ci-artifacts.rust-lang.org/rustc-builds/$rustc_sha/rust-dev-nightly-$target.tar.xz" | \
184+
tar -xJ --strip-components 2 -C $install_dir
185+
}
186+
if [[ -n "${{ matrix.platform['dynamic-target'] }}" ]]; then
187+
download_llvm \
188+
"${{ matrix.platform['dynamic-target'] }}" \
189+
${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}
190+
# LD_LIBRARY_PATH is needed because we're going to link everything dynamically below. This
191+
# doesn't affect behavior, but greatly reduces disk usage.
192+
echo "LD_LIBRARY_PATH=${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/lib" >> $GITHUB_ENV
193+
# We start with steps that use dynamic linking. Add llvm-config
194+
# associated with dynamic target to `PATH`.
195+
echo "${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/bin" >> $GITHUB_PATH
196+
fi
197+
if [[ -n "${{ matrix.platform['static-target'] }}" ]]; then
198+
download_llvm \
199+
"${{ matrix.platform['static-target'] }}" \
200+
${RUSTC_LLVM_INSTALL_DIR_STATIC}
201+
if [[ "${{ runner.os }}" == "Linux" ]]; then
202+
# `FileCheck` binary shipped in musl tarballs is linked dynamically
203+
# to musl, we can't execute it on Ubuntu.
204+
rm -f "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin/FileCheck"
205+
fi
206+
fi
207+
208+
- name: Restore LLVM from GitHub Actions
158209
if: matrix.llvm-from == 'source'
159210
uses: actions/cache/restore@v4
160211
with:
@@ -181,17 +232,19 @@ jobs:
181232
182233
- uses: taiki-e/install-action@cargo-hack
183234

184-
- name: Check
235+
- name: Check (dynamic linking, feature powerset)
236+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
185237
run: |
186-
cargo hack check --feature-powerset \
187-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
188-
--features ${{ env.LLVM_FEATURES }}
238+
cargo hack check --feature-powerset --exclude-features \
239+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \
240+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
189241
190-
- name: Build
242+
- name: Build (dynamic linking, feature powerset)
243+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
191244
run: |
192-
cargo hack build --feature-powerset \
193-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
194-
--features ${{ env.LLVM_FEATURES }}
245+
cargo hack build --feature-powerset --exclude-features \
246+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \
247+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
195248
196249
# Toolchains provided by rustup include standard library artifacts
197250
# only for Tier 1 targets, which do not include BPF targets.
@@ -201,11 +254,13 @@ jobs:
201254
# running compiler tests.
202255
#
203256
# `RUSTC_BOOTSTRAP` is needed to use `rustc-build-sysroot` on stable Rust.
204-
- name: Test (sysroot built on demand)
257+
- name: Test (sysroot built on demand, dynamic linking)
258+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
205259
run: |
206260
RUSTC_BOOTSTRAP=1 cargo hack test --feature-powerset \
207-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
208-
--features ${{ env.LLVM_FEATURES }}
261+
--exclude-features \
262+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \
263+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
209264
210265
# To make things easier for package maintainers, the step of building a
211266
# custom sysroot can be skipped by setting the `BPFEL_SYSROOT_DIR`
@@ -216,7 +271,7 @@ jobs:
216271
#
217272
# `RUSTC_BOOTSTRAP` is needed to make `xtask build-std` work on stable
218273
# Rust.
219-
- name: Test (prebuilt BPF standard library)
274+
- name: Build BPF standard library
220275
run: |
221276
set -euxo pipefail
222277
@@ -227,9 +282,13 @@ jobs:
227282
--sysroot-dir "$BPFEL_SYSROOT_DIR" \
228283
--target bpfel-unknown-none
229284
230-
BPFEL_SYSROOT_DIR="$BPFEL_SYSROOT_DIR" cargo hack test --feature-powerset \
231-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
232-
--features ${{ env.LLVM_FEATURES }}
285+
- name: Test (prebuilt BPF standard libary, dynamic linking)
286+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
287+
run: |
288+
BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \
289+
cargo hack test --feature-powerset --exclude-features \
290+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \
291+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
233292
234293
- uses: actions/checkout@v6
235294
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
@@ -240,13 +299,63 @@ jobs:
240299

241300
- name: Install
242301
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
243-
run: cargo install --path . --no-default-features --features ${{ env.LLVM_FEATURES }}
302+
run: |
303+
cargo install --path . --no-default-features --features \
304+
${{ env.LLVM_FEATURES_DYNAMIC }}
244305
245306
- name: Run aya integration tests
246307
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
247308
working-directory: aya
248309
run: cargo xtask integration-test local
249310

311+
- name: Prepare for static linking (LLVM from Rust CI)
312+
if: matrix.llvm-from == 'rust-ci'
313+
run: |
314+
echo "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin" >> $GITHUB_PATH
315+
316+
- name: Install static libraries (macOS)
317+
if: runner.os == 'macOS'
318+
# macOS does not provide any static libraries. Homebrew does provide
319+
# them, but in custom paths that the system-wide clang is not aware of.
320+
# Point build.rs to them by setting environment variables.
321+
#
322+
# We install llvm package only for libc++.
323+
#
324+
# libLLVM from homebrew requires zstd.
325+
run: |
326+
set -euxo pipefail
327+
brew install llvm zlib
328+
echo "CXXSTDLIB_PATH=$(brew --prefix llvm)/lib/c++" >> $GITHUB_ENV
329+
echo "ZLIB_PATH=$(brew --prefix zlib)/lib" >> $GITHUB_ENV
330+
if [[ "${{ matrix.llvm-from }}" == "packages" ]]; then
331+
brew install zstd
332+
echo "LIBZSTD_PATH=$(brew --prefix zstd)/lib" >> $GITHUB_ENV
333+
fi
334+
335+
- name: Check (static linking, single feature set)
336+
# Static linking in combination with `cargo hack --feature-powerset`
337+
# (multiple builds) increases the disk usage massively. Therefore we
338+
# perform all static builds with only one fixed feature set.
339+
run: |
340+
cargo check --no-default-features --features \
341+
${{ env.LLVM_FEATURES_STATIC }}
342+
343+
- name: Build (static linking, single feature set)
344+
run: |
345+
cargo build --no-default-features --features \
346+
${{ env.LLVM_FEATURES_STATIC }}
347+
348+
- name: Test (sysroot built on demand, static linking)
349+
run: |
350+
RUSTC_BOOTSTRAP=1 cargo test --no-default-features --features \
351+
${{ env.LLVM_FEATURES_STATIC }}
352+
353+
- name: Test (prebuilt BPF standard library, static linking)
354+
run: |
355+
BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \
356+
cargo test --no-default-features --features \
357+
${{ env.LLVM_FEATURES_STATIC }}
358+
250359
- name: Report disk usage
251360
if: ${{ always() }}
252361
uses: ./bpf-linker/.github/actions/report-disk-usage

0 commit comments

Comments
 (0)