Skip to content

Commit 8c31073

Browse files
committed
ci: Specify target and static linking of C runtime explicitly
Without specifying the target, cargo uses the host target, which in case of Linux runners is `*-unknown-linux-gnu`. To test static linking to the full extent, use `*-unknown-linux-musl` targets. On top of that, make sure that libc and C runtime are actually linked statically by specifying `-C target-feature=+crt-static` rustflag. As of today, that's still a default option on the most of `*-musl` targets[0][1], but it's being phased out in favor of dynamic linking being the default option.[2][3][4] [0] https://github.com/rust-lang/rust/blob/672388edbee9e93c35e5fdf7dac818a6612a5103/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs#L19-L20 [1] https://github.com/rust-lang/rust/blob/672388edbee9e93c35e5fdf7dac818a6612a5103/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs#L17-L18 [2] rust-lang/compiler-team#422 [3] rust-lang/rust#133386 [4] rust-lang/rust#14451
1 parent 2a078ad commit 8c31073

File tree

1 file changed

+41
-8
lines changed

1 file changed

+41
-8
lines changed

.github/workflows/ci.yml

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ jobs:
119119
LLVM_EXCLUDE_FEATURES_DYNAMIC: llvm-link-static,no-llvm-linking
120120
RUSTC_LLVM_INSTALL_DIR_DYNAMIC: /tmp/rustc-llvm-dynamic
121121
RUSTC_LLVM_INSTALL_DIR_STATIC: /tmp/rustc-llvm-static
122+
SYSROOT_DIR: /tmp/sysroot
122123

123124
steps:
124125
- uses: actions/checkout@v6
@@ -130,6 +131,7 @@ jobs:
130131
with:
131132
toolchain: ${{ matrix.toolchain.rust }}
132133
components: rust-src
134+
targets: ${{ matrix.platform.static-target }}
133135

134136
- name: Check (default features, no system LLVM)
135137
run: cargo check
@@ -313,6 +315,15 @@ jobs:
313315
run: |
314316
echo "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin" >> $GITHUB_PATH
315317
318+
- name: Prepare sysroot
319+
if: runner.os == 'Linux' && matrix.llvm-from == 'rust-ci'
320+
run: |
321+
set -euxo pipefail
322+
mkdir -p $SYSROOT_DIR
323+
wget -q -O - $(cargo xtask musl-sysroot-url) | \
324+
tar -xJ -C $SYSROOT_DIR --xattrs-include='*.*' --numeric-owner --wildcards './usr/lib/*'
325+
echo "CXXSTDLIB_PATH=$(dirname $(find $SYSROOT_DIR -name libstdc++.a))" >> $GITHUB_ENV
326+
316327
- name: Install static libraries (macOS)
317328
if: runner.os == 'macOS'
318329
# macOS does not provide any static libraries. Homebrew does provide
@@ -333,28 +344,50 @@ jobs:
333344
fi
334345
335346
- name: Check (static linking, single feature set)
347+
# LLVM from APT is dynamically linked against glibc, so when used with
348+
# musl it causes link errors (libLLVM contains undefined glibc symbols).
349+
# To build fully static binaries, LLVM from the `*-musl` Rust CI
350+
# tarballs must be used instead.
351+
if: ${{ ! (runner.os == 'Linux' && matrix.llvm-from == 'packages') }}
336352
# Static linking in combination with `cargo hack --feature-powerset`
337353
# (multiple builds) increases the disk usage massively. Therefore we
338354
# perform all static builds with only one fixed feature set.
339355
run: |
340-
cargo check --no-default-features --features \
341-
${{ env.LLVM_FEATURES_STATIC }}
356+
set -euxo pipefail
357+
# Link libc and C runtime statically.
358+
echo "RUSTFLAGS=-C target-feature=+crt-static" >> $GITHUB_ENV
359+
cargo check --no-default-features \
360+
--features ${{ env.LLVM_FEATURES_STATIC }} \
361+
--target ${{ matrix.platform.static-target }}
342362
343363
- name: Build (static linking, single feature set)
364+
if: ${{ ! (runner.os == 'Linux' && matrix.llvm-from == 'packages') }}
344365
run: |
345-
cargo build --no-default-features --features \
346-
${{ env.LLVM_FEATURES_STATIC }}
366+
set -euxo pipefail
367+
cargo build --no-default-features \
368+
--features ${{ env.LLVM_FEATURES_STATIC }} \
369+
--target ${{ matrix.platform.static-target }}
370+
bin="target/${{ matrix.platform.static-target }}/debug/bpf-linker"
371+
if readelf -l "$bin" | grep -q INTERP || \
372+
readelf -d "$bin" | grep -q '(NEEDED)'; then
373+
echo "ERROR: $bin is NOT fully static (has runtime dependencies)"
374+
exit 1
375+
fi
347376
348377
- name: Test (sysroot built on demand, static linking)
378+
if: ${{ ! (runner.os == 'Linux' && matrix.llvm-from == 'packages') }}
349379
run: |
350-
RUSTC_BOOTSTRAP=1 cargo test --no-default-features --features \
351-
${{ env.LLVM_FEATURES_STATIC }}
380+
RUSTC_BOOTSTRAP=1 cargo test --no-default-features \
381+
--features ${{ env.LLVM_FEATURES_STATIC }} \
382+
--target ${{ matrix.platform.static-target }}
352383
353384
- name: Test (prebuilt BPF standard library, static linking)
385+
if: ${{ ! (runner.os == 'Linux' && matrix.llvm-from == 'packages') }}
354386
run: |
355387
BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \
356-
cargo test --no-default-features --features \
357-
${{ env.LLVM_FEATURES_STATIC }}
388+
cargo test --no-default-features \
389+
--features ${{ env.LLVM_FEATURES_STATIC }} \
390+
--target ${{ matrix.platform.static-target }}
358391
359392
- name: Report disk usage
360393
if: ${{ always() }}

0 commit comments

Comments
 (0)