diff --git a/.github/actions/setup-msvc-dev-cmd/action.yml b/.github/actions/setup-msvc-dev-cmd/action.yml new file mode 100644 index 0000000..87f0fc9 --- /dev/null +++ b/.github/actions/setup-msvc-dev-cmd/action.yml @@ -0,0 +1,85 @@ +name: Setup MSVC Developer Command Prompt +description: Export MSVC developer environment variables for subsequent Windows build steps. +inputs: + arch: + description: Target architecture passed to vcvarsall.bat, for example x64 or arm64. + required: true +runs: + using: composite + steps: + - name: Export MSVC environment + shell: pwsh + run: | + $ErrorActionPreference = 'Stop' + + $arch = '${{ inputs.arch }}' + $validArchitectures = @('x86', 'x64', 'arm', 'arm64') + if ($arch -notin $validArchitectures) { + throw "Unsupported MSVC architecture: $arch" + } + + $vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe' + if (-not (Test-Path $vswhere)) { + throw "vswhere was not found: $vswhere" + } + + $installationPath = & $vswhere -latest -products '*' -property installationPath + if (-not $installationPath) { + throw 'Visual Studio installation was not found' + } + + $vcvarsall = Join-Path $installationPath 'VC\Auxiliary\Build\vcvarsall.bat' + if (-not (Test-Path $vcvarsall)) { + throw "vcvarsall.bat was not found: $vcvarsall" + } + + $before = @{} + Get-ChildItem Env: | ForEach-Object { + $before[$_.Name] = $_.Value + } + + $vcvarsCommand = "`"$vcvarsall`" $arch >nul && set" + $environment = & cmd.exe /s /c $vcvarsCommand + if ($LASTEXITCODE -ne 0) { + throw "vcvarsall.bat failed for architecture: $arch" + } + + $preserveVariables = @( + 'VCPKG_ROOT', + 'VCPKG_INSTALLATION_ROOT', + 'VCPKG_DEFAULT_BINARY_CACHE', + 'VCPKG_DOWNLOADS' + ) + + foreach ($line in $environment) { + if ($line -notmatch '^([^=]+)=(.*)$') { + continue + } + + $name = $Matches[1] + $value = $Matches[2] + if ($before.ContainsKey($name) -and $before[$name] -ceq $value) { + continue + } + + if ($name -in $preserveVariables) { + continue + } + + if ($name -ieq 'Path') { + # Preserve vcvarsall's PATH ordering. GITHUB_PATH prepends entries and + # can make Visual Studio's bundled vcpkg shadow the runner vcpkg. + $delimiter = "MSVC_ENV_$([guid]::NewGuid().ToString('N'))" + "$name<<$delimiter" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + $value | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + $delimiter | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + continue + } + + $delimiter = "MSVC_ENV_$([guid]::NewGuid().ToString('N'))" + "$name<<$delimiter" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + $value | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + $delimiter | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + } + + "MSVC developer environment initialized for $arch" diff --git a/.github/actions/setup-native-prereqs/action.yml b/.github/actions/setup-native-prereqs/action.yml index ed83ff3..e68d673 100644 --- a/.github/actions/setup-native-prereqs/action.yml +++ b/.github/actions/setup-native-prereqs/action.yml @@ -49,6 +49,8 @@ runs: if: endsWith(inputs.target, '-pc-windows-msvc') shell: pwsh run: | + $ErrorActionPreference = 'Stop' + if ($env:VCPKG_DEFAULT_BINARY_CACHE) { New-Item -ItemType Directory -Force -Path $env:VCPKG_DEFAULT_BINARY_CACHE | Out-Null } @@ -62,10 +64,27 @@ runs: default { throw "unsupported Windows target: ${{ inputs.target }}" } } - # vcpkg is pre-installed on GitHub-hosted Windows runners. - vcpkg install glib:$Triplet libusb:$Triplet fftw3:$Triplet pkgconf:$Triplet + $BundledVcpkg = 'C:\vcpkg\vcpkg.exe' + $ResolvedVcpkg = Get-Command vcpkg -CommandType Application -ErrorAction SilentlyContinue | Select-Object -First 1 + $VcpkgExe = if (Test-Path $BundledVcpkg) { + $BundledVcpkg + } elseif ($ResolvedVcpkg) { + $ResolvedVcpkg.Source + } else { + throw 'vcpkg executable was not found' + } + + $VcpkgRoot = Split-Path -Parent $VcpkgExe + $env:VCPKG_ROOT = $VcpkgRoot + $env:VCPKG_INSTALLATION_ROOT = $VcpkgRoot + Write-Host "Using vcpkg at $VcpkgExe" + + $Packages = @("glib:$Triplet", "libusb:$Triplet", "fftw3:$Triplet", "pkgconf:$Triplet") + & $VcpkgExe install $Packages + if ($LASTEXITCODE -ne 0) { + throw "vcpkg install failed with exit code $LASTEXITCODE" + } - $VcpkgRoot = if ($env:VCPKG_INSTALLATION_ROOT) { $env:VCPKG_INSTALLATION_ROOT } elseif ($env:VCPKG_ROOT) { $env:VCPKG_ROOT } else { throw "vcpkg root environment variable is not set" } $PkgConfigExe = "$VcpkgRoot/installed/$Triplet/tools/pkgconf/pkgconf.exe" $PkgConfigPath = "$VcpkgRoot/installed/$Triplet/lib/pkgconfig;$VcpkgRoot/installed/$Triplet/share/pkgconfig" $PkgConfigBin = "$VcpkgRoot/installed/$Triplet/tools/pkgconf" @@ -73,6 +92,7 @@ runs: $DebugRuntimeBin = "$VcpkgRoot/installed/$Triplet/debug/bin" "VCPKG_ROOT=$VcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 + "VCPKG_INSTALLATION_ROOT=$VcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 "DSVIEW_VCPKG_ROOT=$VcpkgRoot" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 "DSVIEW_VCPKG_TRIPLET=$Triplet" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 "CMAKE_TOOLCHAIN_FILE=$VcpkgRoot/scripts/buildsystems/vcpkg.cmake" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f77775f..70f4ebb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -74,7 +74,7 @@ jobs: - name: Initialize MSVC developer command prompt if: contains(matrix.target, 'windows') - uses: ilammy/msvc-dev-cmd@v1 + uses: ./.github/actions/setup-msvc-dev-cmd with: arch: ${{ matrix.msvc_arch }} @@ -91,7 +91,7 @@ jobs: - name: Restore Windows vcpkg cache if: contains(matrix.target, 'windows') - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | .cache/vcpkg/binary diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2d0ef14..c729f60 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -74,7 +74,7 @@ jobs: - name: Initialize MSVC developer command prompt if: contains(matrix.target, 'windows') - uses: ilammy/msvc-dev-cmd@v1 + uses: ./.github/actions/setup-msvc-dev-cmd with: arch: ${{ matrix.msvc_arch }} @@ -91,7 +91,7 @@ jobs: - name: Restore Windows vcpkg cache if: contains(matrix.target, 'windows') - uses: actions/cache@v4 + uses: actions/cache@v5 with: path: | .cache/vcpkg/binary