CI #678
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| pull_request: | |
| schedule: | |
| - cron: 00 4 * * * | |
| env: | |
| CARGO_TERM_COLOR: always | |
| permissions: {} | |
| jobs: | |
| llvm: | |
| uses: ./.github/workflows/llvm.yml | |
| lint-stable: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: stable | |
| components: clippy, rust-src | |
| - name: Run clippy | |
| run: cargo clippy --features llvm-21,no-llvm-linking --all-targets --workspace -- --deny warnings | |
| lint-nightly: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: nightly | |
| components: rustfmt, rust-src | |
| - name: Check formatting | |
| run: cargo fmt --all -- --check | |
| build: | |
| runs-on: ${{ matrix.platform.os }} | |
| # We work with two git repositories in this workflow: | |
| # | |
| # - bpf-linker | |
| # - aya (for integration tests) | |
| # | |
| # Cargo searches for `.cargo` directories recursively in all parent | |
| # directories. Therefore, nesting different Rust projects with their own | |
| # `.cargo/config.toml` files in the same hierarchy (one nested in another) | |
| # causes cargo to read and merge both configurations. | |
| # | |
| # To avoid that, we clone both repositories in separate directories inside | |
| # the workspace. | |
| defaults: | |
| run: | |
| working-directory: bpf-linker | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| toolchain: | |
| - rust: 1.90.0 | |
| llvm: 20 | |
| exclude-features: default,llvm-19,llvm-21,rust-llvm-19,rust-llvm-21 | |
| - rust: stable | |
| llvm: 21 | |
| exclude-features: default,llvm-19,llvm-20,rust-llvm-19,rust-llvm-20 | |
| - rust: beta | |
| llvm: 21 | |
| exclude-features: default,llvm-20,rust-llvm-20 | |
| - rust: nightly | |
| llvm: 21 | |
| exclude-features: llvm-20,rust-llvm-20 | |
| platform: | |
| # Rust CI ships only one flavor of libLLVM, dynamic or static, per | |
| # target. Linux GNU targets come with dynamic ones. Apple and Linux | |
| # musl targets come with static ones. | |
| - os: macos-latest | |
| static-target: aarch64-apple-darwin | |
| - os: macos-15-intel | |
| static-target: x86_64-apple-darwin | |
| # We don't use ubuntu-latest because we care about the apt packages available. | |
| - os: ubuntu-22.04 | |
| dynamic-target: x86_64-unknown-linux-gnu | |
| static-target: x86_64-unknown-linux-musl | |
| - os: ubuntu-22.04-arm | |
| dynamic-target: aarch64-unknown-linux-gnu | |
| static-target: aarch64-unknown-linux-musl | |
| llvm-from: | |
| - packages | |
| - rust-ci | |
| include: | |
| # Currently we build LLVM from source only for Linux x86_64. | |
| - toolchain: | |
| rust: nightly | |
| llvm: 21 | |
| exclude-features: llvm-20,rust-llvm-20 | |
| platform: | |
| os: ubuntu-22.04 | |
| llvm-from: source | |
| name: os=${{ matrix.platform.os }} rustc=${{ matrix.toolchain.rust }} llvm-version=${{ matrix.toolchain.llvm }} llvm-from=${{ matrix.llvm-from }} | |
| needs: llvm | |
| env: | |
| RUST_BACKTRACE: full | |
| # Features that have to be included for dynamic linking. | |
| LLVM_FEATURES_DYNAMIC: llvm-${{ matrix.toolchain.llvm }} | |
| # Features that have to be included for static linking. | |
| LLVM_FEATURES_STATIC: llvm-${{ matrix.toolchain.llvm }},llvm-link-static | |
| # Features that have to be excluded when running `cargo hack --feature-powerset` | |
| # and intending to link dynamically. | |
| LLVM_EXCLUDE_FEATURES_DYNAMIC: llvm-link-static,no-llvm-linking | |
| RUSTC_LLVM_INSTALL_DIR_DYNAMIC: /tmp/rustc-llvm-dynamic | |
| RUSTC_LLVM_INSTALL_DIR_STATIC: /tmp/rustc-llvm-static | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| path: bpf-linker | |
| - name: Install Rust ${{ matrix.toolchain.rust }} | |
| uses: dtolnay/rust-toolchain@master | |
| with: | |
| toolchain: ${{ matrix.toolchain.rust }} | |
| components: rust-src | |
| - name: Check (default features, no system LLVM) | |
| run: cargo check | |
| - name: Build (default features, no system LLVM) | |
| run: cargo build | |
| - name: Install btfdump | |
| run: cargo install btfdump | |
| - name: Add clang to PATH | |
| if: runner.os == 'Linux' | |
| # ubuntu-22.04 comes with clang 13-15[0]; support for signed and 64bit | |
| # enum values was added in clang 15[1] which isn't in `$PATH`. | |
| # | |
| # [0] https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2204-Readme.md | |
| # | |
| # [1] https://github.com/llvm/llvm-project/commit/dc1c43d | |
| run: echo /usr/lib/llvm-15/bin >> $GITHUB_PATH | |
| - name: Install LLVM (Linux, packages) | |
| if: matrix.llvm-from == 'packages' && runner.os == 'Linux' | |
| run: | | |
| set -euxo pipefail | |
| wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc | |
| echo -e deb http://apt.llvm.org/jammy/ llvm-toolchain-jammy-${{ matrix.toolchain.llvm }} main | sudo tee /etc/apt/sources.list.d/llvm.list | |
| sudo apt update | |
| sudo apt -y install llvm-${{ matrix.toolchain.llvm }}-dev | |
| echo /usr/lib/llvm-${{ matrix.toolchain.llvm }}/bin >> $GITHUB_PATH | |
| - name: Install LLVM (macOS, packages) | |
| if: matrix.llvm-from == 'packages' && runner.os == 'macOS' | |
| run: | | |
| set -euxo pipefail | |
| brew install llvm@${{ matrix.toolchain.llvm }} | |
| echo $(brew --prefix llvm@${{ matrix.toolchain.llvm }})/bin >> $GITHUB_PATH | |
| # DYLD_LIBRARY_PATH is needed because we're going to link everything dynamically below. This | |
| # doesn't affect behavior, but greatly reduces disk usage. | |
| echo "DYLD_LIBRARY_PATH=$(brew --prefix llvm@${{ matrix.toolchain.llvm }})/lib" >> $GITHUB_ENV | |
| - name: Install LLVM from Rust CI | |
| if: matrix.llvm-from == 'rust-ci' | |
| run: | | |
| set -euxo pipefail | |
| mkdir -p $RUSTC_LLVM_INSTALL_DIR_DYNAMIC $RUSTC_LLVM_INSTALL_DIR_STATIC | |
| rustc_sha=$(cargo xtask rustc-llvm-commit --github-token "${{ secrets.GITHUB_TOKEN }}") | |
| download_llvm() { | |
| local target=$1 | |
| local install_dir=$2 | |
| wget -q -O - "https://ci-artifacts.rust-lang.org/rustc-builds/$rustc_sha/rust-dev-nightly-$target.tar.xz" | \ | |
| tar -xJ --strip-components 2 -C $install_dir | |
| } | |
| if [[ -n "${{ matrix.platform['dynamic-target'] }}" ]]; then | |
| download_llvm \ | |
| "${{ matrix.platform['dynamic-target'] }}" \ | |
| ${RUSTC_LLVM_INSTALL_DIR_DYNAMIC} | |
| # LD_LIBRARY_PATH is needed because we're going to link everything dynamically below. This | |
| # doesn't affect behavior, but greatly reduces disk usage. | |
| echo "LD_LIBRARY_PATH=${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/lib" >> $GITHUB_ENV | |
| # We start with steps that use dynamic linking. Add llvm-config | |
| # associated with dynamic target to `PATH`. | |
| echo "${RUSTC_LLVM_INSTALL_DIR_DYNAMIC}/bin" >> $GITHUB_PATH | |
| fi | |
| if [[ -n "${{ matrix.platform['static-target'] }}" ]]; then | |
| download_llvm \ | |
| "${{ matrix.platform['static-target'] }}" \ | |
| ${RUSTC_LLVM_INSTALL_DIR_STATIC} | |
| if [[ "${{ runner.os }}" == "Linux" ]]; then | |
| # `FileCheck` binary shipped in musl tarballs is linked dynamically | |
| # to musl, we can't execute it on Ubuntu. | |
| rm -f "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin/FileCheck" | |
| fi | |
| fi | |
| - name: Restore LLVM from GitHub Actions | |
| if: matrix.llvm-from == 'source' | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: llvm-install | |
| key: ${{ needs.llvm.outputs.cache-key }} | |
| fail-on-cache-miss: true | |
| - name: Add LLVM to PATH && LD_LIBRARY_PATH | |
| if: matrix.llvm-from == 'source' | |
| run: | | |
| set -euxo pipefail | |
| echo "${{ github.workspace }}/llvm-install/bin" >> $GITHUB_PATH | |
| # LD_LIBRARY_PATH is needed because we're going to link everything dynamically below. This | |
| # doesn't affect behavior, but greatly reduces disk usage. | |
| echo "LD_LIBRARY_PATH=${{ github.workspace }}/llvm-install/lib" >> $GITHUB_ENV | |
| # llvm-sys discovers link flags at build script time; these are cached by cargo. The cached | |
| # flags may be incorrect when the cache is reused across LLVM versions. | |
| - name: Bust llvm-sys cache | |
| run: | | |
| set -euxo pipefail | |
| cargo clean -p llvm-sys | |
| cargo clean -p llvm-sys --release | |
| - uses: taiki-e/install-action@cargo-hack | |
| - name: Check (dynamic linking, feature powerset) | |
| if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci' | |
| run: | | |
| cargo hack check --feature-powerset --exclude-features \ | |
| ${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \ | |
| --features ${{ env.LLVM_FEATURES_DYNAMIC }} | |
| - name: Build (dynamic linking, feature powerset) | |
| if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci' | |
| run: | | |
| cargo hack build --feature-powerset --exclude-features \ | |
| ${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \ | |
| --features ${{ env.LLVM_FEATURES_DYNAMIC }} | |
| # Toolchains provided by rustup include standard library artifacts | |
| # only for Tier 1 targets, which do not include BPF targets. | |
| # | |
| # The default workaround is to use the `rustc-build-sysroot` crate to | |
| # build a custom sysroot with the required BPF standard library before | |
| # running compiler tests. | |
| # | |
| # `RUSTC_BOOTSTRAP` is needed to use `rustc-build-sysroot` on stable Rust. | |
| - name: Test (sysroot built on demand, dynamic linking) | |
| if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci' | |
| run: | | |
| RUSTC_BOOTSTRAP=1 cargo hack test --feature-powerset \ | |
| --exclude-features \ | |
| ${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \ | |
| --features ${{ env.LLVM_FEATURES_DYNAMIC }} | |
| # To make things easier for package maintainers, the step of building a | |
| # custom sysroot can be skipped by setting the `BPFEL_SYSROOT_DIR` | |
| # environment variable to the path of the prebuilt BPF sysroot. | |
| # | |
| # Test this configuration by prebuilding the BPF standard library | |
| # manually. | |
| # | |
| # `RUSTC_BOOTSTRAP` is needed to make `xtask build-std` work on stable | |
| # Rust. | |
| - name: Build BPF standard library | |
| run: | | |
| set -euxo pipefail | |
| RUSTC_SRC="$(rustc --print sysroot)/lib/rustlib/src/rust/library" | |
| BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" | |
| RUSTC_BOOTSTRAP=1 cargo xtask build-std \ | |
| --rustc-src "$RUSTC_SRC" \ | |
| --sysroot-dir "$BPFEL_SYSROOT_DIR" \ | |
| --target bpfel-unknown-none | |
| - name: Test (prebuilt BPF standard libary, dynamic linking) | |
| if: matrix.platform.dynamic-target || matrix.llvm-from != 'rust-ci' | |
| run: | | |
| BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \ | |
| cargo hack test --feature-powerset --exclude-features \ | |
| ${{ env.LLVM_EXCLUDE_FEATURES_DYNAMIC }},${{ matrix.toolchain.exclude-features }} \ | |
| --features ${{ env.LLVM_FEATURES_DYNAMIC }} | |
| - uses: actions/checkout@v6 | |
| if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly' | |
| with: | |
| repository: aya-rs/aya | |
| path: aya | |
| submodules: recursive | |
| - name: Install | |
| if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly' | |
| run: | | |
| cargo install --path . --no-default-features --features \ | |
| ${{ env.LLVM_FEATURES_DYNAMIC }} | |
| - name: Run aya integration tests | |
| if: runner.os == 'Linux' && matrix.toolchain.rust == 'nightly' | |
| working-directory: aya | |
| run: cargo xtask integration-test local | |
| - name: Prepare for static linking (LLVM from Rust CI) | |
| if: matrix.llvm-from == 'rust-ci' | |
| run: | | |
| echo "${RUSTC_LLVM_INSTALL_DIR_STATIC}/bin" >> $GITHUB_PATH | |
| - name: Install static libraries (macOS) | |
| if: runner.os == 'macOS' | |
| # macOS does not provide any static libraries. Homebrew does provide | |
| # them, but in custom paths that the system-wide clang is not aware of. | |
| # Point build.rs to them by setting environment variables. | |
| # | |
| # We install llvm package only for libc++. | |
| # | |
| # libLLVM from homebrew requires zstd. | |
| run: | | |
| set -euxo pipefail | |
| brew install llvm zlib | |
| echo "CXXSTDLIB_PATH=$(brew --prefix llvm)/lib/c++" >> $GITHUB_ENV | |
| echo "ZLIB_PATH=$(brew --prefix zlib)/lib" >> $GITHUB_ENV | |
| if [[ "${{ matrix.llvm-from }}" == "packages" ]]; then | |
| brew install zstd | |
| echo "LIBZSTD_PATH=$(brew --prefix zstd)/lib" >> $GITHUB_ENV | |
| fi | |
| - name: Check (static linking, single feature set) | |
| # Static linking in combination with `cargo hack --feature-powerset` | |
| # (multiple builds) increases the disk usage massively. Therefore we | |
| # perform all static builds with only one fixed feature set. | |
| run: | | |
| cargo check --no-default-features --features \ | |
| ${{ env.LLVM_FEATURES_STATIC }} | |
| - name: Build (static linking, single feature set) | |
| run: | | |
| cargo build --no-default-features --features \ | |
| ${{ env.LLVM_FEATURES_STATIC }} | |
| - name: Test (sysroot built on demand, static linking) | |
| run: | | |
| RUSTC_BOOTSTRAP=1 cargo test --no-default-features --features \ | |
| ${{ env.LLVM_FEATURES_STATIC }} | |
| - name: Test (prebuilt BPF standard library, static linking) | |
| run: | | |
| BPFEL_SYSROOT_DIR="${{ github.workspace }}/bpf-sysroot" \ | |
| cargo test --no-default-features --features \ | |
| ${{ env.LLVM_FEATURES_STATIC }} | |
| - name: Report disk usage | |
| if: ${{ always() }} | |
| uses: ./bpf-linker/.github/actions/report-disk-usage |