Skip to content

Merge pull request #4 from irlserver/feat/bundled-ffmpeg #210

Merge pull request #4 from irlserver/feat/bundled-ffmpeg

Merge pull request #4 from irlserver/feat/bundled-ffmpeg #210

Workflow file for this run

name: Build
on:
push:
branches: [main, master]
pull_request:
workflow_call:
# The plugin bundles its own static FFmpeg/libsrt, so the only remaining tie to
# a specific OBS release is libobs itself. libobs gates a module on
# (major, minor) <= host version and looks up nothing but obs_module_*, so
# building against the OLDEST supported line produces one artifact that loads
# on that line and every newer one. That is why there is no per-OBS-line matrix
# here any more.
env:
OBS_VERSION: "32.1.2"
OBS_DEPS_VERSION: "2025-08-23"
jobs:
linux-x64:
runs-on: ubuntu-26.04
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
build-essential cmake pkg-config nasm meson ninja-build \
libobs-dev libva-dev
# Only the install prefix is cached. The source and object trees are an
# order of magnitude larger and the build-marker files live inside the
# prefix, so a restored prefix alone is enough to skip every dep build.
- name: Cache bundled deps
id: cache-deps
uses: actions/cache@v4
with:
path: deps/.build/prefix
key: irl-deps-linux-x64-${{ hashFiles('deps/versions.env', 'deps/build-deps.sh') }}
- name: Build bundled deps
run: ./deps/build-deps.sh
- name: Configure
run: cmake -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
- name: Build
run: cmake --build build --parallel
- name: Verify isolation
run: ./scripts/verify-plugin.sh build/obs-irl-source.so
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: obs-irl-source-linux-x64
path: build/obs-irl-source.so
windows-x64:
runs-on: windows-2025-vs2026
steps:
- uses: actions/checkout@v4
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
# librist builds with meson. It has to be the Windows-native meson (so it
# detects cl.exe rather than looking for a POSIX toolchain), which
# path-type: inherit below then makes visible inside MSYS2.
- name: Install meson
shell: pwsh
run: pip install --disable-pip-version-check meson ninja
# FFmpeg's configure needs a POSIX shell even when it drives cl.exe.
# path-type: inherit keeps the MSVC environment visible inside MSYS2.
- name: Setup MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: MSYS
path-type: inherit
update: false
install: make nasm diffutils pkgconf
- name: Cache bundled deps
id: cache-deps
uses: actions/cache@v4
with:
path: deps/.build/prefix
key: irl-deps-windows-x64-${{ hashFiles('deps/versions.env', 'deps/build-deps.sh') }}
- name: Build bundled deps
shell: msys2 {0}
run: ./deps/build-deps.sh
- name: Cache OBS build
id: cache-obs
uses: actions/cache@v4
with:
path: |
obs-src
obs-deps
key: obs-build-${{ env.OBS_VERSION }}-${{ env.OBS_DEPS_VERSION }}-v3
# obs-deps is still needed here, but only to build libobs itself. The
# plugin no longer links its FFmpeg.
- name: Download OBS dependencies
if: steps.cache-obs.outputs.cache-hit != 'true'
shell: pwsh
run: |
Invoke-WebRequest `
-Uri "https://github.com/obsproject/obs-deps/releases/download/${{ env.OBS_DEPS_VERSION }}/windows-deps-${{ env.OBS_DEPS_VERSION }}-x64.zip" `
-OutFile obs-deps.zip
Expand-Archive obs-deps.zip -DestinationPath obs-deps
- name: Clone OBS source
if: steps.cache-obs.outputs.cache-hit != 'true'
run: git clone --depth 1 --branch ${{ env.OBS_VERSION }} https://github.com/obsproject/obs-studio.git obs-src
- name: Patch OBS to build only libobs
if: steps.cache-obs.outputs.cache-hit != 'true'
shell: pwsh
run: |
# Keep only libobs + w32-pthreads, remove all other subdirectories
# (plugins, frontend, renderers, tests)
$lines = Get-Content obs-src/CMakeLists.txt
$output = @()
$done = $false
foreach ($line in $lines) {
if ($done) { continue }
if ($line -match '^\s*add_subdirectory\(libobs\)\s*$') {
$output += 'add_subdirectory(deps/w32-pthreads)'
$output += $line
$done = $true
} else {
$output += $line
}
}
$output | Set-Content obs-src/CMakeLists.txt
# Disable automatic dependency download (we provide deps via CMAKE_PREFIX_PATH)
(Get-Content obs-src/cmake/windows/defaults.cmake) `
-replace '^include\(buildspec\)', '# include(buildspec)' |
Set-Content obs-src/cmake/windows/defaults.cmake
# Skip multi-architecture subprocess builds (OBS normally launches
# a child cmake for x86 which would fail in our stripped-down tree)
@"
include_guard(GLOBAL)
include(compilerconfig)
if(NOT DEFINED OBS_PARENT_ARCHITECTURE)
set(OBS_PARENT_ARCHITECTURE `${CMAKE_VS_PLATFORM_NAME})
endif()
"@ | Set-Content obs-src/cmake/windows/architecture.cmake
- name: Configure OBS
if: steps.cache-obs.outputs.cache-hit != 'true'
shell: cmd
run: >
cmake -S obs-src -B obs-src/build
-G "Visual Studio 18 2026" -A x64
-DCMAKE_PREFIX_PATH=%CD%\obs-deps
-DENABLE_UI=OFF
-DENABLE_PLUGINS=OFF
- name: Build OBS (libobs only)
if: steps.cache-obs.outputs.cache-hit != 'true'
shell: cmd
run: cmake --build obs-src/build --config Release --target libobs --target w32-pthreads
- name: Configure
shell: cmd
run: >
cmake -B build
-G "Visual Studio 18 2026" -A x64
-DOBS_SOURCE_DIR=%CD%\obs-src
- name: Build
shell: cmd
run: cmake --build build --config RelWithDebInfo --parallel
- name: Verify isolation
shell: pwsh
run: |
$dll = "build/RelWithDebInfo/obs-irl-source.dll"
$deps = (dumpbin /dependents $dll) -join "`n"
$exports = (dumpbin /exports $dll) -join "`n"
$fail = $false
if ($deps -match 'av(codec|format|util)-\d+\.dll|sws(cale)?-\d+\.dll|swresample-\d+\.dll') {
Write-Host " FAIL plugin still imports a host FFmpeg DLL"; $fail = $true
} else {
Write-Host " ok no FFmpeg DLL imports (host FFmpeg not required)"
}
if ($exports -match '\bav_|\bavcodec_|\bsrt_|\bmbedtls_') {
Write-Host " FAIL bundled stack symbols are exported"; $fail = $true
} else {
Write-Host " ok bundled stack symbols not exported"
}
if ($exports -match 'obs_module_load') {
Write-Host " ok obs_module_load exported"
} else {
Write-Host " FAIL obs_module_load missing"; $fail = $true
}
if ($fail) { Write-Host $deps; Write-Host $exports; exit 1 }
- name: Collect runtime dependencies
shell: pwsh
run: |
# Copy w32-pthreads.dll next to the plugin
$w32dll = Get-ChildItem -Path obs-src/build/deps/w32-pthreads -Filter "w32-pthreads.dll" -Recurse | Select-Object -First 1
if ($w32dll) {
Copy-Item $w32dll.FullName build/RelWithDebInfo/
}
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: obs-irl-source-windows-x64
path: |
build/RelWithDebInfo/obs-irl-source.dll
build/RelWithDebInfo/w32-pthreads.dll
# PDB ships in the CI artifact (not the release zip) so a crash
# log resolves obs-irl-source.dll frames to function names.
# OBS's crash handler reads it if it sits next to the DLL.
build/RelWithDebInfo/obs-irl-source.pdb
macos-arm64:
runs-on: macos-15
env:
MACOSX_DEPLOYMENT_TARGET: "12.0"
steps:
- uses: actions/checkout@v4
# ffmpeg is intentionally NOT installed from Homebrew. The plugin links
# the bundled static stack instead, which is what removes its dependency
# on whatever FFmpeg the host OBS ships.
- name: Install build tools
run: brew install cmake pkg-config nasm meson ninja simde uthash jansson
- name: Cache bundled deps
id: cache-deps
uses: actions/cache@v4
with:
path: deps/.build/prefix
key: irl-deps-macos-arm64-${{ hashFiles('deps/versions.env', 'deps/build-deps.sh') }}
- name: Build bundled deps
run: ./deps/build-deps.sh
- name: Cache OBS build
id: cache-obs
uses: actions/cache@v4
with:
path: |
obs-src
obs-deps
key: obs-macos-arm64-${{ env.OBS_VERSION }}-${{ env.OBS_DEPS_VERSION }}-v3
- name: Download OBS dependencies
if: steps.cache-obs.outputs.cache-hit != 'true'
run: |
curl -L -o macos-deps.tar.xz \
"https://github.com/obsproject/obs-deps/releases/download/${{ env.OBS_DEPS_VERSION }}/macos-deps-${{ env.OBS_DEPS_VERSION }}-arm64.tar.xz"
mkdir -p obs-deps
tar -xf macos-deps.tar.xz -C obs-deps
- name: Clone OBS source
if: steps.cache-obs.outputs.cache-hit != 'true'
run: git clone --depth 1 --branch ${{ env.OBS_VERSION }} https://github.com/obsproject/obs-studio.git obs-src
- name: Patch OBS to build only libobs
if: steps.cache-obs.outputs.cache-hit != 'true'
run: |
# Truncate CMakeLists.txt after add_subdirectory(libobs)
sed -i '' '/^add_subdirectory(libobs)/q' obs-src/CMakeLists.txt
# Disable automatic dependency download
sed -i '' 's/^include(buildspec)/# include(buildspec)/' obs-src/cmake/macos/defaults.cmake
# Allow Homebrew paths (OBS blocks them by default)
sed -i '' '/CMAKE_IGNORE_PREFIX_PATH/d' obs-src/cmake/macos/defaults.cmake
# Relax OBS's SDK/Xcode floor. OBS gates the whole app on a very
# recent SDK, but we only build libobs with the UI off, which
# compiles on the runner's SDK.
sed -i '' -E 's/set\(obs_macos_minimum_sdk [0-9.]+\)/set(obs_macos_minimum_sdk 1.0)/' obs-src/cmake/macos/compilerconfig.cmake
sed -i '' -E 's/set\(obs_macos_minimum_xcode [0-9.]+\)/set(obs_macos_minimum_xcode 1.0)/' obs-src/cmake/macos/compilerconfig.cmake
- name: Configure OBS
if: steps.cache-obs.outputs.cache-hit != 'true'
run: >
cmake -S obs-src -B obs-src/build
-G Xcode
-DENABLE_UI=OFF
-DCMAKE_OSX_DEPLOYMENT_TARGET=12.0
-DCMAKE_PREFIX_PATH="$PWD/obs-deps;$(brew --prefix)"
- name: Build OBS (libobs only)
if: steps.cache-obs.outputs.cache-hit != 'true'
run: cmake --build obs-src/build --config Release --target libobs --parallel
# PkgConfig is disabled so a stray Homebrew or obs-deps FFmpeg .pc cannot
# shadow the bundled headers.
- name: Configure
run: >
cmake -B build
-DCMAKE_BUILD_TYPE=RelWithDebInfo
-DOBS_SOURCE_DIR=$PWD/obs-src
-DCMAKE_DISABLE_FIND_PACKAGE_PkgConfig=ON
-DCMAKE_C_FLAGS="-I$(brew --prefix)/include"
- name: Build
run: cmake --build build --parallel
- name: Verify isolation
run: ./scripts/verify-plugin.sh build/obs-irl-source.so
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: obs-irl-source-macos-arm64
path: build/obs-irl-source.so