Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
fab9d37
quest: open the cpp line
kixelated Sep 25, 2026
c00d37d
Merge remote-tracking branch 'origin/main' into line-sync-4100
kixelated Sep 25, 2026
8c64aab
feat(cpp): generate moq-ffi C++ bindings with a pinned uniffi-bindgen…
kixelated Sep 25, 2026
c731e3f
Merge origin/main into quest/m1/cpp/README
kixelated Sep 25, 2026
f8392e3
Merge origin/main into quest/m1/cpp/README
kixelated Sep 25, 2026
c02c9df
quest(cpp): C++ errors carry their message (#4203)
kixelated Sep 26, 2026
4d10c9d
feat(cpp): the moq C++ package, release archives, interop client, and…
kixelated Sep 26, 2026
5989f1d
Merge origin/main into quest/m1/cpp/README
kixelated Sep 26, 2026
341f09d
feat(cpp): moq::Error prints Rust's message (#4292)
kixelated Sep 27, 2026
c48fdd1
Merge remote-tracking branch 'origin/main' into quest/m1/cpp/README
kixelated Sep 28, 2026
50cd8e4
feat(cpp)!: export the C++ package as moq::cpp (#4297)
kixelated Sep 28, 2026
2ae9f9a
feat(obs): the OBS plugin on the generated C++ bindings (#4281)
kixelated Sep 28, 2026
475dd23
quest(cpp): block the line on the #4281 catalog switch and stats race…
kixelated Sep 28, 2026
ea479c9
Merge origin/main into quest/m1/cpp/README
kixelated Sep 28, 2026
e8081f5
Merge remote-tracking branch 'origin/main' into quest/m1/cpp/README
kixelated Sep 28, 2026
72d5f25
quest: claim cpp/cancel
kixelated Sep 29, 2026
0abff42
chore(quest): start cxx-standard
kixelated Sep 29, 2026
d20be3c
docs(cpp): document CMAKE_CXX_STANDARD and test a C++23 consumer
kixelated Sep 29, 2026
14960b4
docs(cpp): point callers at valid() before reading a cancelled future
kixelated Sep 29, 2026
0cd0561
Merge pull request #4447 from moq-dev/quest/m1/cpp/cxx-standard
kixelated Sep 29, 2026
c96f029
Merge remote-tracking branch 'origin/quest/m1/cpp/README' into audit/…
kixelated Sep 29, 2026
1ce31bc
quest(cpp): block the line on its inherited platform CI failures
kixelated Sep 29, 2026
88b9ad2
Merge pull request #4379 from moq-dev/audit/cpp-blockers
kixelated Sep 29, 2026
115b8ee
Merge remote-tracking branch 'origin/quest/m1/cpp/README' into quest/…
kixelated Oct 3, 2026
6d0a4ca
test(cpp): assert get() leaves the future invalid
kixelated Oct 3, 2026
20729f1
Merge pull request #4453 from moq-dev/quest/m1/cpp/cancel
kixelated Oct 3, 2026
d8d31d3
quest: claim quest/m1/cpp/obs-version-header
kixelated Oct 3, 2026
c29f94c
quest: claim m1/cpp/msvc-pkg-config
kixelated Oct 3, 2026
ff74c01
fix(obs): keep VERSION files off the include path
kixelated Oct 3, 2026
3a955aa
fix(cpp): keep the GNU-toolchain checks off Windows, fail loud on pkg…
kixelated Oct 3, 2026
a8cff1c
quest: track the generated-bindings newline failure
kixelated Oct 3, 2026
4dede41
Merge pull request #4748 from moq-dev/quest/m1/cpp/msvc-pkg-config
kixelated Oct 3, 2026
439acce
Merge remote-tracking branch 'origin/quest/m1/cpp/README' into quest/…
kixelated Oct 3, 2026
4e48e0e
Merge pull request #4747 from moq-dev/quest/m1/cpp/obs-version-header
kixelated Oct 3, 2026
b4d01ee
Merge origin/main into quest/m1/cpp/README
kixelated Oct 5, 2026
6441129
Merge origin/main into quest/m1/cpp/README
kixelated Oct 5, 2026
2da2cb9
Merge origin/main into quest/m1/cpp/README
kixelated Oct 6, 2026
a882df4
fix(obs): keep the drain alive past Stop, and flatten the cpp questline
kixelated Oct 6, 2026
0db3e75
quest(cpp): fold the OBS release dry run into the first C++ release
kixelated Oct 6, 2026
526500a
Merge origin/main into quest/m1/cpp/README
kixelated Oct 9, 2026
e7388e2
fix(obs): drop the protocol pin from the Advanced tooltip
kixelated Oct 9, 2026
0fed1c5
fix(interop): the C++ client sets max_delay_us
kixelated Oct 9, 2026
178b3d3
quest: the FFI publisher stall covers the C++ publisher
kixelated Oct 9, 2026
d646cb3
fix(sh): moq-c's native-libs lists put the OBS compile in scope
kixelated Oct 9, 2026
d01d6fc
docs(cpp): check every result in the samples; plan the generated C++ …
kixelated Oct 9, 2026
be7739d
quest: a cancelled moq-ffi read never takes data
kixelated Oct 9, 2026
b778894
Merge remote-tracking branch 'origin/main' into cpp-readme-iterate
kixelated Oct 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/alert.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ on:
- Platform
- Quest
- release-brew
- Release C++
- Release Dart
- Release Dart FFI
- Release Go
Expand Down
91 changes: 91 additions & 0 deletions .github/workflows/cpp.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: C++

# Builds and tests the moq C++ package (cpp/moq) with clang and MSVC, outside
# Nix. `just check` already runs `just cpp check` with the dev shell's gcc; the
# dev shell has no clang++, and adding one would change which compiler every
# other recipe gets as `cc`.
#
# Outside Nix the generator comes from `cargo install` at the tag flake.nix
# pins; see the comment there for every other place that names it.

permissions:
contents: read

on:
pull_request:
# `closed` is here only so merging/closing a PR cancels its in-flight run
# via the concurrency group below; the job itself is skipped on close.
types: [opened, synchronize, reopened, closed]
paths:
- "cpp/moq/**"
- "cpp/justfile"
- "rs/moq-ffi/**"
- "sh/cpp/**"
- "rs/moq-c/native-libs/**"
- "doc/lib/cpp/**"
- "doc/lib/samples.sh"
- "Cargo.lock"
- ".github/workflows/cpp.yml"

concurrency:
group: cpp-${{ github.ref }}
cancel-in-progress: true

jobs:
clang:
name: C++ (clang)
if: github.event.action != 'closed'
runs-on: ubuntu-24.04
timeout-minutes: 60

steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable

- uses: ./.github/actions/just

- name: Install uniffi-bindgen-cpp
run: cargo install uniffi-bindgen-cpp --locked --git https://github.com/kixelated/uniffi-bindgen-cpp --tag v0.11.0-kixelated.4+v0.32.2

- name: Check
run: just cpp check
env:
CXX: clang++

# MSVC, with exceptions and RTTI off, plus the package's tests.
msvc:
name: C++ (MSVC)
if: github.event.action != 'closed'
runs-on: windows-latest
timeout-minutes: 60

steps:
- name: Checkout
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- name: Install Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable

# aws-lc-rs assembles its x86_64 crypto with NASM on Windows.
- name: Install NASM
shell: pwsh
run: |
choco install nasm -y --no-progress
"C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- uses: ./.github/actions/just

- name: Install uniffi-bindgen-cpp
shell: bash
run: cargo install uniffi-bindgen-cpp --locked --git https://github.com/kixelated/uniffi-bindgen-cpp --tag v0.11.0-kixelated.4+v0.32.2

- name: Check
shell: bash
run: just cpp check
1 change: 1 addition & 0 deletions .github/workflows/interop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ on:
- "package.json"
# The Go client builds against the modules this script stages.
- "sh/go/**"
- "cpp/moq/**"
- ".github/workflows/interop.yml"

concurrency:
Expand Down
106 changes: 0 additions & 106 deletions .github/workflows/moq-c.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,109 +116,3 @@ jobs:
RELEASE_PREV_TAG: ${{ steps.prev_tag.outputs.tag }}
run: just gh release create artifacts

# The OBS plugin (cpp/obs) statically links moq-c, so it ships with every
# moq-c release: rebuild it against the release we just published (no
# second cargo build, guaranteed-matching ABI) and cut a parallel
# obs-moq-v<version> release. Runs after `release` so the moq-c archives
# the plugin's CMake fetches are already live.
obs-build:
name: OBS plugin (${{ matrix.target }})
needs: release
runs-on: ${{ matrix.os }}

# macOS + Windows only. These link the ffmpeg the obs-deps bundle ships
# (the same one OBS uses), so the binaries are portable. A Linux build
# would link nix/distro ffmpeg and not be portable, so Linux is
# build-from-source (see doc/bin/obs.md) and ships no prebuilt binary.
strategy:
fail-fast: false
matrix:
include:
- target: aarch64-apple-darwin
os: macos-latest
- target: x86_64-pc-windows-msvc
# The plugin preset uses the Visual Studio 17 2022 generator.
os: windows-2022

steps:
# Shallow: this job only compiles, it never reads git history or tags.
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false

- uses: ./.github/actions/just

- name: Parse version
id: parse
shell: bash
run: just gh release parse-version moq-c

# Native Xcode / Visual Studio; libobs/Qt6/ffmpeg come from the obs-deps
# bundle and moq-c from the release we just published (--moq-c-release).
- name: Build and package
shell: bash
env:
TARGET: ${{ matrix.target }}
VERSION: ${{ steps.parse.outputs.version }}
run: |
just obs package --target "$TARGET" --moq-c-release "$VERSION" --output dist

- name: Upload artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
name: obs-moq-${{ matrix.target }}
path: dist/*

obs-release:
name: OBS plugin release
needs: obs-build
runs-on: ubuntu-latest
permissions:
contents: write

steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false

- uses: ./.github/actions/just

- name: Parse version
id: parse
run: just gh release parse-version moq-c

# Only the obs-moq archives: the moq-c-* artifacts from the build job
# belong to the moq-c release, not this one.
- name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
path: artifacts
pattern: obs-moq-*
merge-multiple: true

# release.sh prev-tag keys off the current tag, but the trigger here is a
# moq-c-v* tag, so it can't find the previous obs-moq tag. Take the
# newest existing obs-moq tag (excluding this version, for safe re-runs)
# so the release notes span only since the last obs-moq release.
- name: Find previous obs-moq tag
id: prev_tag
env:
VERSION: ${{ steps.parse.outputs.version }}
run: |
cur="obs-moq-v${VERSION}"
# awk (not grep -vx | head) so an empty result is exit 0, not 1:
# under `set -eo pipefail` the inaugural release has no prior tag and
# grep's exit 1 would fail the step. Empty tag is fine downstream.
prev=$(git tag --list 'obs-moq-v*' --sort=-v:refname | awk -v cur="$cur" '$0 != cur { print; exit }')
echo "tag=${prev}" >>"$GITHUB_OUTPUT"

# Cut a parallel obs-moq-v<version> release at this commit (gh creates
# the tag).
- name: Create or update release
env:
GH_TOKEN: ${{ github.token }}
RELEASE_TAG: "obs-moq-v${{ steps.parse.outputs.version }}"
RELEASE_TITLE: "obs-moq v${{ steps.parse.outputs.version }}"
RELEASE_PREV_TAG: ${{ steps.prev_tag.outputs.tag }}
run: just gh release create artifacts
16 changes: 11 additions & 5 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ name: Nightly
# no artifacts with the default one, which is several minutes of duplicate work
# that a PR gate can't justify for how rarely it catches something. `obs` is
# diff-independent because its PR-time counterpart can't be: obs.yml has to
# name the paths that can break an external link to libmoq.a, and no list of
# paths covers every one of them (see the comment there).
# name the paths that can break an external link to a Rust staticlib, and no
# list of paths covers every one of them (see the comment there).
#
# The `release-*` jobs are diff-independent because the release workflows only
# ever run on a tag: a change that compiles under plain cargo can still break a
Expand Down Expand Up @@ -181,9 +181,9 @@ jobs:
if: ${{ !cancelled() }}
run: nix develop --command just rs audit

# The OBS plugin and moq-c's C fixtures are the only things that link
# libmoq.a from outside cargo, so a stale `rs/moq-c/native-libs/*.txt`
# breaks them and nothing else. obs.yml lists the inputs that can do that,
# The OBS plugin (over moq-ffi) and moq-c's C fixtures link a Rust
# staticlib from outside cargo, so a stale `rs/moq-c/native-libs/*.txt`
# breaks them and no cargo build. obs.yml lists the inputs that can do that,
# but a list of paths can't be complete: a build script emitting
# `cargo::rustc-link-lib` needs no manifest change, and widening that
# filter to `rs/**` would run a link on nearly every PR. Being
Expand Down Expand Up @@ -384,6 +384,12 @@ jobs:
permissions:
contents: write

release-cpp:
name: Release C++
uses: ./.github/workflows/release-cpp.yml
permissions:
contents: write

release-moq-relay:
name: moq-relay
uses: ./.github/workflows/moq-relay.yml
Expand Down
72 changes: 43 additions & 29 deletions .github/workflows/obs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,35 @@ name: OBS
# multi-hundred-MB obs-deps bundle on macOS and Windows.
#
# Linux is the platform that needs no bundle at all -- nixpkgs has obs-studio,
# Qt6 and ffmpeg, so the `.#obs` shell is the whole dependency set. The plugin is
# platform-independent C++ over moq-c's C ABI, so a Linux compile catches the
# breakage a macOS developer would otherwise ship uncompiled. The macOS and
# Windows release builds cover the rest: each platform's link line and the
# obs-deps bundle.
# Qt6 and ffmpeg, so the `.#obs` shell is the whole dependency set. The plugin
# is platform-independent C++ over the generated moq-ffi bindings (cpp/moq), so
# a Linux compile catches the breakage a macOS developer would otherwise ship
# uncompiled. The macOS and Windows release builds cover the rest: each
# platform's link line and the obs-deps bundle.
#
# Narrow trigger, like swift.yml: the plugin's own sources, the moq-c header
# they call through, and the flake that supplies the toolchain.
# Narrow trigger, like swift.yml: the plugin's own sources, the C++ package and
# the moq-ffi API it is generated from, and the flake that supplies the
# toolchain, including uniffi-bindgen-cpp.
#
# moq-c's own C fixtures (`just rs c-tests`) run here too. They link libmoq.a
# from outside cargo the same way, which is too slow for nextest's hang budget
# and needs the debug staticlib this job has just built, so this is the one
# PR gate that already has everything they need. They also compile the C doc
# samples, hence `doc/lib/c/**` in the trigger.
# from outside cargo the same way the plugin links moq-ffi, which is too slow
# for nextest's hang budget, so this job, which already does that kind of link,
# is where they gate PRs. They also compile the C doc samples, hence
# `doc/lib/c/**` in the trigger.
#
# The manifests and Cargo.lock are in there for the one way a crate the plugin
# never names can break it: linking libmoq.a from outside cargo needs the native
# libraries in `rs/moq-c/native-libs/*.txt`, which are maintained by hand. A
# dependency that starts pulling in a new one leaves that list stale, and every
# Rust gate stays green, because cargo passes the flag itself and only this job
# links without it.
# never names can break it: linking a Rust staticlib from outside cargo needs
# the native libraries in `rs/moq-c/native-libs/*.txt`, which moq-ffi and
# moq-c share and which are maintained by hand. A dependency that starts
# pulling in a new one leaves that list stale, and every Rust gate stays green,
# because cargo passes the flag itself and only this job links without it.
#
# Manifests and build scripts rather than Cargo.lock alone, because neither a
# feature toggle nor a build script has to touch the lockfile. moq-c takes
# moq-native with default features, so flipping one of those defaults on
# (`jemalloc` gates `dep:tikv-jemallocator`) changes what libmoq.a needs at link
# time while Cargo.lock stays byte-identical, since moq-relay already put that
# package in the graph; a build.rs emitting `cargo::rustc-link-lib` needs no
# manifest change at all.
# feature toggle nor a build script has to touch the lockfile. Flipping a
# default feature on (`jemalloc` gates `dep:tikv-jemallocator`) changes what
# the staticlib needs at link time while Cargo.lock stays byte-identical, since
# moq-relay already put that package in the graph; a build.rs emitting
# `cargo::rustc-link-lib` needs no manifest change at all.
#
# A list of paths still can't be complete here -- a vendored C source or a
# .cargo/config.toml could do it too -- and `rs/**` would run this on nearly
Expand All @@ -51,6 +51,7 @@ on:
paths:
- "rs/**"
- "cpp/obs/**"
- "cpp/moq/**"
- "doc/lib/c/**"
- "doc/lib/samples.sh"
- ".cargo/**"
Expand All @@ -66,7 +67,9 @@ on:
types: [opened, synchronize, reopened, closed]
paths:
- "cpp/obs/**"
- "cpp/moq/**"
- "sh/obs/**"
- "rs/moq-ffi/**"
- "rs/moq-c/**"
- "doc/lib/c/**"
- "doc/lib/samples.sh"
Expand Down Expand Up @@ -115,7 +118,7 @@ jobs:

# cache.yml warms the default-branch store on `main`. Pull requests restore
# it; the action refuses to publish from a pull request. It holds
# dev-profile artifacts, which is why `just obs ci` builds moq-c in debug
# dev-profile artifacts, which is why `just obs ci` builds moq-ffi in debug
# rather than the preset's release.
- name: Rust cache
uses: ./.github/actions/rust-cache
Expand All @@ -125,15 +128,13 @@ jobs:
- name: Build
run: nix develop .#obs --command just obs ci

# The plugin build above already produced the debug libmoq.a, so the
# cargo step inside is a no-op and this is just a cc and a run.
- name: moq-c C fixtures
run: nix develop .#obs --command just rs c-tests

# The release build of the OBS plugin, minus the published moq-c: build.sh
# without `--moq-c-release` links the in-tree rs/moq-c instead, so a PR is
# checked against its own C ABI. The obs-deps bundle (libobs, Qt6, ffmpeg)
# comes from buildspec.json at configure time, same as a tag build.
# The release build of the OBS plugin, minus the published C++ package:
# build.sh without `--moq-release` builds the in-tree cpp/moq instead, so a PR
# is checked against its own moq-ffi API. The obs-deps bundle (libobs, Qt6,
# ffmpeg) comes from buildspec.json at configure time, same as a tag build.
release:
name: OBS (${{ matrix.name }})
if: github.event.action != 'closed'
Expand Down Expand Up @@ -162,6 +163,19 @@ jobs:

- uses: ./.github/actions/just

# aws-lc-rs assembles its x86_64 crypto with NASM on Windows.
- name: Install NASM
if: runner.os == 'Windows'
shell: pwsh
run: |
choco install nasm -y --no-progress
"C:\Program Files\NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

# The tag flake.nix pins; see the comment there.
- name: Install uniffi-bindgen-cpp
shell: bash
run: cargo install uniffi-bindgen-cpp --locked --git https://github.com/kixelated/uniffi-bindgen-cpp --tag v0.11.0-kixelated.4+v0.32.2

- name: Build
shell: bash
env:
Expand Down
Loading
Loading