Skip to content

Modernize ProgramLoader and unify program loading pipeline #367

Modernize ProgramLoader and unify program loading pipeline

Modernize ProgramLoader and unify program loading pipeline #367

Workflow file for this run

---
name: Multi-Distro Build (CMake)
on:
push:
branches: [master]
paths-ignore:
- '**.md'
- '.markdownlint.json'
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [master, develop]
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
jobs:
# 1. Ubuntu All Frontends (SDL3, SDL2, SDL1, TUI, Headless)
ubuntu-all-frontends:
name: Ubuntu 24.04 (All Frontends)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake ninja-build imagemagick libzip-dev \
libcurl4-openssl-dev zlib1g-dev git libxkbcommon-dev libz3-dev \
libsdl2-dev libsdl1.2-dev libsdl-image1.2-dev libpulse-dev libasound2-dev ccache gh
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-ubuntu-all
- name: Setup SDL3
uses: libsdl-org/setup-sdl@main
id: sdl
with:
version: 3-latest
version-sdl-image: 3-latest
install-linux-dependencies: true
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DFRONTEND=all \
-DCMAKE_PREFIX_PATH="${{ steps.sdl.outputs.prefix }}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
- name: Build
run: cmake --build build -j$(nproc)
- name: Test
env:
SDL_VIDEODRIVER: dummy
SDL_VIDEO_DRIVER: dummy
SDL_AUDIODRIVER: dummy
SDL_AUDIO_DRIVER: dummy
run: ctest --test-dir build -j$(nproc) --output-on-failure
- name: Install
run: sudo cmake --install build
# 2. Multi-Distro Matrix (Fedora, Arch Linux, Debian / Pi OS x86)
distro-matrix:
name: ${{ matrix.name }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: Fedora Latest (SDL3)
image: fedora:latest
setup: |
dnf install -y gcc-c++ cmake ninja-build ImageMagick libzip-devel \
SDL3-devel SDL3_image-devel libcurl-devel zlib-devel git z3-devel curl ccache nodejs \
perl-IO-Compress
frontend: sdl3
- name: Arch Linux Rolling (SDL3)
image: archlinux:latest
setup: |
pacman -Syu --noconfirm
pacman -S --noconfirm base-devel cmake ninja imagemagick libzip \
sdl3 sdl3_image libcurl-gnutls zlib git z3 curl ccache nodejs
frontend: sdl3
- name: Debian 12 / Pi OS x86 (SDL2)
image: debian:bookworm-slim
setup: |
apt-get update
apt-get install -y g++ cmake ninja-build imagemagick libzip-dev \
libcurl4-openssl-dev zlib1g-dev git libxkbcommon-dev libz3-dev \
libsdl2-dev curl ccache nodejs
frontend: sdl2
container:
image: ${{ matrix.image }}
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: ${{ matrix.setup }}
- name: Cache ccache
uses: actions/cache@v4
with:
path: |
~/.cache/ccache
~/.ccache
key: ccache-${{ matrix.name }}-${{ github.sha }}
restore-keys: |
ccache-${{ matrix.name }}-
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DFRONTEND=${{ matrix.frontend }} \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
- name: Build
run: cmake --build build -j$(nproc)
- name: Test
env:
SDL_VIDEODRIVER: dummy
SDL_VIDEO_DRIVER: dummy
SDL_AUDIODRIVER: dummy
SDL_AUDIO_DRIVER: dummy
run: ctest --test-dir build -j$(nproc) --output-on-failure
- name: Install
run: cmake --install build
# 3. Native ARM64 (Ubuntu / Raspberry Pi OS 64-bit Compatible)
rpi-arm64:
name: Native ARM64 (Ubuntu / Pi OS 64-bit)
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake ninja-build imagemagick libzip-dev \
libcurl4-openssl-dev zlib1g-dev git libxkbcommon-dev libz3-dev ccache
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-arm64
- name: Setup SDL3
uses: libsdl-org/setup-sdl@main
id: sdl
with:
version: 3-latest
version-sdl-image: 3-latest
install-linux-dependencies: true
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DFRONTEND=sdl3 \
-DCMAKE_PREFIX_PATH="${{ steps.sdl.outputs.prefix }}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
- name: Build
run: cmake --build build -j$(nproc)
- name: Test
env:
SDL_VIDEODRIVER: dummy
SDL_VIDEO_DRIVER: dummy
SDL_AUDIODRIVER: dummy
SDL_AUDIO_DRIVER: dummy
run: ctest --test-dir build -j$(nproc) --output-on-failure
- name: Install
run: sudo cmake --install build
# 4. Sanitizers (ASAN/UBSAN - All Frontends)
sanitizers-build:
name: Sanitizers (All Frontends + ASAN/UBSAN)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake ninja-build imagemagick libzip-dev \
libcurl4-openssl-dev zlib1g-dev git libxkbcommon-dev libz3-dev \
libsdl2-dev libsdl1.2-dev libsdl-image1.2-dev libpulse-dev libasound2-dev ccache gh
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-sanitizers
- name: Setup SDL3
uses: libsdl-org/setup-sdl@main
id: sdl
with:
version: 3-latest
version-sdl-image: 3-latest
install-linux-dependencies: true
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DFRONTEND=all \
-DENABLE_ASAN=ON \
-DENABLE_UBSAN=ON \
-DCMAKE_PREFIX_PATH="${{ steps.sdl.outputs.prefix }}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
- name: Build
run: cmake --build build -j$(nproc)
- name: Test
env:
ASAN_OPTIONS: "detect_leaks=1"
UBSAN_OPTIONS: "print_stacktrace=1"
SDL_VIDEODRIVER: dummy
SDL_VIDEO_DRIVER: dummy
SDL_AUDIODRIVER: dummy
SDL_AUDIO_DRIVER: dummy
run: ctest --test-dir build -j$(nproc) --output-on-failure
# 5. Static Analysis (clang-tidy)
clang-tidy-check:
name: Static Analysis (clang-tidy)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake ninja-build clang-tidy imagemagick \
libzip-dev libcurl4-openssl-dev zlib1g-dev git libxkbcommon-dev libz3-dev \
libsdl2-dev libsdl1.2-dev libsdl-image1.2-dev libpulse-dev libasound2-dev ccache gh
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-clang-tidy
- name: Setup SDL3
uses: libsdl-org/setup-sdl@main
id: sdl
with:
version: 3-latest
version-sdl-image: 3-latest
install-linux-dependencies: true
- name: Configure
run: |
cmake -B build -G Ninja \
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON \
-DFRONTEND=all \
-DBUILD_TESTING=OFF \
-DCMAKE_PREFIX_PATH="${{ steps.sdl.outputs.prefix }}" \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
cmake --build build --target generate_xpms
jq 'unique_by(.file)' build/compile_commands.json > build/compile_commands.json.tmp && mv build/compile_commands.json.tmp build/compile_commands.json
- name: Build & Analyze
run: |
run-clang-tidy -p build -j$(nproc) -quiet "src/.*"
# 6. Fuzzing Smoke Test (libFuzzer + ASan/UBSan)
fuzz-smoke:
name: Fuzzing Smoke Test (Ubuntu 24.04 + Clang + libFuzzer)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y clang cmake ninja-build imagemagick libzip-dev \
libcurl4-openssl-dev zlib1g-dev git libxkbcommon-dev libz3-dev ccache
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-fuzz
- name: Restore Fuzzing Corpus Cache
uses: actions/cache@v4
with:
path: tests/fuzz/corpus
key: ${{ runner.os }}-fuzz-corpus-${{ github.sha }}
restore-keys: |
${{ runner.os }}-fuzz-corpus-
- name: Configure & Build
run: |
cmake -B build-fuzz -G Ninja \
-DCMAKE_C_COMPILER=clang \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DFRONTEND=headless \
-DENABLE_FUZZING=ON \
-DBUILD_TESTING=ON \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
cmake --build build-fuzz -j$(nproc)
- name: Run Fuzz Tests
run: |
ctest --test-dir build-fuzz -L fuzz --output-on-failure
- name: Minimize Corpus
if: always()
run: |
for target in memory snapshot disk-loader image-container disk-controller disk-adapter speaker audio-mixer mockingboard ay8910 via6522; do
if [ -d "tests/fuzz/corpus/${target}" ]; then
mkdir -p "tests/fuzz/corpus/${target}-min"
./build-fuzz/fuzz-${target} -merge=1 "tests/fuzz/corpus/${target}-min" "tests/fuzz/corpus/${target}" || true
rm -rf "tests/fuzz/corpus/${target}"
mv "tests/fuzz/corpus/${target}-min" "tests/fuzz/corpus/${target}"
fi
done
# 7. Shared Peripherals (Headless + Plugin Loader Smoke Test)
shared-peripherals:
name: Shared Peripherals (Headless Plugin Loader)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake ninja-build imagemagick libzip-dev \
libcurl4-openssl-dev zlib1g-dev git libxkbcommon-dev libz3-dev ccache
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-shared-peripherals
- name: Configure
run: |
cmake -B build-shared -G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DFRONTEND=headless \
-DBUILD_SHARED_PERIPHERALS=ON \
-DBUILD_TESTING=ON \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
- name: Build
run: cmake --build build-shared -j$(nproc)
- name: Test
run: ctest --test-dir build-shared -j$(nproc) --output-on-failure
- name: Assert Hardware Count
run: |
count=$(./build-shared/linapple --list-hardware | grep -c '^- ')
echo "Detected peripheral count: $count"
if [ "$count" -ne 10 ]; then
echo "Expected 10 peripherals, but got $count"
exit 1
fi
- name: Assert No Plugin Carries Compression
run: |
for plugin in build-shared/*.so; do
echo "== $plugin"
! ldd "$plugin" | grep -E 'libz\.so|libzip\.so'
done
# 8. No Disk Peripherals (Headless, both image-opening cards off)
no-disk-peripherals:
name: No Disk Peripherals (Headless, No Compression)
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Install Dependencies
run: |
sudo apt-get update
sudo apt-get install -y g++ cmake ninja-build imagemagick libzip-dev \
libcurl4-openssl-dev zlib1g-dev git libxkbcommon-dev libz3-dev ccache
- name: Setup ccache
uses: hendrikmuhs/ccache-action@v1.2
with:
key: ${{ runner.os }}-no-disk-peripherals
- name: Configure
run: |
cmake -B build-nodisk -G Ninja \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DFRONTEND=headless \
-DENABLE_PERIPHERAL_DISK=OFF \
-DENABLE_PERIPHERAL_HARDDISK=OFF \
-DBUILD_TESTING=ON \
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
- name: Build
run: cmake --build build-nodisk -j$(nproc)
- name: Test
run: ctest --test-dir build-nodisk -j$(nproc) --output-on-failure
- name: Assert No Compression Is Configured or Linked
run: |
! grep -E '^(ZLIB_|LIBZIP_|pkgcfg_lib_LIBZIP)' build-nodisk/CMakeCache.txt
ldd build-nodisk/linapple
! ldd build-nodisk/linapple | grep -E 'libz\.so|libzip\.so'
# 9. CI Gate (All Checks Passed)
ci-gate:
name: CI Status Gate
if: always()
needs:
- ubuntu-all-frontends
- distro-matrix
- rpi-arm64
- sanitizers-build
- clang-tidy-check
- fuzz-smoke
- shared-peripherals
- no-disk-peripherals
runs-on: ubuntu-latest
steps:
- name: Verify all required jobs passed
run: |
echo "Evaluating CI job statuses..."
passed=true
for result in "${{ needs.ubuntu-all-frontends.result }}" \
"${{ needs.distro-matrix.result }}" \
"${{ needs.rpi-arm64.result }}" \
"${{ needs.sanitizers-build.result }}" \
"${{ needs.clang-tidy-check.result }}" \
"${{ needs.fuzz-smoke.result }}" \
"${{ needs.shared-peripherals.result }}" \
"${{ needs.no-disk-peripherals.result }}"; do
echo "Job result: $result"
if [ "$result" != "success" ]; then
passed=false
fi
done
if [ "$passed" = false ]; then
echo "Error: One or more required CI jobs failed or were cancelled."
exit 1
fi
echo "All required CI jobs succeeded."