Update build.yml #62
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |