|
| 1 | +on: |
| 2 | + schedule: |
| 3 | + - cron: '0 8 * * *' |
| 4 | + push: |
| 5 | + |
| 6 | +jobs: |
| 7 | + ci: |
| 8 | + runs-on: ubuntu-22.04 |
| 9 | + container: ghcr.io/rust-for-linux/ci |
| 10 | + |
| 11 | + timeout-minutes: 70 |
| 12 | + |
| 13 | + strategy: |
| 14 | + fail-fast: false |
| 15 | + matrix: |
| 16 | + tree: |
| 17 | + - rust-next |
| 18 | + # rust-fixes |
| 19 | + # rust-dev |
| 20 | + |
| 21 | + # next |
| 22 | + |
| 23 | + # stable/linux-6.7.y |
| 24 | + # stable-rc/linux-6.7.y |
| 25 | + |
| 26 | + # stable/linux-6.6.y |
| 27 | + # stable-rc/linux-6.6.y |
| 28 | + |
| 29 | + # stable/linux-6.1.y |
| 30 | + # stable-rc/linux-6.1.y |
| 31 | + |
| 32 | + arch: |
| 33 | + - x86_64 |
| 34 | + # arm64 |
| 35 | + |
| 36 | + toolchain: |
| 37 | + # llvm |
| 38 | + - rustc_codegen_gcc |
| 39 | + |
| 40 | + config: |
| 41 | + - defconfig |
| 42 | + - defconfig+debug |
| 43 | + |
| 44 | + output: |
| 45 | + - src |
| 46 | + # subdir |
| 47 | + # outside |
| 48 | + |
| 49 | + include: |
| 50 | + # # `arch: arm64` (with `rust-dev`). |
| 51 | + # - tree: rust-dev |
| 52 | + # arch: arm64 |
| 53 | + # toolchain: rustc_codegen_gcc |
| 54 | + # config: defconfig |
| 55 | + # output: src |
| 56 | + # |
| 57 | + # # `arch: arm64` (with `rust-dev` + `defconfig+debug`). |
| 58 | + # - tree: rust-dev |
| 59 | + # arch: arm64 |
| 60 | + # toolchain: rustc_codegen_gcc |
| 61 | + # config: defconfig+debug |
| 62 | + # output: src |
| 63 | + |
| 64 | + # `output: subdir`. |
| 65 | + - tree: rust-next |
| 66 | + arch: x86_64 |
| 67 | + toolchain: rustc_codegen_gcc |
| 68 | + config: defconfig |
| 69 | + output: subdir |
| 70 | + |
| 71 | + # `output: outside`. |
| 72 | + - tree: rust-next |
| 73 | + arch: x86_64 |
| 74 | + toolchain: rustc_codegen_gcc |
| 75 | + config: defconfig |
| 76 | + output: outside |
| 77 | + |
| 78 | + exclude: |
| 79 | + # Rust 1.71.1 (in Linux 6.6) had a bug: it generated `.eh_frame` with debug assertions enabled. |
| 80 | + - tree: stable/linux-6.6.y |
| 81 | + config: defconfig+debug |
| 82 | + |
| 83 | + # Rust 1.71.1 (in Linux 6.6) had a bug: it generated `.eh_frame` with debug assertions enabled. |
| 84 | + - tree: stable-rc/linux-6.6.y |
| 85 | + config: defconfig+debug |
| 86 | + |
| 87 | + steps: |
| 88 | + # Setup: variables. |
| 89 | + - run: echo "JOBS=-j$(($(nproc) + 1))" >> $GITHUB_ENV |
| 90 | + |
| 91 | + - if: matrix.arch == 'x86_64' |
| 92 | + run: | |
| 93 | + echo 'MAKE_ARCH=ARCH=x86_64' >> $GITHUB_ENV |
| 94 | + echo 'IMAGE_PATH=arch/x86/boot/bzImage' >> $GITHUB_ENV |
| 95 | + echo 'QEMU_ARCH=x86_64' >> $GITHUB_ENV |
| 96 | + echo 'QEMU_ARGS=-append console=ttyS0' >> $GITHUB_ENV |
| 97 | + - if: matrix.arch == 'arm64' |
| 98 | + run: | |
| 99 | + echo 'MAKE_ARCH=ARCH=arm64' >> $GITHUB_ENV |
| 100 | + echo 'MAKE_CROSS_COMPILE=CROSS_COMPILE=aarch64-linux-gnu-' >> $GITHUB_ENV |
| 101 | + echo 'IMAGE_PATH=arch/arm64/boot/Image.gz' >> $GITHUB_ENV |
| 102 | + echo 'QEMU_ARCH=aarch64' >> $GITHUB_ENV |
| 103 | + echo 'QEMU_ARGS=-machine virt' >> $GITHUB_ENV |
| 104 | +
|
| 105 | + - if: matrix.toolchain == 'llvm' |
| 106 | + run: echo 'MAKE_TOOLCHAIN=LLVM=1' >> $GITHUB_ENV |
| 107 | + |
| 108 | + - if: matrix.output == 'src' |
| 109 | + run: | |
| 110 | + echo 'OUTPUT_DIR=linux/' >> $GITHUB_ENV |
| 111 | + - if: matrix.output == 'subdir' |
| 112 | + run: | |
| 113 | + echo 'MAKE_OUTPUT=O=subdir' >> $GITHUB_ENV |
| 114 | + echo 'OUTPUT_DIR=linux/subdir/' >> $GITHUB_ENV |
| 115 | + - if: matrix.output == 'outside' |
| 116 | + run: | |
| 117 | + echo 'MAKE_OUTPUT=O=/outside' >> $GITHUB_ENV |
| 118 | + echo 'OUTPUT_DIR=/outside/' >> $GITHUB_ENV |
| 119 | +
|
| 120 | + # Setup: checkout Linux source tree. |
| 121 | + - if: startsWith(matrix.tree, 'rust-') |
| 122 | + run: git clone --depth 1 --branch ${{ matrix.tree }} https://github.com/Rust-for-Linux/linux.git linux |
| 123 | + - if: startsWith(matrix.tree, 'next') |
| 124 | + run: git clone --depth 1 https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git linux |
| 125 | + - if: startsWith(matrix.tree, 'stable/') |
| 126 | + run: git clone --depth 1 --branch $(echo ${{ matrix.tree }} | cut -d/ -f2-) https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git linux |
| 127 | + - if: startsWith(matrix.tree, 'stable-rc/') |
| 128 | + run: git clone --depth 1 --branch $(echo ${{ matrix.tree }} | cut -d/ -f2-) https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux |
| 129 | + |
| 130 | + - run: git -C linux show --no-patch |
| 131 | + |
| 132 | + # Setup: checkout CI tree. |
| 133 | + - uses: actions/checkout@v4 |
| 134 | + with: |
| 135 | + path: ci |
| 136 | + |
| 137 | + # Setup: Rust. |
| 138 | + - run: | |
| 139 | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- \ |
| 140 | + -y \ |
| 141 | + --no-modify-path \ |
| 142 | + --default-toolchain $(linux/scripts/min-tool-version.sh rustc) \ |
| 143 | + --profile minimal \ |
| 144 | + --component rust-src \ |
| 145 | + --component rustfmt \ |
| 146 | + --component clippy |
| 147 | + echo "$HOME/.cargo/bin" >> $GITHUB_PATH |
| 148 | +
|
| 149 | + # Setup: `rustc_codegen_gcc`. |
| 150 | + - if: matrix.toolchain == 'rustc_codegen_gcc' |
| 151 | + run: | |
| 152 | + apt-get -y --no-install-recommends purge cpp gcc |
| 153 | + curl --proto '=https' --tlsv1.2 -sSfLO https://github.com/antoyo/gcc/releases/download/master/gcc-13.deb |
| 154 | + dpkg -i gcc-13.deb |
| 155 | +
|
| 156 | + git clone --depth 1 --branch $(linux/scripts/min-tool-version.sh rustc) https://github.com/rust-lang/rust.git rust-repo |
| 157 | + # FIXME: 1.75.0 only: avoid `.eh_frame` error. |
| 158 | + git config --global user.email "[email protected]" |
| 159 | + git config --global user.name "Your Name" |
| 160 | + git -C rust-repo am ../ci/0001-Do-not-emit-.eh_frame-section-when-using-Cpanic-abor.patch |
| 161 | +
|
| 162 | + echo "MAKE_KRUSTFLAGS=KRUSTFLAGS=-Zcodegen-backend=$(pwd)/rust-repo/compiler/rustc_codegen_gcc/target/release/librustc_codegen_gcc.so" >> $GITHUB_ENV |
| 163 | +
|
| 164 | + cd rust-repo/compiler/rustc_codegen_gcc |
| 165 | + echo /usr/lib > gcc_path |
| 166 | + sed -i '/channel/d' rust-toolchain |
| 167 | + export RUSTC_BOOTSTRAP=1 |
| 168 | + ./y.sh prepare --only-libcore |
| 169 | + ./y.sh build --release --features master |
| 170 | +
|
| 171 | + # Setup: `bindgen`. |
| 172 | + # |
| 173 | + # The `bindgen` package name is only used for 6.1 LTS. |
| 174 | + - run: | |
| 175 | + cargo install --locked --version $(linux/scripts/min-tool-version.sh bindgen) bindgen-cli || |
| 176 | + cargo install --locked --version $(linux/scripts/min-tool-version.sh bindgen) bindgen |
| 177 | +
|
| 178 | + # Setup: `busybox`. |
| 179 | + - run: cp /root/busybox-${{ matrix.arch }} /root/busybox |
| 180 | + |
| 181 | + # Prepare build output folder. |
| 182 | + - if: matrix.output != 'src' |
| 183 | + run: | |
| 184 | + mkdir ${{ env.OUTPUT_DIR }} |
| 185 | + sed -i 's:linux/samples/rust/:${{ env.OUTPUT_DIR }}samples/rust/:' ci/qemu-initramfs.desc |
| 186 | +
|
| 187 | + # Make sure Rust is available. |
| 188 | + - run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} rustavailable |
| 189 | + |
| 190 | + # Configure kernel. |
| 191 | + - run: cp ci/*.config linux/kernel/configs/ |
| 192 | + |
| 193 | + - 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 |
| 194 | + |
| 195 | + - if: matrix.config == 'defconfig+debug' |
| 196 | + 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 |
| 197 | + |
| 198 | + # Dump kernel configuration before the build and save it. |
| 199 | + - run: | |
| 200 | + cat ${{ env.OUTPUT_DIR }}.config |
| 201 | + cp ${{ env.OUTPUT_DIR }}.config config-before |
| 202 | +
|
| 203 | + # Build. |
| 204 | + - run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} |
| 205 | + |
| 206 | + # Check the kernel configuration did not change, just in case. |
| 207 | + - run: diff -u config-before ${{ env.OUTPUT_DIR }}.config |
| 208 | + |
| 209 | + # Make sure certain key configs were enabled. |
| 210 | + - run: | |
| 211 | + grep -F 'CONFIG_RUST=y' ${{ env.OUTPUT_DIR }}.config |
| 212 | + grep -F 'CONFIG_WERROR=y' ${{ env.OUTPUT_DIR }}.config |
| 213 | +
|
| 214 | + # Prepare image. |
| 215 | + - run: ${{ env.OUTPUT_DIR }}usr/gen_init_cpio ci/qemu-initramfs.desc > qemu-initramfs.img |
| 216 | + |
| 217 | + # Run in QEMU. |
| 218 | + - run: | |
| 219 | + qemu-system-${{ env.QEMU_ARCH }} \ |
| 220 | + ${{ env.QEMU_ARGS }} \ |
| 221 | + -kernel ${{ env.OUTPUT_DIR }}${{ env.IMAGE_PATH }} \ |
| 222 | + -initrd qemu-initramfs.img \ |
| 223 | + -smp 2 \ |
| 224 | + -nographic \ |
| 225 | + -vga none \ |
| 226 | + -no-reboot \ |
| 227 | + | sed 's:\r$::' \ |
| 228 | + | tee qemu-stdout |
| 229 | +
|
| 230 | + # Report other data. |
| 231 | + - run: | |
| 232 | + ls -l |
| 233 | +
|
| 234 | + ls -l \ |
| 235 | + ${{ env.OUTPUT_DIR }}samples/rust/*.o \ |
| 236 | + ${{ env.OUTPUT_DIR }}samples/rust/*.ko \ |
| 237 | + ${{ env.OUTPUT_DIR }}rust/*.o \ |
| 238 | + ${{ env.OUTPUT_DIR }}vmlinux \ |
| 239 | + ${{ env.OUTPUT_DIR }}${{ env.IMAGE_PATH }} |
| 240 | +
|
| 241 | + ci/size.sh \ |
| 242 | + ${{ env.OUTPUT_DIR }}samples/rust/*.o \ |
| 243 | + ${{ env.OUTPUT_DIR }}samples/rust/*.ko \ |
| 244 | + ${{ env.OUTPUT_DIR }}rust/*.o \ |
| 245 | + ${{ env.OUTPUT_DIR }}vmlinux |
| 246 | +
|
| 247 | + # Check `.comment` section. |
| 248 | + - if: matrix.toolchain == 'llvm' |
| 249 | + run: | |
| 250 | + if [ $(linux/scripts/min-tool-version.sh rustc | cut -d'.' -f2) -ge 73 ]; then |
| 251 | + llvm-readelf --string-dump .comment ${{ env.OUTPUT_DIR }}rust/core.o |
| 252 | + llvm-objcopy --dump-section .comment=comment ${{ env.OUTPUT_DIR }}rust/core.o |
| 253 | + grep --text "^.rustc version $(linux/scripts/min-tool-version.sh rustc)" comment |
| 254 | + else |
| 255 | + echo 'Skipping since `rustc` < 1.73.0.' |
| 256 | + fi |
| 257 | + - if: matrix.toolchain == 'rustc_codegen_gcc' |
| 258 | + run: | |
| 259 | + llvm-readelf --string-dump .comment ${{ env.OUTPUT_DIR }}rust/core.o |
| 260 | + llvm-objcopy --dump-section .comment=comment ${{ env.OUTPUT_DIR }}rust/core.o |
| 261 | + # TODO: starting with Rust 1.76.0, we should check for the improved `.comment` section. |
| 262 | + grep --text '^.GCC: ' comment |
| 263 | +
|
| 264 | + # Check QEMU log output. |
| 265 | + - run: | |
| 266 | + grep '] rust_minimal: Rust minimal sample (init)$' qemu-stdout |
| 267 | + grep '] rust_minimal: Am I built-in? false$' qemu-stdout |
| 268 | + grep '] rust_minimal: My numbers are \[72, 108, 200]$' qemu-stdout |
| 269 | + grep '] rust_minimal: Rust minimal sample (exit)$' qemu-stdout |
| 270 | +
|
| 271 | + # Linux 6.1 does not have `rust_print`. |
| 272 | + - if: ${{ ! contains(matrix.tree, '6.1') }} |
| 273 | + run: | |
| 274 | + grep '] rust_print: Rust printing macros sample (init)$' qemu-stdout |
| 275 | +
|
| 276 | + grep '] rust_print: Emergency message (level 0) without args$' qemu-stdout |
| 277 | + grep '] rust_print: Alert message (level 1) without args$' qemu-stdout |
| 278 | + grep '] rust_print: Critical message (level 2) without args$' qemu-stdout |
| 279 | + grep '] rust_print: Error message (level 3) without args$' qemu-stdout |
| 280 | + grep '] rust_print: Warning message (level 4) without args$' qemu-stdout |
| 281 | + grep '] rust_print: Notice message (level 5) without args$' qemu-stdout |
| 282 | + grep '] rust_print: Info message (level 6) without args$' qemu-stdout |
| 283 | + grep '] rust_print: A line that is continued without args$' qemu-stdout |
| 284 | +
|
| 285 | + grep '] rust_print: Emergency message (level 0) with args$' qemu-stdout |
| 286 | + grep '] rust_print: Alert message (level 1) with args$' qemu-stdout |
| 287 | + grep '] rust_print: Critical message (level 2) with args$' qemu-stdout |
| 288 | + grep '] rust_print: Error message (level 3) with args$' qemu-stdout |
| 289 | + grep '] rust_print: Warning message (level 4) with args$' qemu-stdout |
| 290 | + grep '] rust_print: Notice message (level 5) with args$' qemu-stdout |
| 291 | + grep '] rust_print: Info message (level 6) with args$' qemu-stdout |
| 292 | + grep '] rust_print: A line that is continued with args$' qemu-stdout |
| 293 | +
|
| 294 | + # Linux 6.1 does not have KUnit `rustdoc` tests. |
| 295 | + - if: ${{ matrix.config == 'defconfig+debug' && ! contains(matrix.tree, '6.1') }} |
| 296 | + run: grep '] ok 1 rust_doctests_kernel$' qemu-stdout |
| 297 | + |
| 298 | + - run: | |
| 299 | + grep -i '\bpanic\b' qemu-stdout && exit 1 |
| 300 | + grep -i '\boops\b' qemu-stdout && exit 1 |
| 301 | + grep -i '\btaint\b' qemu-stdout && exit 1 |
| 302 | + grep -i '\bfault\b' qemu-stdout && exit 1 |
| 303 | + grep -i '\btrace\b' qemu-stdout && exit 1 |
| 304 | + grep -i '\bcorrupted\b' qemu-stdout && exit 1 |
| 305 | +
|
| 306 | + grep -i '\bbug\b' qemu-stdout | |
| 307 | + grep -Fv '" and report a bug' && |
| 308 | + exit 1 |
| 309 | +
|
| 310 | + grep -i '\berror\b' qemu-stdout | |
| 311 | + grep -Fv 'message (level 3)' | |
| 312 | + grep -Fv 'regulatory.db' && |
| 313 | + exit 1 |
| 314 | +
|
| 315 | + grep -i '\bwarning\b' qemu-stdout | |
| 316 | + grep -Fv 'message (level 4)' && |
| 317 | + exit 1 |
| 318 | +
|
| 319 | + exit 0 |
| 320 | +
|
| 321 | + # Re-build with Clippy. |
| 322 | + - run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} CLIPPY=1 |
| 323 | + |
| 324 | + # Generate Rust documentation. |
| 325 | + - run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} rustdoc |
| 326 | + |
| 327 | + # Check `#[test]`s. |
| 328 | + - run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} rusttest |
| 329 | + |
| 330 | + # Check formatting. |
| 331 | + - run: make -C linux ${{ env.MAKE_ARCH }} ${{ env.MAKE_CROSS_COMPILE }} ${{ env.MAKE_TOOLCHAIN }} ${{ env.MAKE_OUTPUT }} ${{ env.MAKE_KRUSTFLAGS }} ${{ env.JOBS }} rustfmtcheck |
| 332 | + |
| 333 | + # Test single targets. |
| 334 | + - run: | |
| 335 | + rm ${{ env.OUTPUT_DIR }}samples/rust/rust_minimal.o |
| 336 | + 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 |
| 337 | + file ${{ env.OUTPUT_DIR }}samples/rust/rust_minimal.o | grep -F 'ELF' |
| 338 | +
|
| 339 | + # Rust 1.71.1 (in Linux 6.6) had a bug: it does not generate dependency files. |
| 340 | + - if: ${{ ! contains(matrix.tree, '6.6') }} |
| 341 | + run: | |
| 342 | + 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 |
| 343 | + grep -F '#![feature(prelude_import)]' ${{ env.OUTPUT_DIR }}samples/rust/rust_minimal.rsi |
| 344 | +
|
| 345 | + - run: | |
| 346 | + 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 |
| 347 | + grep -F '.text' ${{ env.OUTPUT_DIR }}samples/rust/rust_minimal.s |
| 348 | +
|
| 349 | + - if: matrix.toolchain == 'llvm' |
| 350 | + run: | |
| 351 | + 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.ll |
| 352 | + grep -F '; ModuleID' ${{ env.OUTPUT_DIR }}samples/rust/rust_minimal.ll |
| 353 | +
|
| 354 | + # Test Rust host programs. |
| 355 | + - run: ${{ env.OUTPUT_DIR }}samples/rust/hostprogs/single | grep -F 'The number is 42.' |
0 commit comments