From 2db3991c7f6cbe5b21bc0b284ff343c10f8f8d65 Mon Sep 17 00:00:00 2001 From: Final AI Agent Date: Mon, 3 Aug 2026 20:19:40 +0000 Subject: [PATCH 1/3] ci: add native Windows ARM64 build --- .github/workflows/ci.yml | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0907a639b7..dfd41a00af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,7 @@ jobs: - name: Windows MSVC Release os: windows-latest msvc: true + package: true devenv: | Import-Module "$env:VS\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" Enter-VsDevShell -VsInstallPath $env:VS -SkipAutomaticLocation -DevCmdArguments "-arch=x64 -host_arch=x64" @@ -38,6 +39,28 @@ jobs: -Dfribidi:tests=false -Dfribidi:docs=false -Dlibass:fontconfig=disabled + - name: Windows ARM64 MSVC Release + os: windows-11-arm + msvc: true + package: false + devenv: | + Import-Module "$env:VS\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" + Enter-VsDevShell -VsInstallPath $env:VS -SkipAutomaticLocation -DevCmdArguments "-arch=arm64 -host_arch=arm64" + buildtype: release + args: >- + -Ddefault_library=static + --force-fallback-for=zlib,harfbuzz,freetype2,fribidi,libpng + -Dfallback_nasm=true + -Dfreetype2:harfbuzz=disabled + -Dharfbuzz:freetype=disabled + -Dharfbuzz:cairo=disabled + -Dharfbuzz:glib=disabled + -Dharfbuzz:gobject=disabled + -Dharfbuzz:tests=disabled + -Dharfbuzz:docs=disabled + -Dfribidi:tests=false + -Dfribidi:docs=false + -Dlibass:fontconfig=disabled #- { # name: Windows MinGW, # os: windows-latest, @@ -92,7 +115,7 @@ jobs: - name: Setup Meson run: | python -m pip install --upgrade pip setuptools - pip install meson + pip install meson ninja # Taken from https://github.com/libass/libass/blob/0.17.5/.github/workflows/meson.yml#L118-L125 - name: Find Visual Studio @@ -105,9 +128,9 @@ jobs: "VS=$vsPath" >> $env:GITHUB_ENV - name: Install dependencies (Windows) - if: matrix.config.os == 'windows-latest' + if: startsWith(matrix.config.os, 'windows-') run: | - choco install ninja innosetup + if ('${{ matrix.config.package }}' -eq 'true') { choco install innosetup } $moonscripturl = "https://github.com/leafo/moonscript/releases/download/v0.6.0/moonscript-v0.6.0-windows-x86_64.zip" mkdir moonscript @@ -170,7 +193,7 @@ jobs: # Windows artifacts - name: Generate Windows installer - if: matrix.config.os == 'windows-latest' + if: matrix.config.package env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | @@ -178,14 +201,14 @@ jobs: meson compile win-installer -C build - name: Generate Windows portable installer - if: matrix.config.os == 'windows-latest' + if: matrix.config.package run: | ${{ matrix.config.devenv }} cd build && ninja win-portable - name: Upload artifacts - win_installer uses: actions/upload-artifact@v6 - if: matrix.config.os == 'windows-latest' + if: matrix.config.package with: name: ${{ matrix.config.name }} - installer path: build/Aegisub-*.exe @@ -193,7 +216,7 @@ jobs: - name: Upload artifacts - portable.zip uses: actions/upload-artifact@v6 - if: matrix.config.os == 'windows-latest' + if: matrix.config.package with: name: ${{ matrix.config.name }} - portable path: build/aegisub-portable-64.zip From bde6dbe7975b0914ed558e38ee2a4db2baa4f1ad Mon Sep 17 00:00:00 2001 From: Final AI Agent Date: Mon, 3 Aug 2026 20:52:03 +0000 Subject: [PATCH 2/3] ci: package Windows ARM64 builds --- .github/workflows/ci.yml | 11 ++++++++--- packages/meson.build | 5 +++-- packages/win_installer/aegisub3.iss | 11 ++++++++++- packages/win_installer/fragment_codecs.iss | 2 ++ packages/win_installer/fragment_runtimes.iss | 4 ++-- packages/win_installer/fragment_setupbase.iss | 4 ++++ .../win_installer/portable/create-portable.ps1 | 18 +++++++++++++----- tools/win-installer-setup.ps1 | 15 +++++++++++---- 8 files changed, 53 insertions(+), 17 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dfd41a00af..cec68fd965 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,8 @@ jobs: - name: Windows MSVC Release os: windows-latest msvc: true + arch: x64 + vs_component: Microsoft.VisualStudio.Component.VC.Tools.x86.x64 package: true devenv: | Import-Module "$env:VS\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" @@ -42,7 +44,9 @@ jobs: - name: Windows ARM64 MSVC Release os: windows-11-arm msvc: true - package: false + arch: arm64 + vs_component: Microsoft.VisualStudio.Component.VC.Tools.ARM64 + package: true devenv: | Import-Module "$env:VS\Common7\Tools\Microsoft.VisualStudio.DevShell.dll" Enter-VsDevShell -VsInstallPath $env:VS -SkipAutomaticLocation -DevCmdArguments "-arch=arm64 -host_arch=arm64" @@ -61,6 +65,7 @@ jobs: -Dfribidi:tests=false -Dfribidi:docs=false -Dlibass:fontconfig=disabled + -Dcsri=disabled #- { # name: Windows MinGW, # os: windows-latest, @@ -122,7 +127,7 @@ jobs: if: matrix.config.msvc run: | $vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" - $vsPath = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath + $vsPath = & $vswhere -latest -products * -requires ${{ matrix.config.vs_component }} -property installationPath if (-not $vsPath) { throw "Could not find a Visual Studio installation" } "VS=$vsPath" "VS=$vsPath" >> $env:GITHUB_ENV @@ -219,7 +224,7 @@ jobs: if: matrix.config.package with: name: ${{ matrix.config.name }} - portable - path: build/aegisub-portable-64.zip + path: build/aegisub-portable-${{ matrix.config.arch }}.zip # macOS artifacts - name: Generate macOS installer diff --git a/packages/meson.build b/packages/meson.build index 49de536885..e88f6bef55 100644 --- a/packages/meson.build +++ b/packages/meson.build @@ -1,16 +1,17 @@ conf_pkg = configuration_data() if host_machine.system() == 'windows' + package_arch = host_machine.cpu_family() == 'aarch64' ? 'arm64' : 'x64' installer_setup = [powershell_exe, '-ExecutionPolicy', 'Bypass', '-File', meson.project_source_root() / 'tools/win-installer-setup.ps1'] run_target('win-installer', - command: [installer_setup, meson.project_build_root(), meson.project_source_root()]) + command: [installer_setup, meson.project_build_root(), meson.project_source_root(), package_arch]) portable_setup = [powershell_exe, '-ExecutionPolicy', 'Bypass', '-File', meson.project_source_root() / 'packages/win_installer/portable/create-portable.ps1'] - run_target('win-portable', command: [portable_setup, meson.project_build_root(), meson.project_source_root()]) + run_target('win-portable', command: [portable_setup, meson.project_build_root(), meson.project_source_root(), package_arch]) elif host_machine.system() == 'darwin' fontconfig_conf = run_command('pkg-config', '--variable=confdir', 'fontconfig').stdout().strip() bundle_app_sh = find_program(meson.project_source_root() / 'tools/osx-bundle.sh') diff --git a/packages/win_installer/aegisub3.iss b/packages/win_installer/aegisub3.iss index de510ed6c0..3f6f48278f 100644 --- a/packages/win_installer/aegisub3.iss +++ b/packages/win_installer/aegisub3.iss @@ -1,4 +1,8 @@ -#define ARCH 64 +#ifdef ARM64 +#define ARCH "arm64" +#else +#define ARCH "x64" +#endif #include "fragment_setupbase.iss" #include "fragment_strings.iss" @@ -7,8 +11,13 @@ AppID={{24BC8B57-716C-444F-B46B-A3349B9164C5} DefaultDirName={commonpf}\Aegisub PrivilegesRequired=poweruser +#ifdef ARM64 +ArchitecturesInstallIn64BitMode=arm64 +ArchitecturesAllowed=arm64 +#else ArchitecturesInstallIn64BitMode=x64compatible ArchitecturesAllowed=x64compatible +#endif #include "fragment_mainprogram.iss" #include "fragment_associations.iss" diff --git a/packages/win_installer/fragment_codecs.iss b/packages/win_installer/fragment_codecs.iss index 7d0bf740ae..95f340ae8d 100644 --- a/packages/win_installer/fragment_codecs.iss +++ b/packages/win_installer/fragment_codecs.iss @@ -4,4 +4,6 @@ ; DestDir: {app}; Source: {#DEPS_DIR}\AvisynthPlus64\x64\Output\AviSynth.dll; Flags: ignoreversion; Components: main ; DestDir: {app}; Source: {#DEPS_DIR}\AvisynthPlus64\x64\Output\plugins\DirectShowSource.dll; Flags: ignoreversion; Components: main ; VSFilter +#ifndef ARM64 DestDir: {app}\csri; Source: {#DEPS_DIR}\VSFilter\x64\VSFilter.dll; Flags: ignoreversion; Components: main +#endif diff --git a/packages/win_installer/fragment_runtimes.iss b/packages/win_installer/fragment_runtimes.iss index c7c69762fb..3db18cfe3f 100644 --- a/packages/win_installer/fragment_runtimes.iss +++ b/packages/win_installer/fragment_runtimes.iss @@ -1,7 +1,7 @@ ; This file implements checking for and installing runtime libraries for Aegisub [Files] -DestDir: {tmp}; Source: "{#DEPS_DIR}\VC_redist\VC_redist.x{#ARCH}.exe"; Flags: nocompression deleteafterinstall +DestDir: {tmp}; Source: "{#DEPS_DIR}\VC_redist\VC_redist.{#ARCH}.exe"; Flags: nocompression deleteafterinstall [Run] -Filename: {tmp}\VC_redist.x{#ARCH}.exe; StatusMsg: {cm:InstallRuntime}; Parameters: "/install /quiet /norestart" +Filename: {tmp}\VC_redist.{#ARCH}.exe; StatusMsg: {cm:InstallRuntime}; Parameters: "/install /quiet /norestart" diff --git a/packages/win_installer/fragment_setupbase.iss b/packages/win_installer/fragment_setupbase.iss index af8ca018ed..254cf7854f 100644 --- a/packages/win_installer/fragment_setupbase.iss +++ b/packages/win_installer/fragment_setupbase.iss @@ -35,7 +35,11 @@ UninstallDisplayIcon={app}\aegisub.exe WizardImageFile={#INSTALLER_DIR}\welcome-large.bmp WizardSmallImageFile={#INSTALLER_DIR}\aegisub-large.bmp +#ifdef ARM64 +OutputBaseFilename=Aegisub-{#BUILD_GIT_VERSION_STRING}-arm64 +#else OutputBaseFilename=Aegisub-{#BUILD_GIT_VERSION_STRING} +#endif VersionInfoDescription=Aegisub {#BUILD_GIT_VERSION_STRING} [Languages] diff --git a/packages/win_installer/portable/create-portable.ps1 b/packages/win_installer/portable/create-portable.ps1 index 84123cc178..f966f6896f 100644 --- a/packages/win_installer/portable/create-portable.ps1 +++ b/packages/win_installer/portable/create-portable.ps1 @@ -6,7 +6,10 @@ param ( [string]$BuildRoot, [Parameter(Position = 1, Mandatory = $true)] [ValidateNotNullOrEmpty()] - [string]$SourceRoot + [string]$SourceRoot, + [Parameter(Position = 2, Mandatory = $true)] + [ValidateSet('x64', 'arm64')] + [string]$Architecture ) $ErrorActionPreference = 'Stop' @@ -38,7 +41,7 @@ Write-Host "SOURCE_ROOT=$SourceRoot" $InstallerDir = Join-Path $BuildRoot "install" $InstallerDepsDir = Join-Path $BuildRoot "installer-deps" $PortableOutputDir = Join-Path $BuildRoot "aegisub-portable" -$PortableZipPath = Join-Path $BuildRoot "aegisub-portable-64.zip" +$PortableZipPath = Join-Path $BuildRoot "aegisub-portable-$Architecture.zip" Write-Step 'Removing previous output' Remove-Item -LiteralPath $PortableOutputDir -Force -Recurse -ErrorAction SilentlyContinue @@ -63,11 +66,16 @@ Copy-ToDirectory $InstallerDepsDir\dictionaries\en_US.dic $PortableOutputDir\di # Copy-ToDirectory $InstallerDepsDir\AvisynthPlus64\x64\Output\AviSynth.dll $PortableOutputDir # Copy-ToDirectory $InstallerDepsDir\AvisynthPlus64\x64\Output\plugins\DirectShowSource.dll $PortableOutputDir -Write-Step 'Copying VSFilter' -Copy-ToDirectory $InstallerDepsDir\VSFilter\x64\VSFilter.dll $PortableOutputDir\csri +if ($Architecture -eq 'x64') { + Write-Step 'Copying VSFilter' + Copy-ToDirectory $InstallerDepsDir\VSFilter\x64\VSFilter.dll $PortableOutputDir\csri +} +else { + Write-Step 'Skipping VSFilter (not available for ARM64)' +} Write-Step 'Copying VC++ runtime' -Copy-ToDirectory $InstallerDepsDir\VC_redist\VC_redist.x64.exe $PortableOutputDir\Microsoft.CRT +Copy-ToDirectory (Join-Path $InstallerDepsDir "VC_redist\VC_redist.$Architecture.exe") $PortableOutputDir\Microsoft.CRT Write-Step 'Copying automation' Copy-ToDirectory "$InstallerDir\share\aegisub\automation\*" "$PortableOutputDir\automation\" -Recurse diff --git a/tools/win-installer-setup.ps1 b/tools/win-installer-setup.ps1 index 857a3bcd61..d702734191 100644 --- a/tools/win-installer-setup.ps1 +++ b/tools/win-installer-setup.ps1 @@ -7,6 +7,9 @@ param ( [Parameter(Position = 1, Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$SourceRoot, + [Parameter(Position = 2, Mandatory = $true)] + [ValidateSet('x64', 'arm64')] + [string]$Architecture, [ValidateNotNullOrEmpty()] [string]$DepCtrlVersion = "0.8.1" ) @@ -92,9 +95,9 @@ if ((Get-CachedDepCtrlVersion $DepCtrlDir) -ne $DepCtrlVersion) { # Remove-Item $avsArchive # } -# VSFilter +# VSFilter has no ARM64 build; libass remains the subtitle renderer there. $VSFilterDir = Join-Path $DepsDir "VSFilter" -if (!(Test-Path $VSFilterDir)) { +if ($Architecture -eq 'x64' -and !(Test-Path $VSFilterDir)) { New-Item -ItemType Directory -Path $VSFilterDir | Out-Null $vsFilterReleases = Invoke-WebRequest "https://api.github.com/repos/pinterf/xy-VSFilter/releases/latest" -Headers $GitHeaders -UseBasicParsing | ConvertFrom-Json $vsFilterUrl = $vsFilterReleases.assets[0].browser_download_url @@ -108,7 +111,8 @@ if (!(Test-Path $VSFilterDir)) { $RedistDir = Join-Path $DepsDir "VC_redist" if (!(Test-Path $RedistDir)) { New-Item -ItemType Directory -Path $RedistDir | Out-Null - Invoke-WebRequest https://aka.ms/vs/17/release/VC_redist.x64.exe -OutFile (Join-Path $RedistDir "VC_redist.x64.exe") -UseBasicParsing + $redistUrl = "https://aka.ms/vc14/vc_redist.$Architecture.exe" + Invoke-WebRequest $redistUrl -OutFile (Join-Path $RedistDir "VC_redist.$Architecture.exe") -UseBasicParsing } # Dictionaries @@ -139,5 +143,8 @@ if(!$?) { Exit $LASTEXITCODE } # Invoke InnoSetup $IssUrl = Join-Path $InstallerDir "aegisub_depctrl.iss" -iscc $IssUrl +$isccArgs = @() +if ($Architecture -eq 'arm64') { $isccArgs += '/DARM64' } +$isccArgs += $IssUrl +iscc @isccArgs if(!$?) { Exit $LASTEXITCODE } From 4fbbd1a4fc37815b62a083f1cdb12f27116cc85f Mon Sep 17 00:00:00 2001 From: Final AI Agent Date: Tue, 4 Aug 2026 18:08:11 +0000 Subject: [PATCH 3/3] ci: install gas-preprocessor for Windows ARM64 --- .github/workflows/ci.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cec68fd965..d82ac75919 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -174,6 +174,23 @@ jobs: sudo apt-get install -y lua5.1 liblua5.1-0-dev luarocks sudo luarocks --lua-version=5.1 install busted + # dav1d's ARM assembly uses GNU syntax, which MSVC's armasm64 cannot + # consume directly. gas-preprocessor translates it during the build. + - name: Checkout gas-preprocessor (Windows ARM64) + if: matrix.config.msvc && matrix.config.arch == 'arm64' + uses: actions/checkout@v6 + with: + repository: FFmpeg/gas-preprocessor + ref: ac1836309c2e77023c228b7184485597286289d3 + path: gas-preprocessor + + - name: Setup gas-preprocessor (Windows ARM64) + if: matrix.config.msvc && matrix.config.arch == 'arm64' + run: | + $gaspp = (Resolve-Path gas-preprocessor).Path + $gaspp | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append + perl -c "$gaspp\gas-preprocessor.pl" + - name: Configure run: | ${{ matrix.config.devenv }}