Select latest Windows SDK version in build workflow #64
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" | |
| # vcpkg: prefer Release only | |
| VCPKG_DEFAULT_TRIPLET: "x64-windows-release" | |
| VCPKG_BUILD_TYPE: "release" | |
| # Optional: encourage single-config Release for CMake projects that respect it | |
| CMAKE_BUILD_TYPE: "Release" | |
| CMAKE_GENERATOR: "Ninja" | |
| 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: Select Windows SDK (>= 10.0.20348.0) | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| $kitsRoot = "C:\Program Files (x86)\Windows Kits\10\Lib" | |
| if (-not (Test-Path $kitsRoot)) { | |
| throw "Windows Kits not found at: $kitsRoot" | |
| } | |
| # Find installed SDK versions | |
| $versions = Get-ChildItem -Directory $kitsRoot | Select-Object -ExpandProperty Name | |
| Write-Host "Installed Windows SDK versions:" | |
| $versions | Sort-Object | ForEach-Object { Write-Host " - $_" } | |
| # Pick the newest one | |
| $selected = ($versions | Sort-Object {[version]$_} | Select-Object -Last 1) | |
| if (-not $selected) { throw "Could not determine installed Windows SDK version." } | |
| Write-Host "Selected Windows SDK version: $selected" | |
| # CMake/VS tooling often expects a trailing backslash in WindowsSDKVersion | |
| "WindowsSDKVersion=$selected\" | Out-File -Append -Encoding utf8 $env:GITHUB_ENV | |
| # Also help CMake explicitly | |
| "CMAKE_SYSTEM_VERSION=$selected" | Out-File -Append -Encoding utf8 $env:GITHUB_ENV | |
| # Sanity check: must be >= 10.0.20348.0 | |
| if ([version]($selected.TrimEnd("\")) -lt [version]"10.0.20348.0") { | |
| throw "Selected SDK $selected is still < 10.0.20348.0" | |
| } | |
| - name: Install Ninja | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| choco install -y ninja | |
| ninja --version | |
| - name: Install dependencies (vcpkg, classic mode, Release only) | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| if (-not $env:VCPKG_INSTALLATION_ROOT -or $env:VCPKG_INSTALLATION_ROOT.Trim() -eq "") { | |
| $env:VCPKG_INSTALLATION_ROOT = "C:\vcpkg" | |
| } | |
| $vcpkgRoot = $env:VCPKG_INSTALLATION_ROOT | |
| Write-Host "Using vcpkg root: $vcpkgRoot" | |
| if (-not (Test-Path $vcpkgRoot)) { | |
| throw "vcpkg root does not exist: $vcpkgRoot" | |
| } | |
| $vcpkgExe = Join-Path $vcpkgRoot "vcpkg.exe" | |
| if (-not (Test-Path $vcpkgExe)) { | |
| Write-Host "vcpkg.exe not found, bootstrapping..." | |
| Push-Location $vcpkgRoot | |
| .\bootstrap-vcpkg.bat | |
| Pop-Location | |
| } | |
| & $vcpkgExe version | |
| # Release-only triplets (avoid building debug variants) | |
| & $vcpkgExe install ` | |
| ffmpeg:x64-windows-release ` | |
| mbedtls:x64-windows-release ` | |
| speexdsp:x64-windows-release ` | |
| jansson:x64-windows-release ` | |
| uthash:x64-windows-release ` | |
| simde:x64-windows-release | |
| - name: Build (revo-lib) + build.rs builds OBS | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = "Stop" | |
| # Point build.rs/CMake to vcpkg toolchain | |
| $env:VCPKG_ROOT = $env:VCPKG_INSTALLATION_ROOT | |
| $env:VCPKG_TOOLCHAIN_FILE = Join-Path $env:VCPKG_ROOT "scripts\buildsystems\vcpkg.cmake" | |
| $env:VCPKG_DEFAULT_TRIPLET = "x64-windows-release" | |
| # IMPORTANT: do NOT force manifests here (it can break classic mode) | |
| # $env:VCPKG_FEATURE_FLAGS = "manifests" | |
| 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 |