Skip to content

Commit f2ee2b6

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 43c8ac3 commit f2ee2b6

File tree

1 file changed

+141
-24
lines changed

1 file changed

+141
-24
lines changed

.github/workflows/ci.yml

Lines changed: 141 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,22 @@ 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
6973
- os: macos-15-intel
74+
static-target: x86_64-apple-darwin
7075
- os: ubuntu-22.04
76+
dynamic-target: x86_64-unknown-linux-gnu
77+
static-target: x86_64-unknown-linux-musl
7178
- os: ubuntu-22.04-arm
79+
dynamic-target: aarch64-unknown-linux-gnu
80+
static-target: aarch64-unknown-linux-musl
7281
llvm-from:
7382
- packages
83+
- rust-ci
7484
include:
7585
# Currently we build LLVM from source only for Linux x86_64.
7686
- toolchain:
@@ -85,8 +95,15 @@ jobs:
8595

8696
env:
8797
RUST_BACKTRACE: full
88-
LLVM_FEATURES: llvm-${{ matrix.toolchain.llvm }}
89-
LLVM_EXCLUDE_FEATURES: llvm-link-static,no-llvm-linking
98+
# Features that have to be included for dynamic linking.
99+
LLVM_FEATURES_DYNAMIC: llvm-${{ matrix.toolchain.llvm }}
100+
# Features that have to be included for static linking.
101+
LLVM_FEATURES_STATIC: llvm-${{ matrix.toolchain.llvm }},llvm-link-static
102+
# Features that have to be excluded when running `cargo hack --feature-powerset`
103+
# and intending to link dynamically.
104+
LLVM_EXCLUDE_FEATURES_DYNAMIC: llvm-link-static,no-llvm-linking
105+
RUSTC_LLVM_INSTALL_DIR_DYNAMIC: /tmp/rustc-llvm-dynamic
106+
RUSTC_LLVM_INSTALL_DIR_STATIC: /tmp/rustc-llvm-static
90107

91108
steps:
92109
- uses: actions/checkout@v6
@@ -118,16 +135,19 @@ jobs:
118135
set -euxo pipefail
119136
echo /usr/lib/llvm-15/bin >> $GITHUB_PATH
120137
121-
- name: Install LLVM (Linux, packages)
122-
if: matrix.llvm-from == 'packages' && runner.os == 'Linux'
138+
- name: Add LLVM APT repository
139+
if: runner.os == 'Linux'
123140
run: |
124141
set -euxo pipefail
125142
wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc
126143
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-
128144
sudo apt update
129-
sudo apt -y install llvm-${{ matrix.llvm-version }}-dev
130-
echo /usr/lib/llvm-${{ matrix.llvm-version }}/bin >> $GITHUB_PATH
145+
146+
- name: Install LLVM (Linux, packages)
147+
if: matrix.llvm-from == 'packages' && runner.os == 'Linux'
148+
run: |
149+
set -euxo pipefail
150+
sudo apt -y install llvm-${{ matrix.toolchain.llvm }}-dev
131151
echo /usr/lib/llvm-${{ matrix.toolchain.llvm }}/bin >> $GITHUB_PATH
132152
133153
- name: Install LLVM (macOS, packages)
@@ -138,7 +158,39 @@ jobs:
138158
echo $(brew --prefix llvm@${{ matrix.toolchain.llvm }})/bin >> $GITHUB_PATH
139159
echo "DYLD_LIBRARY_PATH=$(brew --prefix llvm@${{ matrix.toolchain.llvm }})/lib" >> $GITHUB_ENV
140160
141-
- name: Restore LLVM
161+
- name: Install LLVM from Rust CI
162+
if: matrix.llvm-from == 'rust-ci'
163+
run: |
164+
set -euxo pipefail
165+
mkdir -p $RUSTC_LLVM_INSTALL_DIR_DYNAMIC $RUSTC_LLVM_INSTALL_DIR_STATIC
166+
rustc_sha=$(cargo xtask rustc-llvm-commit --github-token "${{ secrets.GITHUB_TOKEN }}")
167+
download_llvm() {
168+
local target=$1
169+
local install_dir=$2
170+
wget -q -O - "https://ci-artifacts.rust-lang.org/rustc-builds/$rustc_sha/rust-dev-nightly-$target.tar.xz" | \
171+
tar -xJ --strip-components 2 -C $install_dir
172+
}
173+
if [[ -n "${{ matrix.platform['dynamic-target'] }}" ]]; then
174+
download_llvm \
175+
"${{ matrix.platform['dynamic-target'] }}" \
176+
${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}
177+
echo "LD_LIBRARY_PATH=${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/lib" >> $GITHUB_ENV
178+
# We start with steps that use dynamic linking. Add llvm-config
179+
# associated with dynamic target to `PATH`.
180+
echo "${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/bin" >> $GITHUB_PATH
181+
fi
182+
if [[ -n "${{ matrix.platform['static-target'] }}" ]]; then
183+
download_llvm \
184+
"${{ matrix.platform['static-target'] }}" \
185+
${RUSTC_LLVM_INSTALL_DIR_STATIC}
186+
if [[ "${{ runner.os }}" == "Linux" ]]; then
187+
# `FileCheck` binary shipped in musl tarballs is linked dynamically
188+
# to musl, we can't execute it on Ubuntu.
189+
rm -f "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin/FileCheck"
190+
fi
191+
fi
192+
193+
- name: Restore LLVM from GitHub Actions
142194
if: matrix.llvm-from == 'source'
143195
uses: actions/cache/restore@v4
144196
with:
@@ -165,17 +217,19 @@ jobs:
165217
166218
- uses: taiki-e/install-action@cargo-hack
167219

168-
- name: Check
220+
- name: Check (dynamic linking, feature powerset)
221+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
169222
run: |
170-
cargo hack check --feature-powerset \
171-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
172-
--features ${{ env.LLVM_FEATURES }}
223+
cargo hack check --feature-powerset --exclude-features \
224+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \
225+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
173226
174-
- name: Build
227+
- name: Build (dynamic linking, feature powerset)
228+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
175229
run: |
176-
cargo hack build --feature-powerset \
177-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
178-
--features ${{ env.LLVM_FEATURES }}
230+
cargo hack build --feature-powerset --exclude-features \
231+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \
232+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
179233
180234
# Toolchains provided by rustup include standard library artifacts
181235
# only for Tier 1 targets, which do not include BPF targets.
@@ -185,11 +239,13 @@ jobs:
185239
# running compiler tests.
186240
#
187241
# `RUSTC_BOOTSTRAP` is needed to use `rustc-build-sysroot` on stable Rust.
188-
- name: Test (sysroot built on demand)
242+
- name: Test (sysroot built on demand, dynamic linking)
243+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
189244
run: |
190245
RUSTC_BOOTSTRAP=1 cargo hack test --feature-powerset \
191-
--exclude-features ${{ env.LLVM_EXCLUDE_FEATURES }},${{ matrix.toolchain.exclude-features }} \
192-
--features ${{ env.LLVM_FEATURES }}
246+
--exclude-features \
247+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \
248+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
193249
194250
# To make things easier for package maintainers, the step of building a
195251
# custom sysroot can be skipped by setting the `BPFEL_SYSROOT_DIR`
@@ -200,7 +256,7 @@ jobs:
200256
#
201257
# `RUSTC_BOOTSTRAP` is needed to make `xtask build-std` work on stable
202258
# Rust.
203-
- name: Test (prebuilt BPF standard library)
259+
- name: Build BPF standard library
204260
run: |
205261
set -euxo pipefail
206262
@@ -211,9 +267,13 @@ jobs:
211267
--sysroot-dir "$BPFEL_SYSROOT_DIR" \
212268
--target bpfel-unknown-none
213269
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 }}
270+
- name: Test (prebuilt BPF standard libary, dynamic linking)
271+
if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci'
272+
run: |
273+
BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \
274+
cargo hack test --feature-powerset --exclude-features \
275+
${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \
276+
--features ${{ env.LLVM_FEATURES_DYNAMIC }}
217277
218278
- uses: actions/checkout@v6
219279
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
@@ -224,13 +284,70 @@ jobs:
224284

225285
- name: Install
226286
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
227-
run: cargo install --path . --no-default-features --features ${{ env.LLVM_FEATURES }}
287+
run: |
288+
cargo install --path . --no-default-features --features \
289+
${{ env.LLVM_FEATURES_DYNAMIC }}
228290
229291
- name: Run aya integration tests
230292
if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly'
231293
working-directory: aya
232294
run: cargo xtask integration-test local
233295

296+
- name: Prepare for static linking (LLVM from Rust CI)
297+
if: matrix.llvm-from == 'rust-ci'
298+
run: |
299+
echo "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin" >> $GITHUB_PATH
300+
301+
- name: Install static libraries (macOS)
302+
if: runner.os == 'macOS'
303+
# macOS does not provide any static libraries. Homebrew does provide
304+
# them, but in custom paths that the system-wide clang is not aware of.
305+
# Point build.rs to them by setting environment variables.
306+
#
307+
# We install llvm package only for libc++.
308+
#
309+
# libLLVM from homebrew requires zstd.
310+
run: |
311+
brew install llvm zlib
312+
echo "CXXSTDLIB_PATH=$(brew --prefix llvm)/lib/c++" >> $GITHUB_ENV
313+
echo "ZLIB_PATH=$(brew --prefix zlib)/lib" >> $GITHUB_ENV
314+
if [[ "${{ matrix.llvm-from }}" == "packages" ]]; then
315+
brew install zstd
316+
echo "LIBZSTD_PATH=$(brew --prefix zstd)/lib" >> $GITHUB_ENV
317+
fi
318+
319+
- name: Point to correct stdc++ (Linux)
320+
if: runner.os == 'Linux'
321+
# There are multiple versions of stdc++ static libraries on Ubuntu,
322+
# each of them in versioned subdirectory inside /usr/lib/gcc. Pick one
323+
# for clarity.
324+
run: |
325+
echo "CXXSTDLIB_PATH=/usr/lib/gcc/x86_64-linux-gnu/12"
326+
327+
- name: Check (static linking, single feature set)
328+
# Static linking in combination with `cargo hack --feature-powerset`
329+
# (multiple builds) increases the disk usage massively. Therefore we
330+
# perform all static builds with only one fixed feature set.
331+
run: |
332+
cargo check --no-default-features --features \
333+
${{ env.LLVM_FEATURES_STATIC }}
334+
335+
- name: Build (static linking, single feature set)
336+
run: |
337+
cargo build --no-default-features --features \
338+
${{ env.LLVM_FEATURES_STATIC }}
339+
340+
- name: Test (sysroot built on demand, static linking)
341+
run: |
342+
RUSTC_BOOTSTRAP=1 cargo test --no-default-features --features \
343+
${{ env.LLVM_FEATURES_STATIC }}
344+
345+
- name: Test (prebuilt BPF standard library, static linking)
346+
run: |
347+
BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \
348+
cargo test --no-default-features --features \
349+
${{ env.LLVM_FEATURES_STATIC }}
350+
234351
- name: Report disk usage
235352
if: ${{ always() }}
236353
uses: ./.github/actions/report-disk-usage

0 commit comments

Comments
 (0)