Files
zoitechat/.github/workflows/windows-arm64-msys2.yml
Workflow config file is invalid. Please check your config file: yaml: line 238: could not find expected ':'
deepend-tildeclub 3f9bb8ffd4 Refactor Windows ARM64 build workflow
Updated Windows ARM64 build workflow to include Python and CFFI installation, modified paths for Inno Setup, and added error handling for missing files.
2026-01-12 21:04:27 -07:00

321 lines
11 KiB
YAML

name: Windows ARM64 Installer (MSYS2 + Inno Setup)
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
windows_arm64_installer:
runs-on: windows-11-arm
steps:
- uses: actions/checkout@v4
- uses: msys2/setup-msys2@v2
with:
msystem: CLANGARM64
update: true
install: >-
git
mingw-w64-clang-aarch64-toolchain
mingw-w64-clang-aarch64-meson
mingw-w64-clang-aarch64-ninja
mingw-w64-clang-aarch64-pkgconf
mingw-w64-clang-aarch64-gettext-tools
mingw-w64-clang-aarch64-libxml2
mingw-w64-clang-aarch64-winpthreads
mingw-w64-clang-aarch64-python
mingw-w64-clang-aarch64-python-cffi
mingw-w64-clang-aarch64-gtk2
mingw-w64-clang-aarch64-gtk-update-icon-cache
mingw-w64-clang-aarch64-luajit
mingw-w64-clang-aarch64-desktop-file-utils
mingw-w64-clang-aarch64-ntldd
- name: Configure
shell: msys2 {0}
run: |
set -euxo pipefail
export PATH="/clangarm64/bin:$PATH"
export MSGFMT="/clangarm64/bin/msgfmt"
export GETTEXTDATADIR="/clangarm64/share/gettext"
# Defensive: ensure python + cffi exist even if the setup action had a bad day
pacman -S --noconfirm --needed mingw-w64-clang-aarch64-python mingw-w64-clang-aarch64-python-cffi
rm -rf build dist
mkdir -p dist
meson setup build \
--prefix=/ \
--bindir=bin \
--libdir=lib \
--datadir=share \
-Dtext-frontend=true \
-Ddbus=disabled \
-Dwith-upd=false \
-Dwith-perl=false \
-Dc_link_args="-pthread -lwinpthread" \
-Dcpp_link_args="-pthread -lwinpthread"
/clangarm64/bin/python.exe -c "import sys, cffi; print('python:', sys.version); print('cffi:', cffi.__version__)"
# Export app version from Meson for the Inno script defines
APPVER="$(meson introspect build --projectinfo | /clangarm64/bin/python.exe -c 'import json,sys; print(json.load(sys.stdin)[\"version\"])')"
echo "APPVER=$APPVER" >> "$GITHUB_ENV"
echo "Meson APPVER=$APPVER"
- name: Build
shell: msys2 {0}
run: |
set -euxo pipefail
export PATH="/clangarm64/bin:$PATH"
ninja -C build
- name: Test
shell: msys2 {0}
run: |
set -euxo pipefail
export PATH="/clangarm64/bin:$PATH"
ninja -C build test || true
- name: Stage install
shell: msys2 {0}
run: |
set -euxo pipefail
export PATH="/clangarm64/bin:$PATH"
DESTDIR="$PWD/dist" ninja -C build install
echo "Installed files (debug):"
find dist -maxdepth 8 -type f \( -iname 'zoitechat*.exe' -o -iname '*.dll' \) -print || true
- name: Harvest runtime DLL dependencies
shell: msys2 {0}
run: |
set -euxo pipefail
export PATH="/clangarm64/bin:$PATH"
shopt -s nullglob
mapfile -t targets < <(find dist -type f \( -iname 'zoitechat*.exe' -o -ipath '*/plugins/*.dll' \) 2>/dev/null || true)
if [ "${#targets[@]}" -eq 0 ]; then
echo "No installed binaries/plugins found under dist/ (skipping dep harvest)"
exit 0
fi
mainexe="$(printf '%s\n' "${targets[@]}" | grep -iE '/zoitechat\.exe$' | head -n1 || true)"
if [ -z "$mainexe" ]; then
echo "zoitechat.exe not found under dist/; skipping dep harvest"
exit 0
fi
bindir="$(dirname "$mainexe")"
echo "Using bindir: $bindir"
for f in "${targets[@]}"; do
deps="$(ntldd -R "$f" 2>/dev/null || true)"
[ -n "$deps" ] || continue
while IFS= read -r dll; do
[ -n "$dll" ] || continue
cp -n "$dll" "$bindir/" || true
done < <(
printf '%s\n' "$deps" \
| tr '\\' '/' \
| awk '{print $1}' \
| grep -E '^/clangarm64/(bin|lib)/.*\.dll$' \
|| true
)
done
- name: Prepare Inno Setup source tree (win32/rel)
shell: msys2 {0}
run: |
set -euxo pipefail
export PATH="/clangarm64/bin:$PATH"
rm -rf win32/rel
mkdir -p win32/rel
app_exe="$(find dist -type f -iname 'zoitechat.exe' | head -n1 || true)"
if [ -z "$app_exe" ]; then
echo "zoitechat.exe not found under dist/; cannot build installer."
find dist -maxdepth 8 -type f -print || true
exit 1
fi
bin_dir="$(dirname "$app_exe")"
install_root="$(cd "$bin_dir/.." && pwd)"
echo "app_exe: $app_exe"
echo "install_root: $install_root"
cp -a "$install_root/." win32/rel/
echo "win32/rel contents (debug):"
find win32/rel -maxdepth 5 -type f \( -iname 'zoitechat*.exe' -o -iname '*.dll' \) -print || true
- name: Install Inno Setup (find real ISCC.exe)
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
if (-not (Get-Command choco.exe -ErrorAction SilentlyContinue)) {
Write-Host "Chocolatey not found; installing..."
Set-ExecutionPolicy Bypass -Scope Process -Force
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072
iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
}
choco install innosetup -y --force --no-progress | Out-Host
$candidates = @()
$pf = ${env:ProgramFiles}
$pfx86 = ${env:ProgramFiles(x86)}
if ($pf) { $candidates += (Join-Path $pf "Inno Setup 6\ISCC.exe") }
if ($pfx86) { $candidates += (Join-Path $pfx86 "Inno Setup 6\ISCC.exe") }
$chocoRoot = ${env:ChocolateyInstall}
if ($chocoRoot -and (Test-Path $chocoRoot)) {
$candidates += (Join-Path $chocoRoot "lib\innosetup\tools\ISCC.exe")
$candidates += (Get-ChildItem -Path (Join-Path $chocoRoot "lib\innosetup") -Recurse -Filter "ISCC.exe" -ErrorAction SilentlyContinue |
Where-Object { $_.FullName -notmatch '\\chocolatey\\bin\\' } |
Select-Object -ExpandProperty FullName -First 10)
}
$regKeys = @(
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 6_is1",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Inno Setup 6_is1"
)
foreach ($k in $regKeys) {
try {
$loc = (Get-ItemProperty -Path $k -ErrorAction Stop).InstallLocation
if ($loc) { $candidates += (Join-Path $loc "ISCC.exe") }
} catch {}
}
$iscc = $candidates | Where-Object { $_ -and (Test-Path $_) } | Select-Object -First 1
if (-not $iscc) {
Write-Host "Checked candidates:"
$candidates | ForEach-Object { Write-Host " - $_" }
throw "ISCC.exe not found after install attempts."
}
Write-Host "Using ISCC:" $iscc
(Get-Item $iscc).VersionInfo | Select-Object ProductVersion, FileVersion | Format-List | Out-Host
"ISCC_PATH=$iscc" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
- name: Patch ARM64 .iss for CI (disable missing idp.iss)
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$issIn = "win32\installer\zoitechat-arm64.iss"
if (-not (Test-Path $issIn)) {
throw "Missing: $issIn"
}
$projectDir = (Resolve-Path "win32\installer").Path
# double trailing backslash avoids Windows arg-quoting weirdness, and still works as a path
$projectDirArg = ($projectDir.TrimEnd('\') + "\\")
"PROJECTDIR=$projectDirArg" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
$text = Get-Content $issIn -Raw
# Comment out the IDP include (it isn't present on the runner; and IDP plugin support on ARM64 is not reliable)
$text = [regex]::Replace($text, '^\s*#include\s+<idp\.iss>\s*$', '; CI: idp.iss disabled for ARM64 builds', 'Multiline')
if ($text -notmatch '; CI: IDP STUBS') {
$stub = @"
; CI: IDP STUBS (no-op on ARM64 CI)
procedure idpDownloadAfter(PageID: Integer);
begin
end;
procedure idpClearFiles;
begin
end;
procedure idpAddFile(const Url, DestFile: string);
begin
end;
procedure idpAddFileComp(const Url, DestFile: string; const Components: string);
begin
end;
procedure idpAddFileSize(const Url, DestFile: string; const Size: Int64);
begin
end;
procedure idpAddFileSizeComp(const Url, DestFile: string; const Size: Int64; const Components: string);
begin
end;
function idpDownloadFiles: Boolean;
begin
Result := True;
end;
"@
# Inject stubs immediately after the [Code] header (so [Setup] stays first)
$text = [regex]::Replace($text, '(\[Code\]\s*\r?\n)', "`$1$stub", 'Singleline')
}
$issOut = "win32\installer\zoitechat-arm64.ci.iss"
Set-Content -Path $issOut -Value $text -Encoding UTF8
Write-Host "Wrote patched CI script: $issOut"
- name: Build ARM64 installer
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$iscc = $env:ISCC_PATH
if (-not $iscc -or -not (Test-Path $iscc)) {
throw "ISCC_PATH missing or invalid."
}
$iss = "win32\installer\zoitechat-arm64.ci.iss"
if (-not (Test-Path $iss)) {
throw "Patched CI script missing: $iss"
}
if (-not $env:APPVER) {
throw "APPVER missing (Meson version export failed)."
}
if (-not $env:PROJECTDIR) {
throw "PROJECTDIR missing."
}
& $iscc "/DAPPARCH=arm64" "/DAPPVER=$env:APPVER" "/DPROJECTDIR=$env:PROJECTDIR" $iss | Out-Host
if ($LASTEXITCODE -ne 0) {
throw "ISCC failed with exit code $LASTEXITCODE"
}
$exe = Get-ChildItem -Path "win32" -Recurse -Filter "*.exe" |
Where-Object { $_.Name -match 'Setup' -or $_.Name -match 'Installer' } |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1
if (-not $exe) {
Write-Host "win32 tree (debug):"
Get-ChildItem -Path "win32" -Recurse -Depth 4 | Select-Object FullName | Out-Host
throw "Installer exe not found under win32/"
}
Write-Host "Installer built:" $exe.FullName
"INSTALLER_EXE=$($exe.FullName)" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
- uses: actions/upload-artifact@v4
with:
name: zoitechat-windows-arm64-installer
path: ${{ env.INSTALLER_EXE }}