Skip to content

Commit cc104df

Browse files
committed
Add CI workflow to build and test with QEMU
Introduce GitHub Actions-based CI that builds the kernel using the GNU RISC-V toolchain and runs selected apps (e.g., cpubench) in QEMU. Results are extracted and posted to PRs. Toolchain setup, build, and QEMU test logic are modularized into scripts in .ci/. Features: - Support multiple apps per run - CI comments results on PR automatically - Timeout prevents hangs Limitations: - Currently GNU-only (LLVM WIP) - cpubench doesn't exit cleanly due to preemptive mode Fixes: #2 Supersedes: #11
1 parent 9679c50 commit cc104df

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

.ci/run-qemu-tests.sh

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/bin/bash
2+
set -e
3+
export CROSS_COMPILE=${CROSS_COMPILE:-riscv32-unknown-elf-}
4+
5+
# Check if at least one app is provided
6+
if [ $# -eq 0 ]; then
7+
echo "Usage: $0 <app1> [app2] [app3] ..."
8+
echo "Example: $0 hello echo cpubench"
9+
exit 1
10+
fi
11+
12+
APPS="$@"
13+
TIMEOUT=10
14+
15+
echo "[+] Will run apps: $APPS"
16+
echo ""
17+
18+
# Loop through each app
19+
for app in $APPS; do
20+
echo "=== Running $app ==="
21+
22+
# Build the app
23+
echo "[+] Building $app..."
24+
make clean >/dev/null 2>&1
25+
if ! make "$app" >/dev/null 2>&1; then
26+
echo "[!] Failed to build $app"
27+
echo ""
28+
continue
29+
fi
30+
31+
# Run in QEMU with timeout
32+
echo "[+] Running $app in QEMU (timeout: ${TIMEOUT}s)..."
33+
set +e
34+
timeout ${TIMEOUT}s qemu-system-riscv32 -nographic -machine virt -bios none -kernel build/image.elf
35+
exit_code=$?
36+
set -e
37+
38+
# Print result
39+
if [ $exit_code -eq 124 ]; then
40+
echo "[!] $app timed out"
41+
elif [ $exit_code -eq 0 ]; then
42+
echo "[✓] $app completed successfully"
43+
else
44+
echo "[!] $app failed with exit code $exit_code"
45+
fi
46+
echo ""
47+
done
48+
49+
echo "[+] All apps tested"

.ci/setup-toolchain.sh

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# Default to GNU if no toolchain specified
5+
TOOLCHAIN_TYPE=${1:-gnu}
6+
7+
TOOLCHAIN_REPO=https://github.com/riscv-collab/riscv-gnu-toolchain
8+
TOOLCHAIN_VERSION=2025.07.03
9+
TOOLCHAIN_OS=ubuntu-24.04
10+
11+
setup_gnu_toolchain() {
12+
echo "[+] Setting up GNU RISC-V toolchain..."
13+
14+
local URL="${TOOLCHAIN_REPO}/releases/download/${TOOLCHAIN_VERSION}/riscv32-elf-${TOOLCHAIN_OS}-gcc-nightly-${TOOLCHAIN_VERSION}-nightly.tar.xz"
15+
16+
echo "[+] Downloading RISC-V GNU toolchain..."
17+
wget -q "$URL"
18+
tar -xf "$(basename "$URL")"
19+
20+
echo "[+] Exporting GNU toolchain path..."
21+
echo "$PWD/riscv/bin" >> "$GITHUB_PATH"
22+
23+
# Set cross-compile prefix for GNU
24+
echo "CROSS_COMPILE=riscv32-unknown-elf-" >> "$GITHUB_ENV"
25+
echo "TOOLCHAIN_TYPE=gnu" >> "$GITHUB_ENV"
26+
}
27+
28+
setup_llvm_toolchain() {
29+
echo "[+] Setting up LLVM RISC-V toolchain..."
30+
31+
# upstream URL for LLVM toolchain
32+
local URL="${TOOLCHAIN_REPO}/releases/download/${TOOLCHAIN_VERSION}/riscv32-elf-${TOOLCHAIN_OS}-llvm-nightly-${TOOLCHAIN_VERSION}-nightly.tar.xz"
33+
34+
echo "[+] Downloading RISC-V LLVM toolchain..."
35+
wget -q "$URL"
36+
tar -xf "$(basename "$URL")"
37+
38+
echo "[+] Exporting LLVM toolchain path..."
39+
echo "$PWD/riscv/bin" >> "$GITHUB_PATH"
40+
41+
# Set cross-compile prefix for LLVM
42+
echo "CROSS_COMPILE=riscv32-unknown-elf-" >> "$GITHUB_ENV"
43+
echo "TOOLCHAIN_TYPE=llvm" >> "$GITHUB_ENV"
44+
echo "AR=llvm-ar" >> "$GITHUB_ENV"
45+
}
46+
47+
case "$TOOLCHAIN_TYPE" in
48+
"gnu")
49+
setup_gnu_toolchain
50+
;;
51+
"llvm")
52+
setup_llvm_toolchain
53+
;;
54+
*)
55+
echo "Error: Unknown toolchain type '$TOOLCHAIN_TYPE'"
56+
echo "Usage: $0 [gnu|llvm]"
57+
exit 1
58+
;;
59+
esac
60+
61+
echo "[+] Toolchain setup complete: $TOOLCHAIN_TYPE"

.github/workflows/ci.yml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
name: Linmo CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
basic-tests:
9+
runs-on: ubuntu-24.04
10+
name: Basic Tests
11+
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v4
15+
16+
- name: Install dependencies
17+
run: |
18+
sudo apt-get update
19+
sudo apt-get install -y build-essential qemu-system-riscv32 wget
20+
21+
- name: Setup GNU RISC-V Toolchain
22+
run: .ci/setup-toolchain.sh gnu
23+
24+
- name: Verify toolchain installation
25+
run: |
26+
riscv32-unknown-elf-gcc --version
27+
qemu-system-riscv32 --version
28+
env:
29+
CROSS_COMPILE: riscv32-unknown-elf-
30+
31+
- name: Build Kernel
32+
run: |
33+
make clean
34+
make
35+
env:
36+
CROSS_COMPILE: riscv32-unknown-elf-
37+
38+
- name: Run Basic Apps
39+
id: test
40+
run: |
41+
output=$(.ci/run-qemu-tests.sh cpubench test64)
42+
echo "TEST_OUTPUT<<EOF" >> $GITHUB_OUTPUT
43+
echo "$output" >> $GITHUB_OUTPUT
44+
echo "EOF" >> $GITHUB_OUTPUT
45+
46+
- name: Comment PR with results
47+
if: github.event_name == 'pull_request'
48+
uses: actions/github-script@v7
49+
with:
50+
script: |
51+
const output = `${{ steps.test.outputs.TEST_OUTPUT }}`;
52+
github.rest.issues.createComment({
53+
issue_number: context.issue.number,
54+
owner: context.repo.owner,
55+
repo: context.repo.repo,
56+
body: `## Linmo QEMU App Test Result\n\n\`\`\`\n${output}\n\`\`\`\n\n_This is an automated report from CI._`
57+
});

0 commit comments

Comments
 (0)