ci/cd: Windows goes vcpkg manifest + MSVC on the VS 2026 runner

The MinGW path kept fighting the environment (the GitHub image's
MSVC INCLUDE/LIB poison the GNU compiles; ocio-sys' fork then
dragged the MSVC-only headers into g++ and died on vcruntime.h).
The Windows jobs on both workflows now:

- run on warp-windows-2025-vs2026-x64-16x (preinstalled VS 2026)
  with the stable MSVC Rust toolchain;
- install dependencies through vcpkg MANIFEST mode: vcpkg.json at
  the repo root carries FFmpeg with every free codec + hwaccel
  (mirroring build-ffmpeg.sh's configure), pkgconf and librsvg;
  the vcpkg_installed tree plus the binary-cache archives are
  cached on the manifest hash with save-always;
- build OCIO bundled (ocio-sys' vendored sources are what MSVC
  wants — the MSYS2 package was the workaround, not the
  preference), so OCIO_RS_NO_MSVC_INCLUDES is gone;
- ship the vcpkg runtime DLLs next to the binaries in the NSIS
  installer with a static-CRT release build (no vcruntime DLLs),
  replacing the ntldd-based MSYS2 bundling.

FFmpeg version pinning via builtin-baseline is a documented
follow-up: the Configure step logs vcpkg list so the first green
run reports the resolved versions. docs/build.md keeps the MSYS2
flow as the local alternative and points at the CI path.
This commit is contained in:
2026-09-11 15:59:39 +08:00
parent 80e6b8bb6e
commit faebc79c31
6 changed files with 131 additions and 152 deletions
+1
View File
@@ -5,4 +5,5 @@ self-hosted-runner:
labels: labels:
- warp-ubuntu-latest-x64-8x - warp-ubuntu-latest-x64-8x
- warp-windows-latest-x64-16x - warp-windows-latest-x64-16x
- warp-windows-2025-vs2026-x64-16x
- warp-macos-26-arm64-6x - warp-macos-26-arm64-6x
+43 -66
View File
@@ -320,11 +320,7 @@ jobs:
# ------------------------------------------------------------------ # ------------------------------------------------------------------
windows: windows:
name: Windows installer (NSIS) name: Windows installer (NSIS)
runs-on: warp-windows-latest-x64-16x runs-on: warp-windows-2025-vs2026-x64-16x
defaults:
run:
shell: msys2 {0}
steps: steps:
- name: Checkout - name: Checkout
@@ -332,49 +328,42 @@ jobs:
with: with:
submodules: true submodules: true
- name: Install Rust (stable) - name: Install Rust (stable, MSVC)
uses: dtolnay/rust-toolchain@stable uses: dtolnay/rust-toolchain@stable
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with: with:
msystem: UCRT64 # The Windows build is MSVC-ABI (the runner carries VS 2026):
update: true # vcpkg's FFmpeg and the vendored OCIO build both want it.
# MSYS2's own Rust targets x86_64-pc-windows-gnu by default — toolchain: stable-x86_64-pc-windows-msvc
# the Windows build is GNU-target (the MSVC linker rejects the
# Unix-style link args the build scripts emit).
install: >-
git
mingw-w64-ucrt-x86_64-gcc
mingw-w64-ucrt-x86_64-rust
- name: Install system dependencies # vcpkg.json at the repo root pins the dependency set (FFmpeg with
run: | # every free codec + hwaccel, pkgconf, librsvg); the resolved tree
bash tooling/install-deps.sh # lands in vcpkg_installed/ and is keyed on the manifest. The
pacman -S --needed --noconfirm \ # binary-cache archives dir makes a manifest bump rebuild cheap.
mingw-w64-ucrt-x86_64-cmake \ - name: Cache vcpkg artifacts
mingw-w64-ucrt-x86_64-opencolorio \ uses: actions/cache@v4
mingw-w64-ucrt-x86_64-librsvg \ with:
mingw-w64-ucrt-x86_64-ffnvcodec-headers \ path: |
mingw-w64-ucrt-x86_64-pkgconf vcpkg_installed
~/AppData/Local/vcpkg/archives
key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json') }}
save-always: true
- name: Install dependencies (vcpkg manifest)
run: vcpkg install --triplet x64-windows
- name: Configure build environment - name: Configure build environment
run: | run: |
# System OCIO (MSYS2, the exact 2.5.2 the bridge targets); $prefix = "$env:GITHUB_WORKSPACE\vcpkg_installed\x64-windows"
# tooling/ocio-env.sh links it STATICALLY when the package ships "FFMPEG_DIR=$prefix" >> $env:GITHUB_ENV
# libOpenColorIO.a, dynamically otherwise (the DLL bundling step "PKG_CONFIG_PATH=$prefix\lib\pkgconfig" >> $env:GITHUB_ENV
# below then still applies). "$prefix\tools\pkgconf" >> $env:GITHUB_PATH
bash tooling/ocio-env.sh >> "$GITHUB_ENV" # Bundled OCIO: ocio-sys' vendored sources build with the MSVC
# ocio-sys is the GIT fork (Mike-Solar/ocio-rs main, pinned in # toolchain (what they need — the MSYS2 package was the
# the root manifest): its build.rs already carries the # workaround, not the preference), so no OCIO_INSTALL_DIR and
# fork's GNU-toolchain fix, so NO crate-unpack/glob patch step # no OCIO_RS_NO_MSVC_INCLUDES anywhere.
# applies here. The old code unpacked `ocio-sys-0.2.1.crate` "OCIO_RS_ENABLE_REAL=1" >> $env:GITHUB_ENV
# from the registry cache — impossible for a git dependency "OCIO_RS_LINK=static" >> $env:GITHUB_ENV
# (no .crate archive; git sources land under vcpkg list
# registry/src/git/<hash>), hence the
# "ls .../ocio-sys-0.2.1/build.rs: No such file" Windows CI
# failure.
echo "OCIO_RS_NO_MSVC_INCLUDES=1" >> "$GITHUB_ENV"
- name: Cache cargo artifacts - name: Cache cargo artifacts
uses: Swatinem/rust-cache@v2 uses: Swatinem/rust-cache@v2
@@ -382,42 +371,30 @@ jobs:
shared-key: oak-workspace shared-key: oak-workspace
cache-on-failure: true cache-on-failure: true
- name: Cache project FFmpeg
uses: actions/cache@v4
with:
path: .cache/ffmpeg
key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
- name: Build project FFmpeg (static, GPL + free codecs + hwaccel)
run: |
bash tooling/ffmpeg/build-ffmpeg.sh
echo "FFMPEG_DIR=$(cygpath -m "$PWD/.cache/ffmpeg")" >> "$GITHUB_ENV"
- name: Install cargo-packager - name: Install cargo-packager
run: cargo install cargo-packager --locked run: cargo install cargo-packager --locked
- name: Generate app icon (PNG from Oak_Icon.svg) - name: Generate app icon (PNG from Oak_Icon.svg)
run: | run: |
mkdir -p icons New-Item -ItemType Directory -Force icons | Out-Null
rsvg-convert -w 512 -h 512 Oak_Icon.svg -o icons/icon.png & "vcpkg_installed\x64-windows\tools\librsvg\rsvg-convert.exe" -w 512 -h 512 Oak_Icon.svg -o icons/icon.png
- name: Build (release) - name: Build (release)
run: | run: |
# Clear the job-hook-injected MSVC INCLUDE/LIB before the GNU # Static CRT: the installer then needs no vcruntime DLLs (the
# build (they poison the MinGW compiles with MSVC SDK headers). # vcpkg DLLs below are the only runtime pieces to bundle).
unset INCLUDE LIB $env:RUSTFLAGS = "-C target-feature=+crt-static"
cargo build --release --locked cargo build --release --locked
# Collect the MSYS2 runtime DLLs (libstdc++/libgcc/OpenColorIO/...) # The vcpkg runtime DLLs (avcodec/avformat/... and the codec libs)
# into target/pkg/win-dlls; the packager `resources` glob then # ship next to the executables: copy them into target/pkg/win-dlls,
# installs them next to the executables. # which the packager `resources` glob installs alongside (the MSVC
# CRT itself is covered by the toolchain's static linking story;
# OCIO is bundled statically).
- name: Bundle runtime DLLs - name: Bundle runtime DLLs
run: | run: |
unset INCLUDE LIB New-Item -ItemType Directory -Force target/pkg/win-dlls | Out-Null
pacman -S --needed --noconfirm mingw-w64-ucrt-x86_64-ntldd Copy-Item "vcpkg_installed\x64-windows\bin\*.dll" target/pkg/win-dlls/
tooling/package/bundle-dylibs-windows.sh target/pkg/win-dlls \
target/release/oak-editor.exe target/release/oak-cli.exe \
target/release/oak-worker.exe
- name: Package (NSIS) - name: Package (NSIS)
run: cargo packager --release --formats nsis run: cargo packager --release --formats nsis
+43 -86
View File
@@ -82,6 +82,7 @@ jobs:
with: with:
path: .cache/ffmpeg path: .cache/ffmpeg
key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }} key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
save-always: true
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# Project FFmpeg (script + FFMPEG_DIR; see docs/build.md) # Project FFmpeg (script + FFMPEG_DIR; see docs/build.md)
@@ -199,14 +200,7 @@ jobs:
windows: windows:
name: Build & test (Windows) name: Build & test (Windows)
runs-on: warp-windows-latest-x64-16x runs-on: warp-windows-2025-vs2026-x64-16x
env:
# The build needs the UCRT64 environment (mingw-w64-ucrt-x86_64-*
# toolchain), not the base MSYS one.
MSYSTEM: UCRT64
defaults:
run:
shell: msys2 {0}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -215,59 +209,51 @@ jobs:
# their own repo and build as path dependencies of oakapp. # their own repo and build as path dependencies of oakapp.
submodules: true submodules: true
- name: Setup MSYS2 - name: Install Rust (stable, MSVC)
uses: msys2/setup-msys2@v2 uses: dtolnay/rust-toolchain@stable
with: with:
msystem: UCRT64 # The Windows build is MSVC-ABI (the runner carries VS 2026):
update: true # vcpkg's FFmpeg and the vendored OCIO build both want it.
# MSYS2's own Rust targets x86_64-pc-windows-gnu by default — toolchain: stable-x86_64-pc-windows-msvc
# the Windows build is GNU-target (the MSVC linker rejects the
# Unix-style link args the build scripts emit).
install: >-
git
mingw-w64-ucrt-x86_64-gcc
mingw-w64-ucrt-x86_64-rust
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# System dependencies # vcpkg (manifest mode) + caches
# ------------------------------------------------------------------ # ------------------------------------------------------------------
- name: Install system dependencies # vcpkg.json at the repo root pins the dependency set (FFmpeg with
run: | # every free codec + hwaccel, pkgconf, librsvg); the resolved tree
bash ./tooling/install-deps.sh # lands in vcpkg_installed/ and is keyed on the manifest. The
pacman -S --needed --noconfirm \ # binary-cache archives dir makes a manifest bump rebuild cheap.
mingw-w64-ucrt-x86_64-cmake \ - name: Cache vcpkg artifacts
mingw-w64-ucrt-x86_64-opencolorio \ uses: actions/cache@v4
mingw-w64-ucrt-x86_64-ffnvcodec-headers \ with:
mingw-w64-ucrt-x86_64-pkgconf \ path: |
mingw-w64-ucrt-x86_64-clang mingw-w64-ucrt-x86_64-clang-libs git vcpkg_installed
~/AppData/Local/vcpkg/archives
key: vcpkg-${{ runner.os }}-${{ hashFiles('vcpkg.json') }}
save-always: true
- name: Install dependencies (vcpkg manifest)
run: vcpkg install --triplet x64-windows
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# Build environment # Build environment
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# Windows uses the MSYS2 OpenColorIO package (the exact 2.5.2 the
# bridge targets; the vendored source needs MSVC-only constructs).
# Dynamic here — the CD packages the DLLs next to the binaries.
- name: Configure build environment - name: Configure build environment
run: | run: |
# System OCIO (MSYS2, the exact 2.5.2 the bridge targets); $prefix = "$env:GITHUB_WORKSPACE\vcpkg_installed\x64-windows"
# tooling/ocio-env.sh links it STATICALLY when the package ships "FFMPEG_DIR=$prefix" >> $env:GITHUB_ENV
# libOpenColorIO.a, dynamically otherwise. "PKG_CONFIG_PATH=$prefix\lib\pkgconfig" >> $env:GITHUB_ENV
bash tooling/ocio-env.sh >> "$GITHUB_ENV" "$prefix\tools\pkgconf" >> $env:GITHUB_PATH
echo "FFMPEG_DIR=.cache/ffmpeg" >> "$GITHUB_ENV" # Bundled OCIO: ocio-sys' vendored sources build with the MSVC
# ocio-sys is the GIT fork (Mike-Solar/ocio-rs main, pinned in # toolchain (what they need — the MSYS2 package was the
# the root manifest): its build.rs already carries the # workaround, not the preference), so no OCIO_INSTALL_DIR and
# fork's GNU-toolchain fix, so NO crate-unpack/glob patch step # no OCIO_RS_NO_MSVC_INCLUDES anywhere.
# applies here. The old code unpacked `ocio-sys-0.2.1.crate` "OCIO_RS_ENABLE_REAL=1" >> $env:GITHUB_ENV
# from the registry cache — impossible for a git dependency "OCIO_RS_LINK=static" >> $env:GITHUB_ENV
# (no .crate archive; git sources land under # Record the resolved versions in the build log: pinning them
# registry/src/git/<hash>), hence the # with builtin-baseline in vcpkg.json is a follow-up.
# "ls .../ocio-sys-0.2.1/build.rs: No such file" Windows CI vcpkg list
# failure.
echo "OCIO_RS_NO_MSVC_INCLUDES=1" >> "$GITHUB_ENV"
# ------------------------------------------------------------------
# Caches
# ------------------------------------------------------------------
# Covers the whole target/ dir plus ~/.cargo; shared across branches # Covers the whole target/ dir plus ~/.cargo; shared across branches
# of the same OS. # of the same OS.
- name: Cache cargo artifacts - name: Cache cargo artifacts
@@ -276,57 +262,28 @@ jobs:
shared-key: oak-ci-windows shared-key: oak-ci-windows
cache-on-failure: true cache-on-failure: true
# The project FFmpeg (release/8.0, static, all free codecs + hwaccel)
# is built by tooling/ffmpeg/build-ffmpeg.sh — 10-20 min on a cold
# cache. It does not depend on the Rust toolchain, so key it on the
# script itself and keep it out of rust-cache.
- name: Cache project FFmpeg
uses: actions/cache@v4
with:
path: .cache/ffmpeg
key: ffmpeg-${{ runner.os }}-${{ hashFiles('tooling/ffmpeg/build-ffmpeg.sh') }}
# ------------------------------------------------------------------
# Project FFmpeg (script + FFMPEG_DIR; see docs/build.md)
# ------------------------------------------------------------------
- name: Build project FFmpeg
run: |
bash tooling/ffmpeg/build-ffmpeg.sh
echo "FFMPEG_DIR=$(cygpath -m "$PWD/.cache/ffmpeg")" >> "$GITHUB_ENV"
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# Build & test # Build & test
# ------------------------------------------------------------------ # ------------------------------------------------------------------
# `cargo check` (not build): the Test step links the test binaries # `cargo check` (not build): the Test step links the test binaries
# anyway, and a full build would codegen every workspace crate twice # anyway, and a full build would codegen every workspace crate twice
# (once without and once with cfg(test)). cargo check performs no # (once without and once with cfg(test)).
# final link, so the mingw-w64 link-order workaround is only needed
# in the Test step.
- name: Build - name: Build
run: | run: cargo check --workspace --locked
cargo check --workspace --locked
- name: Test - name: Test
run: | run: |
# The GitHub image injects the MSVC INCLUDE/LIB into the cargo test --workspace --locked
# environment; clear them in-step (they poison the MinGW if ($LASTEXITCODE -ne 0) {
# compiles with MSVC SDK headers).
unset INCLUDE LIB
# mingw-w64 >= Nov 2025 forwards _assert to __msvcrt_assert inside
# libmingwex.a; rustc's link order puts -lmingwex last, so any
# binary that pulls _assert.o leaves _fileno/_setmode/
# __imp___msvcrt_assert unresolved. A trailing -lmsvcrt re-scans
# the CRT import lib after libmingwex.
export RUSTFLAGS="-C link-args=-lmsvcrt"
if ! cargo test --workspace --locked; then
# Retry once: a few gpui keystroke tests flake on Windows CI — # Retry once: a few gpui keystroke tests flake on Windows CI —
# a synthetic keystroke is occasionally never delivered (the # a synthetic keystroke is occasionally never delivered (the
# undo/redo pair and a plain 's' toggle both failed once, # undo/redo pair and a plain 's' toggle both failed once,
# each identically to its pass state). A real regression # each identically to its pass state). A real regression
# fails both passes. # fails both passes.
echo "first pass failed; retrying once for gpui keystroke flakes" Write-Host "first pass failed; retrying once for gpui keystroke flakes"
cargo test --workspace --locked cargo test --workspace --locked
fi if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
}
macos: macos:
name: Build & test (macOS) name: Build & test (macOS)
+3
View File
@@ -15,6 +15,9 @@ CmakeSettings.json
# clangd's index and likely other things that need not be in the repository # clangd's index and likely other things that need not be in the repository
.cache/ .cache/
# vcpkg manifest-mode install tree (Windows CI/CD; see vcpkg.json)
vcpkg_installed/
# Generated packaging assets (icons/icon.png is produced from Oak_Icon.svg # Generated packaging assets (icons/icon.png is produced from Oak_Icon.svg
# by rsvg-convert in the CD workflow; see .github/workflows/cd.yml) # by rsvg-convert in the CD workflow; see .github/workflows/cd.yml)
/icons/ /icons/
+6
View File
@@ -86,6 +86,12 @@ cargo test --workspace # Linux: see "headless tests" below
## Windows (MSYS2 UCRT64) ## Windows (MSYS2 UCRT64)
> **CI/CD note**: the GitHub Windows CI/CD no longer uses this path — it
> builds MSVC-ABI on `warp-windows-2025-vs2026-x64-16x` with vcpkg
> manifest mode (`vcpkg.json` at the repo root: FFmpeg with every free
> codec + hwaccel, pkgconf, librsvg) and the vendored static OCIO. The
> MSYS2 flow below remains the documented local-build alternative.
The Windows build targets **x86_64-pc-windows-gnu** with MSYS2's own The Windows build targets **x86_64-pc-windows-gnu** with MSYS2's own
Rust; the MSVC toolchain is not supported (the build scripts emit Rust; the MSVC toolchain is not supported (the build scripts emit
Unix-style link args the MSVC linker rejects). Unix-style link args the MSVC linker rejects).
+35
View File
@@ -0,0 +1,35 @@
{
"name": "oak",
"version": "0.5.0",
"comment": "Windows dependencies (CI/CD, MSVC): the project's FFmpeg with every free codec + hwaccel (mirrors tooling/ffmpeg/build-ffmpeg.sh's configure), plus pkgconf so the -sys crates can find the .pc files. ffmpeg version pinning via builtin-baseline is a follow-up once CI reports the resolved version (see .github/workflows/ci.yml).",
"dependencies": [
{
"name": "ffmpeg",
"features": [
"gpl",
"version3",
"x264",
"x265",
"dav1d",
"vpx",
"openh264",
"openjpeg",
"theora",
"webp",
"mp3lame",
"opus",
"vorbis",
"speex",
"snappy",
"ass",
"freetype",
"fribidi",
"fontconfig",
"gnutls",
"ffnvcodec"
]
},
"pkgconf",
"librsvg"
]
}