openpencil/.github/workflows/rust-multiplatform.yml
2026-05-31 17:30:30 +08:00

188 lines
7.6 KiB
YAML

name: Rust multi-platform build
# Builds the OpenPencil Rust workspace across all supported targets.
# Runs on every push/PR to verify the matrix stays green; release artifacts
# are produced by `rust-release.yml` on tag pushes.
on:
push:
branches: ['**']
paths:
- 'Cargo.toml'
- 'Cargo.lock'
- 'crates/**'
- 'vendor/jian/**'
- 'vendor/skia-safe-op/**'
- 'rust-toolchain.toml'
- 'deny.toml'
- '.github/workflows/rust-multiplatform.yml'
pull_request:
paths:
- 'Cargo.toml'
- 'Cargo.lock'
- 'crates/**'
- 'vendor/jian/**'
- 'vendor/skia-safe-op/**'
- '.github/workflows/rust-multiplatform.yml'
workflow_dispatch:
jobs:
desktop:
name: ${{ matrix.label }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- label: macos-aarch64
runner: macos-latest
target: aarch64-apple-darwin
cross: false
# macos-13 (Intel runners) deprecated; build x86_64-apple-darwin via
# cross-compile from Apple Silicon. cargo build/check run; no test
# since binary arch ≠ host arch.
- label: macos-x86_64
runner: macos-latest
target: x86_64-apple-darwin
cross: false
check_only: true
- label: linux-x86_64
runner: ubuntu-latest
target: x86_64-unknown-linux-gnu
cross: false
# Native ARM64 hosted runner — no `cross`. The cross 0.2.x aarch64
# image (Ubuntu 16.04 / GCC 5 / FreeType 2.6) is too old to link the
# modern skia that skia-bindings builds (missing COLR/variable-font
# FreeType symbols + libstdc++ ABI mismatch).
- label: linux-aarch64
runner: ubuntu-24.04-arm
target: aarch64-unknown-linux-gnu
cross: false
- label: windows-x86_64
runner: windows-latest
target: x86_64-pc-windows-msvc
cross: false
# Windows ARM64 — cargo cross-compile from x86_64 host (no Win11
# ARM hosted runner GA yet); cargo check only since binary arch
# ≠ host arch.
- label: windows-aarch64
runner: windows-latest
target: aarch64-pc-windows-msvc
cross: false
check_only: true
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: '1.94'
targets: ${{ matrix.target }}
components: rustfmt, clippy
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install Linux GL/EGL prereqs
if: runner.os == 'Linux' && matrix.cross == false
run: |
sudo apt-get update
sudo apt-get install -y \
libxkbcommon-dev libxkbcommon-x11-dev \
libwayland-dev libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev \
libegl1-mesa-dev libgles2-mesa-dev libgbm-dev mesa-utils \
libfreetype-dev libfontconfig1-dev fonts-noto-cjk \
xvfb
- name: Build (host)
if: matrix.cross == false && matrix.check_only != true
run: cargo build --workspace --target ${{ matrix.target }} --release
- name: Build examples (host, spec §1.2 acceptance #7)
if: matrix.cross == false && matrix.check_only != true
run: cargo build --examples --workspace --target ${{ matrix.target }} --release
- name: Check (cross-arch host, e.g. macos-x86_64 from Apple Silicon)
if: matrix.check_only == true
run: cargo check --workspace --target ${{ matrix.target }}
- name: Test (host, Linux)
if: matrix.cross == false && runner.os == 'Linux'
# Linux GPU smoke + gpu_chrome_stub_composition are now `#[ignore]`
# under LINUX_GPU_SKIA_LOADER_TBD (skia-safe Interface::new_native
# cannot load GL syms from EGL pbuffer + llvmpipe; needs
# `new_load_with(eglGetProcAddress)` loader, deferred to Step 1f or
# spec §3.1 mini-patch). All other tests run normally.
run: cargo test --workspace --target ${{ matrix.target }}
- name: Test (host, macOS / Windows)
if: matrix.cross == false && matrix.check_only != true && runner.os != 'Linux'
run: cargo test --workspace --target ${{ matrix.target }}
# Desktop binary artifact upload is intentionally not wired here yet.
# The real desktop binary lives in the `op-host-desktop` crate; a
# build + upload step can be added once release packaging is finalized.
wasm-web:
name: wasm32-unknown-unknown / op-host-web (compile guard)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: '1.94'
targets: wasm32-unknown-unknown
- uses: Swatinem/rust-cache@v2
with:
key: wasm32
# Step 1b §1.2 wasm32-clean compile guard — without `skia` feature this
# is a stub mount (validates host canvas, does not paint). The real
# render artifact uses the SAME wasm32-unknown-unknown target plus
# `--features skia` (post C-hard.2 lock-in 2026-05-09) and ships
# via a separate Phase A job once the CI-side C-hard pipeline
# (brew emscripten install + EMSDK + .wasm.a symlink hack +
# wasm-bindgen + wasm-opt) lands. Until then this job only proves
# the public surface compiles wasm32-clean.
- run: cargo build -p op-host-web --target wasm32-unknown-unknown --release --no-default-features --features web
# Artifact upload deliberately removed: the stub `.wasm` from this
# path would mislead downstream consumers into thinking the shell can
# render. Restore the upload step once the skia-enabled build runs on
# this CI target.
mobile-check:
name: ${{ matrix.label }} (cargo check only)
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
# iOS targets need Xcode SDK — macOS runner only.
- label: ios-aarch64
runner: macos-latest
target: aarch64-apple-ios
- label: ios-aarch64-sim
runner: macos-latest
target: aarch64-apple-ios-sim
# Android targets via NDK — Linux runner.
- label: android-aarch64
runner: ubuntu-latest
target: aarch64-linux-android
- label: android-x86_64
runner: ubuntu-latest
target: x86_64-linux-android
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: '1.94'
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: mobile-${{ matrix.target }}
# Step 1a spec §11 mobile invariants verify on iOS / Android cargo check:
# - op-editor-ui wasm32/ios/android-clean (no platform deps) — the
# widget facade / editor-UI composition crate.
# - op-host-native compiles on mobile targets with EaglProvider /
# AndroidEglProvider stubs (`unimplemented!("Step 1f")`); desktop GL
# stack (glutin / winit) is target-gated to desktop in Cargo.toml +
# GlutinProvider source is cfg-gated to desktop OS only. Real SDK
# linking and iOS/Android runtime is Step 1f.
- run: cargo check -p op-editor-ui --target ${{ matrix.target }}
- run: cargo check -p op-host-native --target ${{ matrix.target }}