name: Windows Build on: push: branches: - master pull_request: branches: - master jobs: windows_build: runs-on: windows-2022 permissions: contents: read id-token: write attestations: write artifact-metadata: write strategy: matrix: platform: [x64, win32] arch: [x64, x86] exclude: - platform: x64 arch: x86 - platform: win32 arch: x64 fail-fast: false steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: '3.14.2' architecture: ${{ matrix.arch }} - name: Install Dependencies run: | New-Item -Name "deps" -ItemType "Directory" New-Item -Path "C:\gtk-build" -ItemType "Directory" -Force | Out-Null Invoke-WebRequest http://files.jrsoftware.org/is/5/innosetup-5.5.9-unicode.exe -OutFile deps\innosetup-unicode.exe & deps\innosetup-unicode.exe /VERYSILENT | Out-Null $isccCandidates = @( (Join-Path ${env:ProgramFiles(x86)} 'Inno Setup 5\iscc.exe'), (Join-Path ${env:ProgramFiles(x86)} 'Inno Setup 6\iscc.exe'), (Join-Path $env:ProgramFiles 'Inno Setup 5\iscc.exe'), (Join-Path $env:ProgramFiles 'Inno Setup 6\iscc.exe') ) | Where-Object { $_ -and (Test-Path $_) } $isccPath = $isccCandidates | Select-Object -First 1 if (-not $isccPath) { $isccCmd = Get-Command iscc.exe -ErrorAction SilentlyContinue if ($isccCmd) { $isccPath = $isccCmd.Source } } if (-not $isccPath) { throw 'Inno Setup compiler (iscc.exe) not found after installer step.' } "ISCC_EXE=$isccPath" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append Invoke-WebRequest https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.17.0/idpsetup-1.5.1.exe -OutFile deps\idpsetup.exe & deps\idpsetup.exe /VERYSILENT Invoke-WebRequest https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.17.0/gendef-20111031.7z -OutFile deps\gendef.7z & 7z.exe x deps\gendef.7z -oC:\gtk-build Invoke-WebRequest https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.17.0/WinSparkle-20151011.7z -OutFile deps\WinSparkle.7z & 7z.exe x deps\WinSparkle.7z -oC:\gtk-build\WinSparkle Invoke-WebRequest https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.17.0/perl-5.20.0-${{ matrix.arch }}.7z -OutFile deps\perl-${{ matrix.arch }}.7z & 7z.exe x deps\perl-${{ matrix.arch }}.7z -oC:\gtk-build\perl-5.20\${{ matrix.platform }} # Resolve python root from setup-python $pyRoot = $env:pythonLocation if (-not $pyRoot) { $pyRoot = & python -c "import sys; print(sys.prefix)" } # Create BOTH paths because the .vcxproj hard-codes python-3.14\... foreach ($pyDir in @("C:\gtk-build\python-3.14.2", "C:\gtk-build\python-3.14")) { New-Item -Path $pyDir -ItemType Directory -Force | Out-Null $target = Join-Path $pyDir "${{ matrix.platform }}" if (Test-Path $target) { Remove-Item $target -Recurse -Force } New-Item -Path $pyDir -Name "${{ matrix.platform }}" -ItemType Junction -Value $pyRoot | Out-Null } python -m pip install --upgrade pip python -m pip install cffi $gtkArchive = "GTK3_Gvsbuild_zoitechat-2.18.0-pre1_${{ matrix.arch }}.7z" Invoke-WebRequest "https://github.com/ZoiteChat/gvsbuild/releases/download/zoitechat-2.18.0-pre1/$gtkArchive" -OutFile deps\gtk.7z if ("${{ matrix.platform }}" -eq "x64") { & 7z.exe x deps\gtk.7z -oC:\gtk-build\gtk\x64\release } else { & 7z.exe x deps\gtk.7z -oC:\gtk-build\gtk\x86\release } if ($LASTEXITCODE -gt 1) { throw "gtk.7z extraction failed with exit code $LASTEXITCODE" } if ("${{ matrix.platform }}" -eq "win32" -and (Test-Path "C:\gtk-build\gtk\x86")) { $gtkRoot = "C:\gtk-build\gtk" foreach ($alias in @("Win32", "win32")) { $aliasPath = Join-Path $gtkRoot $alias if (-not (Test-Path $aliasPath)) { New-Item -Path $aliasPath -ItemType Junction -Value (Join-Path $gtkRoot "x86") | Out-Null } } } - name: Install Lua Dependencies run: | $releaseArch = if ("${{ matrix.arch }}" -eq "x64") { "x64" } else { "x86" } $gtkRelease = "C:\gtk-build\gtk\$releaseArch\release" if (-not (Test-Path $gtkRelease)) { throw "GTK release root '$gtkRelease' is missing before Lua dependency extraction." } $luaArchive = if ($releaseArch -eq "x64") { "gtk-x64-2018-08-29-openssl1.1.7z" } else { "gtk-win32-2018-08-29-openssl1.1.7z" } $luaArchivePath = "deps\$luaArchive" Invoke-WebRequest "https://github.com/zoitechat/gvsbuild/releases/download/zoitechat-2.17.0/$luaArchive" -OutFile $luaArchivePath & 7z.exe x $luaArchivePath -o$gtkRelease include\luajit*\* include\lua*\* lib\lua51.lib lib\luajit*.lib bin\lua51.dll bin\luajit*.dll lib\lua\2.1\* lib\girepository-1.0\*.typelib share\lua\2.1\* -r if ($LASTEXITCODE -gt 1) { throw "Lua dependency extraction failed with exit code $LASTEXITCODE" } - name: Validate Lua Prerequisites run: | $releaseArch = if ("${{ matrix.arch }}" -eq "x64") { "x64" } else { "x86" } $gtkRelease = "C:\gtk-build\gtk\$releaseArch\release" $includeCandidates = @( "include\luajit-2.1\lua.h", "include\luajit\lua.h", "include\lua5.1\lua.h", "include\lua51\lua.h" ) $libCandidates = @( "lib\lua51.lib", "lib\luajit-5.1.lib", "lib\luajit.lib" ) $dllCandidates = @( "bin\lua51.dll", "bin\luajit-5.1.dll", "bin\luajit.dll" ) function Test-AnyPath([string]$root, [string[]]$candidates) { foreach ($candidate in $candidates) { if (Test-Path (Join-Path $root $candidate)) { return $true } } return $false } $missing = New-Object System.Collections.Generic.List[string] if (-not (Test-AnyPath $gtkRelease $includeCandidates)) { $missing.Add("include (expected one of: $($includeCandidates -join ', '))") } if (-not (Test-AnyPath $gtkRelease $libCandidates)) { $missing.Add("lib import library (expected one of: $($libCandidates -join ', '))") } if (-not (Test-AnyPath $gtkRelease $dllCandidates)) { $missing.Add("bin runtime DLL (expected one of: $($dllCandidates -join ', '))") } $lgiNative = Join-Path $gtkRelease "lib\lua\2.1\lgi" if (-not (Test-Path $lgiNative) -or -not (Get-ChildItem $lgiNative -Filter *.dll -File -ErrorAction SilentlyContinue)) { $missing.Add("lib\\lua\\2.1\\lgi\\*.dll") } $typelibDir = Join-Path $gtkRelease "lib\girepository-1.0" if (-not (Test-Path $typelibDir) -or -not (Get-ChildItem $typelibDir -Filter *.typelib -File -ErrorAction SilentlyContinue)) { $missing.Add("lib\\girepository-1.0\\*.typelib") } $lgiShare = Join-Path $gtkRelease "share\lua\2.1\lgi" if (-not (Test-Path $lgiShare) -or -not (Get-ChildItem $lgiShare -Filter *.lua -File -Recurse -ErrorAction SilentlyContinue)) { $missing.Add("share\\lua\\2.1\\lgi\\*.lua") } if ($missing.Count -gt 0) { Write-Error "Lua prerequisites are missing under '$gtkRelease': $($missing -join '; '). Ensure the Lua/LuaJIT dependency artifact for $releaseArch was downloaded and extracted." exit 1 } "LUA_PREREQ_ROOT=$gtkRelease" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" set "PYTHON_DIR=C:\gtk-build\python-3.14.2\${{ matrix.platform }}" if not exist "%PYTHON_DIR%\libs\python314.lib" ( echo Missing %PYTHON_DIR%\libs\python314.lib dir "%PYTHON_DIR%\libs" exit /b 1 ) set "LIB=%PYTHON_DIR%\libs;%LIB%" set "INCLUDE=%PYTHON_DIR%\include;%INCLUDE%" msbuild win32\zoitechat.sln /m /verbosity:minimal /p:Configuration=Release /p:Platform=${{ matrix.platform }} set "PLUGIN_DIR=..\zoitechat-build\${{ matrix.platform }}\rel\plugins" for %%F in (hcchecksum.dll hcexec.dll hcfishlim.dll hcsysinfo.dll hcupd.dll hcwinamp.dll hcperl.dll hcpython3.dll hclua.dll) do ( if not exist "%PLUGIN_DIR%\%%F" ( if /I "%%F"=="hclua.dll" ( echo Missing expected plugin: %PLUGIN_DIR%\%%F echo hclua.dll is built from Lua/LuaJIT prerequisites under %LUA_PREREQ_ROOT%. echo Verify include/lib/bin/share Lua files were present during dependency validation. ) else ( echo Missing expected plugin: %PLUGIN_DIR%\%%F ) exit /b 1 ) ) shell: cmd - name: Preparing Artifacts run: | move ..\zoitechat-build\${{ matrix.platform }}\ZoiteChat*.exe .\ move ..\zoitechat-build .\ shell: cmd - name: Upload Installer id: upload_installer uses: actions/upload-artifact@v4 with: name: Installer ${{ matrix.arch }} path: ZoiteChat*.exe - name: Attest Installer (Artifact Attestation) if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} uses: actions/attest-build-provenance@v3 with: subject-name: Installer ${{ matrix.arch }} subject-digest: sha256:${{ steps.upload_installer.outputs.artifact-digest }} - name: Upload Build Files id: upload_buildfiles uses: actions/upload-artifact@v4 with: name: Build Files ${{ matrix.arch }} path: zoitechat-build - name: Attest Build Files (Artifact Attestation) if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} uses: actions/attest-build-provenance@v3 with: subject-name: Build Files ${{ matrix.arch }} subject-digest: sha256:${{ steps.upload_buildfiles.outputs.artifact-digest }}