Skip to content

.github/workflows/ci.yaml #284

.github/workflows/ci.yaml

.github/workflows/ci.yaml #284

Workflow file for this run

on:
schedule:
- cron: '0 8 * * *'
push:
pull_request:
jobs:
ci:
runs-on: ubuntu-24.04
timeout-minutes: 70
strategy:
fail-fast: false
matrix:
tree:
- torvalds
# rust-next
# next
arch:
- x86_64
# arm64
config:
- defconfig
- defconfig+debug
output:
- src
# subdir
# outside
env:
RUST_VERSION: nightly-2025-01-12
steps:
# Setup: variables.
- run: echo "JOBS=-j$(($(nproc) + 1))" >> $GITHUB_ENV
- if: matrix.arch == 'x86_64'
run: |
echo 'MAKE_ARCH=ARCH=x86_64' >> $GITHUB_ENV
echo 'IMAGE_PATH=arch/x86/boot/bzImage' >> $GITHUB_ENV
echo 'QEMU_ARCH=x86_64' >> $GITHUB_ENV
echo 'QEMU_ARGS=-append console=ttyS0' >> $GITHUB_ENV
- if: matrix.arch == 'arm64'
run: |
echo 'MAKE_ARCH=ARCH=arm64' >> $GITHUB_ENV
echo 'MAKE_CROSS_COMPILE=CROSS_COMPILE=aarch64-linux-gnu-' >> $GITHUB_ENV
echo 'IMAGE_PATH=arch/arm64/boot/Image.gz' >> $GITHUB_ENV
echo 'QEMU_ARCH=aarch64' >> $GITHUB_ENV
echo 'QEMU_ARGS=-machine virt' >> $GITHUB_ENV
- if: matrix.output == 'src'
run: |
echo 'OUTPUT_DIR=linux/' >> $GITHUB_ENV
- if: matrix.output == 'subdir'
run: |
echo 'MAKE_OUTPUT=O=subdir' >> $GITHUB_ENV
echo 'OUTPUT_DIR=linux/subdir/' >> $GITHUB_ENV
- if: matrix.output == 'outside'
run: |
echo 'MAKE_OUTPUT=O=../outside' >> $GITHUB_ENV
echo 'OUTPUT_DIR=outside/' >> $GITHUB_ENV
- run: |
sudo apt-get -y update
sudo apt-get -y --no-install-recommends install bc file git make flex bison libelf-dev libssl-dev curl python3 llvm clang lld binutils qemu-system-x86 qemu-system-arm
- if: matrix.arch == 'arm64'
run: sudo apt-get -y --no-install-recommends install gcc-aarch64-linux-gnu libc6-dev-arm64-cross
# Setup: checkout Linux source tree.
- if: matrix.tree == 'torvalds'
run: git clone --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git linux
- if: startsWith(matrix.tree, 'rust-')
run: git clone --depth 1 --branch ${{ matrix.tree }} https://github.com/Rust-for-Linux/linux.git linux
- if: matrix.tree == 'next'
run: git clone --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git linux
- run: git -C linux show --no-patch
# Setup: checkout CI tree.
- uses: actions/checkout@v4
with:
path: ci
- run: git -C linux apply ../ci/x86-boot-Use-std-gnu11-to-fix-build-with-GCC-15.patch
# Setup: `busybox`.
- run: |
git clone --depth 1 -b 1_30_1 https://git.busybox.net/busybox/
mv ci/busybox.config busybox/.config
make -C busybox ${{ env.MAKE_CROSS_COMPILE }} ${{ env.JOBS }} busybox
# Setup: Rust.
- run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \
-y \
--no-modify-path \
--default-toolchain $RUST_VERSION \
--profile minimal \
--component rust-src \
--component rustfmt \
--component clippy
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
# Setup: `rustc_codegen_gcc`.
- run: |
sudo apt-get -y --no-install-recommends purge cpp gcc
curl --proto '=https' --tlsv1.2 -sSfLO https://github.com/rust-lang/gcc/releases/latest/download/gcc-15.deb
sudo dpkg -i gcc-15.deb
git clone --depth 1 https://github.com/rust-lang/rustc_codegen_gcc
echo "MAKE_KRUSTFLAGS=KRUSTFLAGS=-Zcodegen-backend=$(pwd)/rustc_codegen_gcc/target/release/librustc_codegen_gcc.so" >> $GITHUB_ENV
cd rustc_codegen_gcc
echo 'gcc-path = "/usr/lib"' > config.toml
#sed -i '/channel/d' rust-toolchain
export RUSTC_BOOTSTRAP=1
./y.sh prepare --only-libcore
./y.sh build --sysroot --release
# Setup: `bindgen`.
- run: cargo install --locked --version 0.70.1 bindgen-cli
# Prepare build output folder.
- if: matrix.output != 'src'
run: |
mkdir ${{ env.OUTPUT_DIR }}
sed -i 's:linux/samples/rust/:${{ env.OUTPUT_DIR }}samples/rust/:' ci/qemu-initramfs.desc
# Make sure Rust is available.
- run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} rustavailable
# Configure kernel.
- run: cp ci/*.config linux/kernel/configs/
- run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} defconfig rfl-${{ matrix.arch }}.config rfl-rust.config
- if: matrix.config == 'defconfig+debug'
run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} rfl-debug.config
# Dump kernel configuration before the build and save it.
- run: |
cat ${{ env.OUTPUT_DIR }}.config
cp ${{ env.OUTPUT_DIR }}.config config-before
# Build.
- run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }}
# Check the kernel configuration did not change, just in case.
- run: diff -u config-before ${{ env.OUTPUT_DIR }}.config
# Make sure certain key configs were enabled.
- run: grep -F 'CONFIG_RUST=y' ${{ env.OUTPUT_DIR }}.config
# Report other data.
- run: |
ls -l \
${{ env.OUTPUT_DIR }}samples/rust/*.o \
${{ env.OUTPUT_DIR }}samples/rust/*.ko \
${{ env.OUTPUT_DIR }}rust/*.o \
${{ env.OUTPUT_DIR }}vmlinux \
${{ env.OUTPUT_DIR }}${{ env.IMAGE_PATH }}
ci/size.sh \
${{ env.OUTPUT_DIR }}samples/rust/*.o \
${{ env.OUTPUT_DIR }}samples/rust/*.ko \
${{ env.OUTPUT_DIR }}rust/*.o \
${{ env.OUTPUT_DIR }}vmlinux
# Check `.comment` section.
- run: |
readelf --string-dump .comment ${{ env.OUTPUT_DIR }}rust/core.o
objcopy --dump-section .comment=comment ${{ env.OUTPUT_DIR }}rust/core.o
grep --text "^.rustc version .* with libgccjit" comment
grep --text 'libgccjit' comment
grep --text 'GCC: ' comment
# Prepare image.
- run: ${{ env.OUTPUT_DIR }}usr/gen_init_cpio ci/qemu-initramfs.desc > qemu-initramfs.img
# Run in QEMU.
- run: |
qemu-system-${{ env.QEMU_ARCH }} \
${{ env.QEMU_ARGS }} \
-kernel ${{ env.OUTPUT_DIR }}${{ env.IMAGE_PATH }} \
-initrd qemu-initramfs.img \
-smp 2 \
-nographic \
-vga none \
-no-reboot \
| sed 's:\r$::' \
| tee qemu-stdout
# Check QEMU log output.
- run: |
grep '] rust_minimal: Rust minimal sample (init)$' qemu-stdout
grep '] rust_minimal: Am I built-in? false$' qemu-stdout
grep '] rust_minimal: My numbers are \[72, 108, 200]$' qemu-stdout
grep '] rust_minimal: Rust minimal sample (exit)$' qemu-stdout
- run: |
grep '] rust_print: Rust printing macros sample (init)$' qemu-stdout
grep '] rust_print: Emergency message (level 0) without args$' qemu-stdout
grep '] rust_print: Alert message (level 1) without args$' qemu-stdout
grep '] rust_print: Critical message (level 2) without args$' qemu-stdout
grep '] rust_print: Error message (level 3) without args$' qemu-stdout
grep '] rust_print: Warning message (level 4) without args$' qemu-stdout
grep '] rust_print: Notice message (level 5) without args$' qemu-stdout
grep '] rust_print: Info message (level 6) without args$' qemu-stdout
grep '] rust_print: A line that is continued without args$' qemu-stdout
grep '] rust_print: Emergency message (level 0) with args$' qemu-stdout
grep '] rust_print: Alert message (level 1) with args$' qemu-stdout
grep '] rust_print: Critical message (level 2) with args$' qemu-stdout
grep '] rust_print: Error message (level 3) with args$' qemu-stdout
grep '] rust_print: Warning message (level 4) with args$' qemu-stdout
grep '] rust_print: Notice message (level 5) with args$' qemu-stdout
grep '] rust_print: Info message (level 6) with args$' qemu-stdout
grep '] rust_print: A line that is continued with args$' qemu-stdout
- run: grep '] ok 1 rust_doctests_kernel$' qemu-stdout
- run: |
grep -i '\bpanic\b' qemu-stdout && exit 1
grep -i '\boops\b' qemu-stdout && exit 1
grep -i '\btaint\b' qemu-stdout && exit 1
grep -i '\bfault\b' qemu-stdout && exit 1
grep -i '\btrace\b' qemu-stdout && exit 1
grep -i '\bcorrupted\b' qemu-stdout && exit 1
grep -i '\bbug\b' qemu-stdout |
grep -Fv '" and report a bug' &&
exit 1
grep -i '\berror\b' qemu-stdout |
grep -Fv 'message (level 3)' |
grep -Fv 'regulatory.db' &&
exit 1
grep -i '\bwarning\b' qemu-stdout |
grep -Fv 'message (level 4)' &&
exit 1
exit 0
# Re-build with Clippy.
- run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} CLIPPY=1
# Generate Rust documentation.
- run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} rustdoc
# Check `#[test]`s.
- run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} rusttest
# Check formatting.
- run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} rustfmtcheck
# Test single targets.
- run: |
rm ${{ env.OUTPUT_DIR }}samples/rust/rust_minimal.o
make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} samples/rust/rust_minimal.o
file ${{ env.OUTPUT_DIR }}samples/rust/rust_minimal.o | grep -F 'ELF'
- run: |
make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} samples/rust/rust_minimal.rsi
grep -F '#![feature(prelude_import)]' ${{ env.OUTPUT_DIR }}samples/rust/rust_minimal.rsi
- run: |
make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} samples/rust/rust_minimal.s
grep -F '.text' ${{ env.OUTPUT_DIR }}samples/rust/rust_minimal.s
# Test Rust host programs.
- run: ${{ env.OUTPUT_DIR }}samples/rust/hostprogs/single | grep -F 'The number is 42.'