diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5f909a77..7bdb9921 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,11 +1,18 @@ name: Build on: - push: - branches: - - main pull_request: workflow_dispatch: + inputs: + publish_release: + description: Publish GitHub Release + required: false + default: false + type: boolean + release_tag: + description: Release tag name when publishing + required: false + default: "" permissions: contents: read @@ -26,7 +33,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version: 20 + node-version: 24 cache: npm cache-dependency-path: web/package-lock.json @@ -63,10 +70,10 @@ jobs: run: cargo install cross --locked - name: Build linux binary - run: bash build/build-images.sh x86_64 + run: bash build/build-images.sh - name: Package deb - run: bash build/package-deb.sh amd64 + run: bash build/package-deb.sh - name: Upload deb uses: actions/upload-artifact@v4 @@ -99,14 +106,14 @@ jobs: run: | $env:VCPKG_ROOT = "C:\vcpkg" $env:VCPKG_DEFAULT_TRIPLET = "x64-windows-static" - $env:VCPKG_INSTALLED_DIR = Join-Path $env:VCPKG_ROOT "installed" + $env:VCPKG_INSTALLED_DIR = Join-Path $pwd "vcpkg_installed" if (-not (Test-Path $env:VCPKG_ROOT)) { git clone https://github.com/microsoft/vcpkg $env:VCPKG_ROOT } & "$env:VCPKG_ROOT\bootstrap-vcpkg.bat" -disableMetrics - & "$env:VCPKG_ROOT\vcpkg.exe" install --triplet $env:VCPKG_DEFAULT_TRIPLET + & "$env:VCPKG_ROOT\vcpkg.exe" install --triplet $env:VCPKG_DEFAULT_TRIPLET --x-install-root="$env:VCPKG_INSTALLED_DIR" $tripletRoot = Join-Path $env:VCPKG_INSTALLED_DIR $env:VCPKG_DEFAULT_TRIPLET $env:TURBOJPEG_SOURCE = "explicit" @@ -131,3 +138,39 @@ jobs: path: target/x86_64-pc-windows-msvc/release/one-kvm.exe if-no-files-found: error retention-days: 7 + + release: + runs-on: ubuntu-22.04 + needs: [deb, windows] + if: ${{ github.event_name == 'workflow_dispatch' && inputs.publish_release }} + timeout-minutes: 30 + permissions: + contents: write + steps: + - name: Validate release tag + run: | + if [ -z "${{ inputs.release_tag }}" ]; then + echo "release_tag is required when publish_release is true" + exit 1 + fi + + - name: Download deb artifact + uses: actions/download-artifact@v4 + with: + name: one-kvm-deb + path: release-artifacts/deb + + - name: Download exe artifact + uses: actions/download-artifact@v4 + with: + name: one-kvm-windows-exe + path: release-artifacts/windows + + - name: Publish GitHub Release + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ inputs.release_tag }} + generate_release_notes: true + files: | + release-artifacts/deb/*.deb + release-artifacts/windows/one-kvm.exe diff --git a/build/windows/build.ps1 b/build/windows/build.ps1 index a0dfb0d5..40b88b01 100644 --- a/build/windows/build.ps1 +++ b/build/windows/build.ps1 @@ -3,6 +3,7 @@ param( [string]$Target = "x86_64-pc-windows-msvc", [string]$Triplet = "x64-windows-static", [string]$VcpkgRoot = $env:VCPKG_ROOT, + [string]$VcpkgInstalledRoot = $env:VCPKG_INSTALLED_DIR, [switch]$NoDefaultFeatures, [string[]]$Features = @(), [Parameter(ValueFromRemainingArguments = $true)] @@ -19,8 +20,12 @@ if ([string]::IsNullOrWhiteSpace($VcpkgRoot)) { } $VcpkgRoot = [System.IO.Path]::GetFullPath($VcpkgRoot) -$vcpkgInstalledRoot = Join-Path $VcpkgRoot "installed" -$vcpkgTripletRoot = Join-Path $vcpkgInstalledRoot $Triplet +if ([string]::IsNullOrWhiteSpace($VcpkgInstalledRoot)) { + $VcpkgInstalledRoot = Join-Path $VcpkgRoot "installed" +} + +$VcpkgInstalledRoot = [System.IO.Path]::GetFullPath($VcpkgInstalledRoot) +$vcpkgTripletRoot = Join-Path $VcpkgInstalledRoot $Triplet $turbojpegLibDir = Join-Path $vcpkgTripletRoot "lib" $turbojpegIncludeDir = Join-Path $vcpkgTripletRoot "include" @@ -34,6 +39,7 @@ if (-not (Test-Path $turbojpegLibDir) -or -not (Test-Path $turbojpegIncludeDir)) $env:VCPKG_ROOT = $VcpkgRoot $env:VCPKG_DEFAULT_TRIPLET = $Triplet +$env:VCPKG_INSTALLED_DIR = $VcpkgInstalledRoot $env:TURBOJPEG_SOURCE = "explicit" $env:TURBOJPEG_LIB_DIR = $turbojpegLibDir $env:TURBOJPEG_INCLUDE_DIR = $turbojpegIncludeDir diff --git a/libs/hwcodec/build.rs b/libs/hwcodec/build.rs index a8d9b292..2bbc811d 100644 --- a/libs/hwcodec/build.rs +++ b/libs/hwcodec/build.rs @@ -91,8 +91,8 @@ mod ffmpeg { ffmpeg_ffi(); // Try VCPKG first, fallback to system FFmpeg via pkg-config - if let Ok(vcpkg_root) = std::env::var("VCPKG_ROOT") { - link_vcpkg(builder, vcpkg_root.into()); + if let Some(vcpkg_installed) = vcpkg_installed_root() { + link_vcpkg(builder, vcpkg_installed); } else { // Use system FFmpeg via pkg-config link_system_ffmpeg(builder); @@ -104,6 +104,22 @@ mod ffmpeg { build_ffmpeg_capture(builder); } + fn vcpkg_installed_root() -> Option { + println!("cargo:rerun-if-env-changed=VCPKG_INSTALLED_DIR"); + println!("cargo:rerun-if-env-changed=VCPKG_ROOT"); + + if let Ok(path) = std::env::var("VCPKG_INSTALLED_DIR") { + if !path.trim().is_empty() { + return Some(PathBuf::from(path)); + } + } + + std::env::var("VCPKG_ROOT") + .ok() + .filter(|path| !path.trim().is_empty()) + .map(|path| PathBuf::from(path).join("installed")) + } + /// Link system FFmpeg using pkg-config or custom path /// Supports both static and dynamic linking based on FFMPEG_STATIC env var fn link_system_ffmpeg(builder: &mut Build) { @@ -274,7 +290,6 @@ mod ffmpeg { target = target.replace("x64", "x86"); } println!("cargo:info={}", target); - path.push("installed"); path.push(target); println!( @@ -297,12 +312,14 @@ mod ffmpeg { "vpx", "libx264", "x265-static", - "libmfx", ]); } for lib in static_libs { println!("cargo:rustc-link-lib=static={}", lib); } + if target_os == "windows" { + link_windows_qsv_lib(&path.join("lib")); + } } let include = path.join("include"); @@ -311,6 +328,16 @@ mod ffmpeg { include } + fn link_windows_qsv_lib(lib_dir: &Path) { + if lib_dir.join("libmfx.lib").exists() { + println!("cargo:rustc-link-lib=static=libmfx"); + println!("cargo:info=Using Windows QSV support library libmfx.lib"); + return; + } + + println!("cargo:warning=Windows QSV support library not found in {}", lib_dir.display()); + } + fn link_os() { let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap(); let target_arch = std::env::var("CARGO_CFG_TARGET_ARCH").unwrap(); diff --git a/res/vcpkg/libyuv/build.rs b/res/vcpkg/libyuv/build.rs index a9d5fb31..7ceb3363 100644 --- a/res/vcpkg/libyuv/build.rs +++ b/res/vcpkg/libyuv/build.rs @@ -82,8 +82,8 @@ fn generate_bindings(cpp_dir: &Path) { fn link_libyuv() { // Try vcpkg first - if let Ok(vcpkg_root) = env::var("VCPKG_ROOT") { - if link_vcpkg(vcpkg_root.into()) { + if let Some(vcpkg_installed) = vcpkg_installed_root() { + if link_vcpkg(vcpkg_installed) { return; } } @@ -109,6 +109,22 @@ fn link_libyuv() { ); } +fn vcpkg_installed_root() -> Option { + println!("cargo:rerun-if-env-changed=VCPKG_INSTALLED_DIR"); + println!("cargo:rerun-if-env-changed=VCPKG_ROOT"); + + if let Ok(path) = env::var("VCPKG_INSTALLED_DIR") { + if !path.trim().is_empty() { + return Some(PathBuf::from(path)); + } + } + + env::var("VCPKG_ROOT") + .ok() + .filter(|path| !path.trim().is_empty()) + .map(|path| PathBuf::from(path).join("installed")) +} + fn link_vcpkg(mut path: PathBuf) -> bool { let target_arch = env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); let target_os = env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); @@ -130,7 +146,6 @@ fn link_vcpkg(mut path: PathBuf) -> bool { } }; - path.push("installed"); path.push(triplet); let include_path = path.join("include"); diff --git a/vcpkg-configuration.json b/vcpkg-configuration.json new file mode 100644 index 00000000..b1cf1cad --- /dev/null +++ b/vcpkg-configuration.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg-configuration.schema.json", + "default-registry": { + "kind": "git", + "repository": "https://github.com/microsoft/vcpkg", + "baseline": "1e199d32ad53aab1defda61ce41c380302e3f95c" + } +}