Build Windows #3
Workflow file for this run
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 Windows | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| on: | |
| workflow_call: | |
| inputs: | |
| game: | |
| required: true | |
| type: string | |
| description: "Game to build (GeneralsMD, Generals)" | |
| preset: | |
| required: false | |
| type: string | |
| default: "win64-modern" | |
| description: "CMake preset for Windows" | |
| workflow_dispatch: | |
| inputs: | |
| game: | |
| type: choice | |
| description: "Game to build" | |
| options: | |
| - GeneralsMD | |
| - Generals | |
| default: GeneralsMD | |
| preset: | |
| type: choice | |
| description: "CMake preset for Windows" | |
| options: | |
| - win64-modern | |
| default: win64-modern | |
| jobs: | |
| build: | |
| name: ${{ inputs.game }}@${{ inputs.preset }} | |
| runs-on: windows-latest | |
| timeout-minutes: 120 | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Cache vcpkg | |
| id: cache-vcpkg | |
| uses: actions/cache@v4 | |
| with: | |
| path: C:\vcpkg | |
| key: vcpkg-windows-${{ runner.os }}-${{ hashFiles('vcpkg.json', 'vcpkg-lock.json') }} | |
| restore-keys: | | |
| vcpkg-windows-${{ runner.os }}- | |
| - name: Bootstrap vcpkg | |
| shell: pwsh | |
| run: | | |
| Write-Host "Setting up vcpkg..." | |
| if (-not (Test-Path "C:\vcpkg\vcpkg.exe")) { | |
| Write-Host "Cloning vcpkg from GitHub..." | |
| git clone https://github.com/microsoft/vcpkg.git C:\vcpkg | |
| git -C C:\vcpkg checkout ffc071e0c08432c60c9b64f00334c0227667931b | |
| Write-Host "Running vcpkg bootstrap..." | |
| & C:\vcpkg\bootstrap-vcpkg.bat -disableMetrics | |
| } else { | |
| Write-Host "Using cached vcpkg" | |
| } | |
| "VCPKG_ROOT=C:\vcpkg" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append | |
| Write-Host "vcpkg ready at C:\vcpkg" | |
| - name: Install Vulkan SDK | |
| uses: jakoch/install-vulkan-sdk-action@v1 | |
| with: | |
| vulkan_version: 1.3.283.0 | |
| install_runtime: true | |
| cache: true | |
| destination: ${{ github.workspace }}/vulkan-sdk | |
| - name: Setup MSVC (x64) | |
| uses: ilammy/msvc-dev-cmd@v1 | |
| with: | |
| arch: x64 | |
| - name: Install Ninja | |
| uses: seanmiddleditch/gha-setup-ninja@v5 | |
| - name: Configure CMake (Windows) | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Force -Path logs | Out-Null | |
| Write-Host "Configuring with preset: ${{ inputs.preset }}" | |
| cmake --preset ${{ inputs.preset }} 2>&1 | Tee-Object -FilePath logs/configure_windows.log | |
| $status = $LASTEXITCODE | |
| if ($status -ne 0) { | |
| Write-Host "CMake configuration failed; last 50 lines:" | |
| Get-Content logs/configure_windows.log | Select-Object -Last 50 | |
| exit $status | |
| } | |
| Write-Host "CMake configuration complete." | |
| - name: Build ${{ inputs.game }} | |
| shell: pwsh | |
| run: | | |
| New-Item -ItemType Directory -Force -Path logs | Out-Null | |
| $jobs = [Environment]::ProcessorCount | |
| Write-Host "Building with $jobs parallel jobs..." | |
| if ("${{ inputs.game }}" -eq "GeneralsMD") { | |
| cmake --build build/${{ inputs.preset }} --target z_generals -j $jobs 2>&1 | | |
| Tee-Object -FilePath logs/build_zh_windows.log | |
| $status = $LASTEXITCODE | |
| $logFile = "logs/build_zh_windows.log" | |
| } else { | |
| cmake --build build/${{ inputs.preset }} --target g_generals -j $jobs 2>&1 | | |
| Tee-Object -FilePath logs/build_generals_windows.log | |
| $status = $LASTEXITCODE | |
| $logFile = "logs/build_generals_windows.log" | |
| } | |
| if ($status -eq 0) { | |
| Write-Host "Build completed successfully." | |
| } else { | |
| Write-Host "Build failed; last 100 lines of $logFile :" | |
| Get-Content $logFile | Select-Object -Last 100 | |
| exit $status | |
| } | |
| - name: Verify Build Artifacts | |
| shell: pwsh | |
| run: | | |
| if ("${{ inputs.game }}" -eq "GeneralsMD") { | |
| $binary = "build/${{ inputs.preset }}/GeneralsMD/GeneralsXZH.exe" | |
| $displayName = "GeneralsXZH.exe" | |
| } else { | |
| $binary = "build/${{ inputs.preset }}/Generals/GeneralsX.exe" | |
| $displayName = "GeneralsX.exe" | |
| } | |
| if (Test-Path $binary) { | |
| $sizeMB = [Math]::Round((Get-Item $binary).Length / 1MB, 2) | |
| Write-Host "Binary built: $displayName ($sizeMB MB)" | |
| } else { | |
| Write-Host "Binary NOT found: $binary" | |
| Write-Host "Listing build output directory:" | |
| Get-ChildItem "build/${{ inputs.preset }}" -Recurse -Filter "*.exe" -ErrorAction SilentlyContinue | | |
| Format-Table FullName, Length -AutoSize | |
| exit 1 | |
| } | |
| - name: Deploy Bundle (Binary + DLLs) | |
| if: success() | |
| shell: pwsh | |
| run: | | |
| if ("${{ inputs.game }}" -eq "GeneralsMD") { | |
| $binary = "build/${{ inputs.preset }}/GeneralsMD/GeneralsXZH.exe" | |
| } else { | |
| $binary = "build/${{ inputs.preset }}/Generals/GeneralsX.exe" | |
| } | |
| $deployDir = "$env:RUNNER_TEMP\GeneralsX-${{ inputs.game }}-deploy" | |
| New-Item -ItemType Directory -Force -Path $deployDir | Out-Null | |
| Write-Host "Creating deployment bundle at: $deployDir" | |
| # Executable | |
| Copy-Item $binary $deployDir -Force | |
| Write-Host " Copied executable" | |
| # DXVK DLLs (Windows pre-built x64 release) | |
| $dxvkDir = "build/${{ inputs.preset }}/_deps/dxvk_win_release-src/x64" | |
| if (Test-Path $dxvkDir) { | |
| foreach ($dll in @("d3d8.dll","d3d9.dll","d3d10core.dll","d3d11.dll","dxgi.dll")) { | |
| $src = Join-Path $dxvkDir $dll | |
| if (Test-Path $src) { Copy-Item $src $deployDir -Force; Write-Host " Copied $dll" } | |
| } | |
| } else { | |
| Write-Host " DXVK directory not found (will be fetched on configure): $dxvkDir" | |
| } | |
| # SDL3.dll | |
| $sdl3Dll = "build/${{ inputs.preset }}/_deps/sdl3-build/SDL3.dll" | |
| if (Test-Path $sdl3Dll) { | |
| Copy-Item $sdl3Dll $deployDir -Force | |
| Write-Host " Copied SDL3.dll" | |
| } | |
| # GeneralsX @bugfix felipebraz 05/03/2026 Include optional SDL3_image runtime DLL in CI bundle when available. | |
| $sdl3ImageDll = "build/${{ inputs.preset }}/_deps/SDL3_image-build/SDL3_image.dll" | |
| if (Test-Path $sdl3ImageDll) { | |
| Copy-Item $sdl3ImageDll $deployDir -Force | |
| Write-Host " Copied SDL3_image.dll" | |
| } else { | |
| Write-Host " SDL3_image.dll not found (optional)" | |
| } | |
| # OpenAL32.dll | |
| $openalDll = Get-ChildItem "build/${{ inputs.preset }}/_deps" ` | |
| -Filter "OpenAL32.dll" -Recurse -ErrorAction SilentlyContinue | Select-Object -First 1 | |
| if ($openalDll) { | |
| Copy-Item $openalDll.FullName $deployDir -Force | |
| Write-Host " Copied OpenAL32.dll" | |
| } | |
| # GeneralsX @bugfix felipebraz 05/03/2026 Include optional FFmpeg runtime DLLs to match local deploy behavior. | |
| $targetDir = if ("${{ inputs.game }}" -eq "GeneralsMD") { "GeneralsMD" } else { "Generals" } | |
| $buildGameDir = "build/${{ inputs.preset }}/$targetDir" | |
| Get-ChildItem $buildGameDir -Filter "av*.dll" -ErrorAction SilentlyContinue | ForEach-Object { | |
| Copy-Item $_.FullName $deployDir -Force | |
| Write-Host " Copied $($_.Name)" | |
| } | |
| Get-ChildItem $buildGameDir -Filter "sw*.dll" -ErrorAction SilentlyContinue | ForEach-Object { | |
| Copy-Item $_.FullName $deployDir -Force | |
| Write-Host " Copied $($_.Name)" | |
| } | |
| # GeneralsX @bugfix felipebraz 05/03/2026 Copy optional dxvk.conf for consistent runtime defaults. | |
| if (Test-Path "dxvk.conf") { | |
| Copy-Item "dxvk.conf" $deployDir -Force | |
| Write-Host " Copied dxvk.conf" | |
| } | |
| Write-Host "Bundle ready at: $deployDir" | |
| Get-ChildItem $deployDir | Format-Table Name, Length -AutoSize | |
| $archivePath = "$env:RUNNER_TEMP\bundle-windows-${{ inputs.game }}-${{ inputs.preset }}.zip" | |
| Write-Host "Creating archive: $archivePath" | |
| Compress-Archive -Path "$deployDir\*" -DestinationPath $archivePath -Force | |
| $sizeMB = [Math]::Round((Get-Item $archivePath).Length / 1MB, 2) | |
| Write-Host "Archive size: $sizeMB MB" | |
| - name: Upload Build Logs | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: build-logs-windows-${{ inputs.game }} | |
| path: logs/ | |
| retention-days: 7 | |
| - name: Upload Deployment Bundle | |
| if: success() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: bundle-windows-${{ inputs.game }}-${{ inputs.preset }}.zip | |
| path: ${{ runner.temp }}/bundle-windows-${{ inputs.game }}-${{ inputs.preset }}.zip | |
| retention-days: 7 | |
| if-no-files-found: warn |