Files
zoitechat/.github/workflows/windows-arm64-msys2.yml
Workflow config file is invalid. Please check your config file: yaml: line 234: could not find expected ':'
2026-01-12 21:14:58 -07:00

311 lines
10 KiB
YAML

name: Windows ARM64 Installer (MSYS2 + Inno Setup)
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
workflow_dispatch: {}
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"
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__)"
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
$projectDirArg = ($projectDir.TrimEnd('\') + "\\")
"PROJECTDIR=$projectDirArg" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
$text = Get-Content $issIn -Raw
$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;
"@
$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 }}