@@ -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