Skip to content

Update build.yml

Update build.yml #62

Workflow file for this run

name: Build revo-lib with OBS 32.x
on:
workflow_dispatch:
push:
branches: [ main ]
jobs:
build-macos:
name: Build (macOS)
runs-on: macos-15-intel
env:
MACOSX_DEPLOYMENT_TARGET: "13.0"
CMAKE_OSX_DEPLOYMENT_TARGET: "13.0"
RUST_BACKTRACE: "1"
# build.rs używa tego jako ref (domyślnie 32.1.0-rc1 jeśli brak)
REVO_OBS_REF: "32.1.0-rc1"
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
brew update
brew install simde ffmpeg mbedtls speexdsp uthash jansson cmake ninja pkg-config
- name: Build (revo-lib) + build.rs builds OBS
shell: bash
run: |
set -euo pipefail
cargo build --release
- name: Package prebuilt libobs artifact (layout compatible with REVO_PREBUILT_LIBOBS_DIR)
shell: bash
run: |
set -euo pipefail
ARCH=$(uname -m)
STAGING="libobs-prebuilt-macos-${ARCH}"
OBS_SRC="obs-libobs/obs-studio"
BUILD_DIR="${OBS_SRC}/build-headless"
INSTALL_PREFIX="${BUILD_DIR}/install"
mkdir -p "${STAGING}/framework"
mkdir -p "${STAGING}/include/obs"
mkdir -p "${STAGING}/bindings"
# 1) Framework
FW_DIR="$(find "${BUILD_DIR}" -type d -name "libobs.framework" -print -quit || true)"
if [ -z "${FW_DIR}" ]; then
echo "ERROR: libobs.framework not found under ${BUILD_DIR}" >&2
find "${BUILD_DIR}" -maxdepth 8 -name "*.framework" -print || true
exit 1
fi
# Copy as obs.framework to match build.rs prebuilt link name (framework=obs)
rm -rf "${STAGING}/framework/obs.framework"
cp -R "${FW_DIR}" "${STAGING}/framework/obs.framework"
echo "Copied framework: ${FW_DIR} -> ${STAGING}/framework/obs.framework"
# Ensure the binary name matches what build.rs links: framework=obs
if [ -f "${STAGING}/framework/obs.framework/libobs" ] && [ ! -e "${STAGING}/framework/obs.framework/obs" ]; then
ln -sf "libobs" "${STAGING}/framework/obs.framework/obs"
fi
# 2) Headers
if [ -d "${INSTALL_PREFIX}/include/obs" ]; then
cp -R "${INSTALL_PREFIX}/include/obs/." "${STAGING}/include/obs/"
echo "Copied installed headers from ${INSTALL_PREFIX}/include/obs"
fi
cp "${OBS_SRC}/libobs/"*.h "${STAGING}/include/obs/" 2>/dev/null || true
# obsconfig.h
if [ -f "${BUILD_DIR}/config/obsconfig.h" ]; then
cp "${BUILD_DIR}/config/obsconfig.h" "${STAGING}/include/obs/"
echo "Copied obsconfig.h"
else
echo "WARNING: obsconfig.h not found at ${BUILD_DIR}/config/obsconfig.h" >&2
fi
# 3) Bindings (pre-generated)
BINDINGS="$(find target -path "*/out/libobs_bindings.rs" -print -quit || true)"
if [ -z "${BINDINGS}" ]; then
echo "ERROR: libobs_bindings.rs not found in target/**/out/" >&2
find target -maxdepth 6 -name "libobs_bindings.rs" -print || true
exit 1
fi
cp "${BINDINGS}" "${STAGING}/bindings/libobs_bindings.rs"
echo "Copied bindings from ${BINDINGS}"
# 4) Metadata
echo "REVO_OBS_REF=${REVO_OBS_REF}" >> "${STAGING}/build-info.env"
echo "OBS_GIT=$(git -C ${OBS_SRC} describe --tags --always 2>/dev/null || echo unknown)" >> "${STAGING}/build-info.env"
echo "BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "${STAGING}/build-info.env"
echo "ARCH=${ARCH}" >> "${STAGING}/build-info.env"
echo "MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET}" >> "${STAGING}/build-info.env"
echo "Artifact layout:"
find "${STAGING}" -not -name '*.h' | sort
echo "STAGING=${STAGING}" >> "$GITHUB_ENV"
- name: Patch framework install names (make artifact portable)
shell: bash
run: |
set -euo pipefail
FW_DIR="${{ env.STAGING }}/framework/obs.framework"
# If obs doesn't exist for some reason, create it now
if [ -f "${FW_DIR}/libobs" ] && [ ! -e "${FW_DIR}/obs" ]; then
ln -sf "libobs" "${FW_DIR}/obs"
fi
# Patch BOTH names if present, so whichever the linker uses is consistent.
for FW_BIN in "${FW_DIR}/libobs" "${FW_DIR}/obs"; do
if [ -f "${FW_BIN}" ]; then
echo "== Patching: ${FW_BIN} =="
echo "Before:"
otool -D "${FW_BIN}" || true
otool -L "${FW_BIN}" || true
install_name_tool -id "@rpath/obs.framework/libobs" "${FW_BIN}"
echo "After:"
otool -D "${FW_BIN}" || true
otool -L "${FW_BIN}" || true
echo "== LC_BUILD_VERSION =="
otool -l "${FW_BIN}" | grep -A2 LC_BUILD_VERSION || true
echo
fi
done
# Re-sign after modifications
codesign --force --sign - "${FW_DIR}" || true
- name: CALCULATED BUNDLE SIZE (system deps referenced by obs.framework)
shell: bash
run: |
set -euo pipefail
STAGING="${{ env.STAGING }}"
FW_DIR="${STAGING}/framework/obs.framework"
if [ -f "${FW_DIR}/obs" ]; then
FW_BIN="${FW_DIR}/obs"
else
FW_BIN="${FW_DIR}/libobs"
fi
echo "=============================="
echo "CALCULATED BUNDLE SIZE (SYSTEM DEPS)"
echo "=============================="
echo "Framework dir: ${FW_DIR}"
echo "Framework bin: ${FW_BIN}"
echo
echo "[STAGING TOTAL]"
du -sh "${STAGING}" || true
echo
echo "[FRAMEWORK TOTAL]"
du -sh "${FW_DIR}" || true
echo
echo "[BREW INFO]"
command -v brew || true
BREW_PREFIX="$(brew --prefix 2>/dev/null || true)"
echo "brew --prefix: ${BREW_PREFIX}"
echo "Exists /usr/local/opt? $(test -d /usr/local/opt && echo yes || echo no)"
echo "Exists /opt/homebrew/opt? $(test -d /opt/homebrew/opt && echo yes || echo no)"
echo
echo "[DEPENDENCIES FROM otool -L]"
DEPS_FILE="$(mktemp)"
otool -L "${FW_BIN}" \
| tail -n +2 \
| awk '{print $1}' \
| grep -vE '^(@rpath|@loader_path|@executable_path)' \
| grep -E '^/' \
| sort -u > "${DEPS_FILE}" || true
sed 's/^/ - /' "${DEPS_FILE}" || true
echo
echo "[CHECK IF otool PATHS EXIST ON DISK]"
while IFS= read -r p; do
[ -n "${p}" ] || continue
if [ -e "${p}" ]; then
echo "OK ${p}"
else
echo "MISS ${p}"
fi
done < "${DEPS_FILE}"
echo
echo "[FFMPEG SIZE (by brew prefix)]"
if brew --prefix ffmpeg >/dev/null 2>&1; then
FFMPEG_PREFIX="$(brew --prefix ffmpeg)"
echo "ffmpeg prefix: ${FFMPEG_PREFIX}"
echo "ffmpeg lib dir size: "
du -sh "${FFMPEG_PREFIX}/lib" || true
echo "ffmpeg dylibs:"
ls -lh "${FFMPEG_PREFIX}/lib"/libav*.dylib 2>/dev/null || true
echo "ffmpeg dylib total:"
python3 - <<'PY'
import glob, os
paths = glob.glob(os.path.join(os.environ["FFMPEG_PREFIX"], "lib", "libav*.dylib"))
total = sum(os.path.getsize(p) for p in paths if os.path.exists(p))
print(f"{total/1024/1024:.2f} MB")
PY
else
echo "ffmpeg not installed (brew --prefix ffmpeg failed)"
fi
echo
echo "[JANSSON SIZE (by brew prefix)]"
if brew --prefix jansson >/dev/null 2>&1; then
JANSSON_PREFIX="$(brew --prefix jansson)"
echo "jansson prefix: ${JANSSON_PREFIX}"
ls -lh "${JANSSON_PREFIX}/lib"/libjansson*.dylib 2>/dev/null || true
python3 - <<'PY'
import glob, os
paths = glob.glob(os.path.join(os.environ["JANSSON_PREFIX"], "lib", "libjansson*.dylib"))
total = sum(os.path.getsize(p) for p in paths if os.path.exists(p))
print(f"{total/1024/1024:.2f} MB")
PY
else
echo "jansson not installed (brew --prefix jansson failed)"
fi
echo
rm -f "${DEPS_FILE}"
env:
FFMPEG_PREFIX: ""
JANSSON_PREFIX: ""
- name: Upload libobs prebuilt artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.STAGING }}
path: ${{ env.STAGING }}/
if-no-files-found: error
build-windows:
name: Build (Windows)
runs-on: windows-2022
env:
RUST_BACKTRACE: "1"
REVO_OBS_REF: "32.1.0-rc1"
# Force single-config generator so Release is consistent (fix Debug build + Release install mismatch)
CMAKE_GENERATOR: "Ninja"
CMAKE_BUILD_TYPE: "Release"
# vcpkg settings (Release only)
VCPKG_DEFAULT_TRIPLET: "x64-windows-release"
VCPKG_ROOT: "C:\\vcpkg"
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
- name: Install Rust
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-pc-windows-msvc
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@v1
- name: Install Ninja
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
choco install -y ninja
ninja --version
- name: Ensure vcpkg exists
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
if (-not (Test-Path $env:VCPKG_ROOT)) {
throw "Expected vcpkg at $env:VCPKG_ROOT but it does not exist on this runner."
}
$vcpkgExe = Join-Path $env:VCPKG_ROOT "vcpkg.exe"
if (-not (Test-Path $vcpkgExe)) {
Push-Location $env:VCPKG_ROOT
.\bootstrap-vcpkg.bat
Pop-Location
}
& $vcpkgExe version
- name: Install dependencies (vcpkg manifest + local baseline, Release only)
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$vcpkgExe = Join-Path $env:VCPKG_ROOT "vcpkg.exe"
# Determine a valid baseline commit from the local vcpkg checkout (guaranteed to exist)
$baseline = (git -C $env:VCPKG_ROOT rev-parse HEAD).Trim()
if (-not $baseline) { throw "Failed to determine vcpkg baseline (git rev-parse HEAD returned empty)." }
Write-Host "Using vcpkg builtin-baseline: $baseline"
@"
{
"name": "revo-lib-ci",
"version-string": "0.0.0",
"builtin-baseline": "$baseline",
"dependencies": [
"ffmpeg",
"mbedtls",
"speexdsp",
"jansson",
"uthash",
"simde"
]
}
"@ | Out-File -Encoding utf8 -NoNewline .\vcpkg.json
& $vcpkgExe install --triplet $env:VCPKG_DEFAULT_TRIPLET
- name: Build (revo-lib) + build.rs builds OBS (Release)
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$env:VCPKG_INSTALLATION_ROOT = $env:VCPKG_ROOT
$env:VCPKG_TOOLCHAIN_FILE = Join-Path $env:VCPKG_ROOT "scripts\buildsystems\vcpkg.cmake"
cargo build --release
- name: Package artifact (basic)
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$arch = "x86_64"
$staging = "libobs-prebuilt-windows-$arch"
New-Item -ItemType Directory -Force -Path $staging | Out-Null
New-Item -ItemType Directory -Force -Path "$staging\target-release" | Out-Null
Copy-Item -Recurse -Force "target\release\*" "$staging\target-release\"
"REVO_OBS_REF=$env:REVO_OBS_REF" | Out-File -Append -Encoding ascii "$staging\build-info.env"
"BUILD_DATE=$(Get-Date -AsUTC -Format o)" | Out-File -Append -Encoding ascii "$staging\build-info.env"
"ARCH=$arch" | Out-File -Append -Encoding ascii "$staging\build-info.env"
"STAGING=$staging" | Out-File -Append -Encoding utf8 $env:GITHUB_ENV
- name: Upload Windows artifact
uses: actions/upload-artifact@v4
with:
name: ${{ env.STAGING }}
path: ${{ env.STAGING }}\
if-no-files-found: error