diff --git a/.github/workflows/windows-build.yml b/.github/workflows/windows-build.yml index a8a0696d..6d04ca21 100644 --- a/.github/workflows/windows-build.yml +++ b/.github/workflows/windows-build.yml @@ -5,6 +5,8 @@ on: branches: [master] pull_request: branches: [master] + release: + types: [published] workflow_dispatch: inputs: installer: @@ -59,9 +61,18 @@ jobs: with: submodules: recursive + # 3.13 to match the rest of the python plugin's pins: Python3Lib + # (python313) in win32\poxchat.props, the embeddable runtime in + # build-deps.ps1, and the python313.* names in poxchat.iss.tt. cffi is + # both a build dependency (generate_plugin.py renders python.c through + # it) and the source of the _cffi_backend.pyd that copy.vcxproj stages + # out of this interpreter's site-packages. - uses: actions/setup-python@v5 with: - python-version: '3.12' + python-version: '3.13' + + - name: Install cffi + run: python -m pip install --disable-pip-version-check cffi # The whole C:\gtk-build tree: install prefix, intermediates and source # archives. The intermediates belong in here because gvsbuild's @@ -107,20 +118,43 @@ jobs: if (-not $line) { throw 'no version in meson.build' } "version=$($line.Matches[0].Groups[1].Value)" >> $env:GITHUB_OUTPUT - # Split by target so a failure names the piece that broke. perl, python3 - # and htm (the C# theme manager) are left out until the rest is green: - # they need a matching Strawberry Perl / CPython / .NET on the runner. - # lua is out too, for want of a LuaJIT gvsbuild can build -- see - # build-deps.ps1. + # Split by target so a failure names the piece that broke. perl is + # dropped deliberately, htm (the C# theme manager) needs a .NET toolchain + # nobody misses -- neither ships. lua links the LuaJIT that + # build-deps.ps1 installs into the gvsbuild prefix; python3 links + # setup-python's import library and ships the embeddable runtime staged + # below. - name: Build core run: msbuild win32\poxchat.sln ${{ env.MSBUILD_PROPS }} /p:YourPython3Path=$env:pythonLocation /t:"poxchat\common;poxchat\fe-gtk;poxchat\fe-text" - name: Build plugins - run: msbuild win32\poxchat.sln ${{ env.MSBUILD_PROPS }} /p:YourPython3Path=$env:pythonLocation /t:"plugins\checksum;plugins\exec;plugins\fishlim;plugins\sysinfo;plugins\winamp;plugins\upd;plugins\notifications-winrt;external\libenchant_win8" + run: msbuild win32\poxchat.sln ${{ env.MSBUILD_PROPS }} /p:YourPython3Path=$env:pythonLocation /t:"plugins\checksum;plugins\exec;plugins\fishlim;plugins\sysinfo;plugins\winamp;plugins\upd;plugins\notifications-winrt;external\libenchant_win8;scripting\lua;scripting\python3" - name: Stage the distributable tree run: msbuild win32\poxchat.sln ${{ env.MSBUILD_PROPS }} /p:YourPython3Path=$env:pythonLocation /t:"release\nls;release\copy" + # The embeddable package from build-deps.ps1, minus its interpreter + # binaries (scripts run inside poxchat) and its signature catalog. + # Never overwrite: the tree already stages gvsbuild's sqlite3.dll, and + # python's _sqlite3.pyd is happy with any current sqlite beside it. + # Runs before the import check and smoke test so hcpython3.dll's + # python313.dll dependency is judged against the tree that ships. + - name: Stage the Python runtime + run: | + $rel = "${{ env.BUILD_DIR }}\x64\rel" + $skip = 'python.exe', 'pythonw.exe', 'python.cat' + Get-ChildItem C:\gtk-build\python-embed -File | + Where-Object { $skip -notcontains $_.Name } | + ForEach-Object { + $name = if ($_.Name -eq 'LICENSE.txt') { 'PYTHON-LICENSE.txt' } else { $_.Name } + $dest = Join-Path $rel $name + if (Test-Path $dest) { + Write-Host "keeping staged $name" + } else { + Copy-Item $_.FullName $dest + } + } + # The smoke test below proves the tree runs, but STATUS_DLL_NOT_FOUND does # not say which DLL is missing, so name the whole set first -- same # reasoning as the inventory step: one runner cycle per missing file is @@ -180,12 +214,35 @@ jobs: path: ${{ steps.portable.outputs.path }} - name: Build installer - if: inputs.installer + if: inputs.installer || github.event_name == 'release' run: .\win32\ci\make-installer.ps1 -BuildDir "${{ env.BUILD_DIR }}" -Provision - name: Upload installer - if: inputs.installer + if: inputs.installer || github.event_name == 'release' uses: actions/upload-artifact@v4 with: name: poxchat-x64-installer path: ${{ env.BUILD_DIR }}\x64\*.exe + + # Attach the Windows artifacts to the release that triggered the run, the + # same way release.yml attaches the AppImage and debs. A separate job so + # the build keeps its read-only token; only this upload needs write. A + # release run reads the dependency cache from the default branch, so tagging + # after master's own run has completed keeps this off the cold path. + publish: + if: github.event_name == 'release' + needs: build + runs-on: ubuntu-24.04 + permissions: + contents: write + steps: + - uses: actions/download-artifact@v4 + with: + merge-multiple: true + + - name: Upload to the release + uses: softprops/action-gh-release@v2 + with: + files: | + PoxChat-*-portable.zip + PoxChat-*_x64.exe diff --git a/docs/areas/windows-ci-build.md b/docs/areas/windows-ci-build.md index c1098f68..639184fd 100644 --- a/docs/areas/windows-ci-build.md +++ b/docs/areas/windows-ci-build.md @@ -9,7 +9,7 @@ when re-enabling one of the targets it currently leaves out. | Piece | Does | |-------|------| -| `win32/ci/build-deps.ps1` | Builds the whole dependency stack into `C:\gtk-build` — gvsbuild for GTK4/OpenSSL/libxml2/sqlite/libcurl/enchant/gettext, then static jansson and libwebsockets, prebuilt WinSparkle, and the CA bundle | +| `win32/ci/build-deps.ps1` | Builds the whole dependency stack into `C:\gtk-build` — gvsbuild for GTK4/OpenSSL/libxml2/sqlite/libcurl/enchant/gettext, then static jansson and libwebsockets, LuaJIT into the gvsbuild prefix, the CPython embeddable runtime, prebuilt WinSparkle, and the CA bundle | | `win32/ci/check-imports.ps1` | Walks PE imports of the staged tree and names every DLL it is missing | | `win32/ci/make-installer.ps1` | Generates `poxchat.iss` from its template and runs Inno Setup 5 | @@ -71,19 +71,35 @@ prefix is a convenient corpus of real 32- and 64-bit PEs to test against. Watch for PowerShell-vs-C reflexes. `for ($i = 0; $i -lt $n; $i++, $p += 40)` is a parse error: the repeat clause takes one expression, not a comma list. -## Currently left out - -- **lua** — gvsbuild builds LuaJIT by running `.\msvcbuild` through - `CreateProcess`, which cannot launch a `.bat` and finds nothing without the - extension. Taking lua back means building LuaJIT here the way jansson and - libwebsockets are built, and lgi and `--enable-gi` come with it. -- **perl, python3, htm** — need a matching Strawberry Perl / CPython / .NET on - the runner. -- **The installer.** `poxchat.iss.tt` names the lua, perl, python and - thememan payloads unconditionally, across `[Files]`, `[Components]`, - `[Registry]`, `[Run]`, `[Icons]` and the Pascal `[Code]` section. Until - those targets build, `-f installer=true` fails at Inno Setup. The portable - zip uploads before the installer step runs, so this costs nothing else. +## The scripting plugins + +- **lua** builds against a LuaJIT that `build-deps.ps1` compiles itself and + installs into the gvsbuild prefix (gvsbuild's own recipe runs `.\msvcbuild` + through `CreateProcess`, which cannot launch a `.bat`, and fails identically + every time). lgi and `--enable-gi` are deliberately not built — the plugin + needs neither, they only ever provided GObject bindings to Lua scripts. +- **python3** links the import library out of setup-python's install and ships + CPython's *embeddable package*, staged whole into the tree, so users need no + system Python. The plugin is a cffi embedding: `generate_plugin.py` needs + `cffi` in the build interpreter, and at run time `_cffi_backend.pyd` + (staged out of that interpreter's site-packages by `copy.vcxproj`) must sit + on sys.path — the `.` entry in `python313._pth` provides that. + + The Python minor version is pinned in four places that must move together: + `python-version` in the workflow, `Python3Lib` in `win32/poxchat.props`, + `$PythonEmbedVersion`/`$PythonEmbedSha256` in `build-deps.ps1`, and the + `python313.*` names in `poxchat.iss.tt`. + +## Deliberately dropped + +- **perl** — dropped as a supported plugin on Windows; it would need a + matching Strawberry Perl on the runner and on every user's machine. +- **htm / thememan** (the C# theme manager) — needs a .NET toolchain, and the + installer no longer offers it. + +The installer template names only payloads the build produces, so +`-f installer=true` is expected to work; the portable zip still uploads before +the installer step, so an installer failure costs nothing else. ## Traps worth remembering diff --git a/win32/ci/build-deps.ps1 b/win32/ci/build-deps.ps1 index c04a3ec7..609f0630 100644 --- a/win32/ci/build-deps.ps1 +++ b/win32/ci/build-deps.ps1 @@ -8,12 +8,17 @@ solution's UserMacros point at: gtk\\release gvsbuild prefix: GTK4, OpenSSL, libxml2, sqlite, - luajit, libcurl, enchant, and gettext (win32\nls - compiles the .po catalogues with its msgfmt.exe) + libcurl, enchant, and gettext (win32\nls compiles + the .po catalogues with its msgfmt.exe). LuaJIT is + built below and installed into this prefix, which is + where poxchat.props looks for lua51.lib and + include\luajit-2.1 jansson\ static jansson -- DepLibs wants jansson.lib and copy.vcxproj ships no jansson dll libwebsockets\ static libwebsockets, same reasoning WinSparkle\\ prebuilt release, for the upd plugin + python-embed\ CPython embeddable runtime, staged whole into the + tree so the python plugin needs no system Python cert\cacert.pem CA bundle, shipped into the tree as cert.pem Nothing outside -BuildRoot is written, so this is safe to run on a developer @@ -33,6 +38,15 @@ param ( [string] $JanssonTag = 'v2.15.1', [string] $LibWebSocketsTag = 'v4.5.8', [string] $WinSparkleVersion = '0.9.4', + # LuaJIT's v2.1 branch is release-less by policy, so pin a commit rather + # than the floating v2.1.ROLLING tag. + [string] $LuaJITCommit = '1ee778a4e37122d8ca7d5733c590a47dafd6b15c', + # The runtime the python plugin ships. Its minor version is load-bearing + # in three other places -- Python3Lib in win32\poxchat.props, setup-python + # in the workflow, and the python313.* names in poxchat.iss.tt -- so bump + # all four together, and the hash with the version. + [string] $PythonEmbedVersion = '3.13.9', + [string] $PythonEmbedSha256 = '91d828c2da3a029b41699e918674a0cb379c02cf20dab9c501306885f837402a', [string] $CMakeGenerator = 'Visual Studio 17 2022' ) @@ -42,13 +56,12 @@ $ProgressPreference = 'SilentlyContinue' # Invoke-WebRequest crawls with the pro # gvsbuild project names, not pkg-config names. gettext is here for msgfmt.exe, # which win32\nls compiles the .po catalogues with. # -# luajit is absent, and with it lgi (which depends on it) and --enable-gi (which -# exists to produce lgi's typelibs). gvsbuild builds luajit by running -# '.\msvcbuild' through CreateProcess, which cannot launch a .bat file and finds -# nothing without the extension -- it fails identically every time, so the lua -# plugin is out of the first build. Re-adding it means building LuaJIT here the -# way jansson and libwebsockets are built below; the installer script also names -# lua and lgi files unconditionally, so that has to be settled at the same time. +# luajit is deliberately not asked of gvsbuild: it runs '.\msvcbuild' through +# CreateProcess, which cannot launch a .bat file and finds nothing without the +# extension -- it fails identically every time. LuaJIT is built directly below +# instead. lgi and --enable-gi (which exists to produce lgi's typelibs) stay +# out with it: the lua plugin itself needs neither, they were only ever for +# GObject bindings inside Lua scripts. $GvsbuildProjects = @( 'gtk4', 'openssl', @@ -230,6 +243,68 @@ if (Test-Path $lwsStatic) { Copy-Item $lwsStatic (Join-Path $lwsPrefix 'lib\websockets.lib') -Force } +Write-Step 'LuaJIT' +# msvcbuild.bat wants cl on PATH and to be run from src\. Doing the vcvars +# call and the cd inside a generated .cmd sidesteps cmd /c's quote-stripping +# rules, which would otherwise eat the spaces in the Visual Studio path. +# msvcbuild.bat does not reliably set an exit code, so the proof of success is +# the artifacts themselves, checked below. Always a full rebuild, but that is +# under a minute. +$ljSrc = Get-SourceTree "https://github.com/LuaJIT/LuaJIT/archive/$LuaJITCommit.zip" "LuaJIT-$($LuaJITCommit.Substring(0, 12))" +$vswhere = Join-Path ${env:ProgramFiles(x86)} 'Microsoft Visual Studio\Installer\vswhere.exe' +$vsRoot = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath +if (-not $vsRoot) { + throw 'vswhere found no Visual Studio with the C++ toolset' +} +$vcvars = Join-Path $vsRoot 'VC\Auxiliary\Build\vcvars64.bat' +$ljBuild = Join-Path $srcRoot 'build-luajit.cmd' +@( + "call `"$vcvars`" || exit /b 1", + "cd /d `"$ljSrc\src`" || exit /b 1", + 'call msvcbuild.bat' +) | Set-Content -Path $ljBuild -Encoding ascii +Invoke-Checked 'LuaJIT msvcbuild' { cmd /c $ljBuild } +foreach ($artifact in 'lua51.dll', 'lua51.lib') { + if (-not (Test-Path (Join-Path $ljSrc "src\$artifact"))) { + throw "LuaJIT build produced no $artifact" + } +} +# Install into the gvsbuild prefix, in the layout poxchat.props expects: +# LuaInclude points at include\luajit-2.1, lua.vcxproj links lua51.lib out of +# the shared lib dir, and copy.vcxproj stages bin\lua51.dll when it exists. +$ljInclude = Join-Path $prefix 'include\luajit-2.1' +New-Item -ItemType Directory -Force -Path $ljInclude | Out-Null +Copy-Item (Join-Path $ljSrc 'src\lua51.dll') (Join-Path $prefix 'bin') -Force +Copy-Item (Join-Path $ljSrc 'src\lua51.lib') (Join-Path $prefix 'lib') -Force +foreach ($header in 'lua.h', 'luaconf.h', 'lualib.h', 'lauxlib.h', 'lua.hpp', 'luajit.h') { + Copy-Item (Join-Path $ljSrc "src\$header") $ljInclude -Force +} + +Write-Step "CPython $PythonEmbedVersion embeddable runtime" +# The python plugin is a cffi embedding: hcpython3.dll links python313.dll and +# needs a stdlib beside it at run time. The embeddable package is CPython's +# designed-for-this layout -- python313.dll, python313.zip, python313._pth +# (whose '.' entry keeps the install dir on sys.path, where copy.vcxproj also +# drops _cffi_backend*.pyd), and the stdlib's extension modules. The workflow +# stages this directory into the tree after the copy project runs. +$pyDir = Join-Path $BuildRoot 'python-embed' +$pyZip = Join-Path $srcRoot "python-$PythonEmbedVersion-embed-amd64.zip" +New-Item -ItemType Directory -Force -Path $srcRoot | Out-Null +if (-not (Test-Path $pyZip)) { + $pyUrl = "https://www.python.org/ftp/python/$PythonEmbedVersion/python-$PythonEmbedVersion-embed-amd64.zip" + Write-Host "downloading $pyUrl" + Invoke-WebRequest -Uri $pyUrl -OutFile $pyZip -UseBasicParsing +} +$pyDigest = (Get-FileHash -Path $pyZip -Algorithm SHA256).Hash +if ($pyDigest -ne $PythonEmbedSha256.ToUpper()) { + Remove-Item $pyZip -Force + throw "python embeddable zip hashed $pyDigest, expected $PythonEmbedSha256" +} +if (Test-Path $pyDir) { + Remove-Item $pyDir -Recurse -Force +} +Expand-Archive -Path $pyZip -DestinationPath $pyDir -Force + Write-Step 'WinSparkle' $wsPrefix = Join-Path $BuildRoot "WinSparkle\$Platform" $wsSrc = Get-SourceTree "https://github.com/vslavik/winsparkle/releases/download/v$WinSparkleVersion/WinSparkle-$WinSparkleVersion.zip" "WinSparkle-$WinSparkleVersion" @@ -268,7 +343,8 @@ New-Item -ItemType Directory -Force -Path $certDir | Out-Null Invoke-WebRequest -Uri 'https://curl.se/ca/cacert.pem' -OutFile (Join-Path $certDir 'cacert.pem') -UseBasicParsing Write-Step 'done' -Write-Host "gvsbuild prefix: $prefix" +Write-Host "gvsbuild prefix: $prefix (LuaJIT installed into it)" Write-Host "jansson: $janssonPrefix" Write-Host "libwebsockets: $lwsPrefix" Write-Host "WinSparkle: $wsPrefix" +Write-Host "python runtime: $pyDir" diff --git a/win32/ci/make-installer.ps1 b/win32/ci/make-installer.ps1 index 0a50f7e3..3f9d884a 100644 --- a/win32/ci/make-installer.ps1 +++ b/win32/ci/make-installer.ps1 @@ -9,7 +9,8 @@ separate, skippable step. poxchat.iss.tt targets Inno Setup 5 and #includes idp.iss from the Inno - Download Plugin (which fetches vcredist/perl/python at install time). The + Download Plugin (which fetches vcredist and the spelling dictionaries at + install time). The hosted runners ship Inno Setup 6 and no idp, so -Provision installs both: IS5 from jrsoftware, idp from the mirror hexchat kept on its gvsbuild releases, the upstream host having gone away years ago. diff --git a/win32/installer/poxchat.iss.tt b/win32/installer/poxchat.iss.tt index f07a958b..2b226b7e 100644 --- a/win32/installer/poxchat.iss.tt +++ b/win32/installer/poxchat.iss.tt @@ -59,7 +59,6 @@ Name: "custom"; Description: "Custom Installation"; Flags: iscustom [Components] Name: "libs"; Description: "PoxChat"; Types: normal minimal custom; Flags: fixed Name: "xctext"; Description: "PoxChat-Text"; Types: custom; Flags: disablenouninstallwarning -Name: "xtm"; Description: "PoxChat Theme Manager"; Types: normal custom; Flags: disablenouninstallwarning Name: "icons"; Description: "Create Shortcuts"; Types: custom; Flags: disablenouninstallwarning Name: "icons\desktopicon"; Description: "Create Desktop Shortcut"; Types: custom; Flags: disablenouninstallwarning Name: "icons\quicklaunchicon"; Description: "Create Quick Launch Shortcut"; Types: custom; Flags: disablenouninstallwarning @@ -74,8 +73,7 @@ Name: "plugins\upd"; Description: "Update Checker"; Types: normal custom; Flags: Name: "plugins\winamp"; Description: "Winamp"; Types: custom; Flags: disablenouninstallwarning Name: "langs"; Description: "Language Interfaces"; Types: custom; Flags: disablenouninstallwarning Name: "langs\lua"; Description: "Lua"; Types: normal custom; Flags: disablenouninstallwarning -Name: "langs\perl"; Description: "Perl (requires Perl 5.20)"; Types: custom; Flags: disablenouninstallwarning -Name: "langs\python"; Description: "Python (requires Python 3.8)"; Types: custom; Flags: disablenouninstallwarning +Name: "langs\python"; Description: "Python"; Types: normal custom; Flags: disablenouninstallwarning [Tasks] Name: portable; Description: "Yes"; GroupDescription: "Portable Mode: Stores configuration files within install directory for portable drives."; Flags: unchecked @@ -88,22 +86,10 @@ Root: HKCR; Subkey: "irc\DefaultIcon"; ValueType: string; ValueName: ""; ValueDa Root: HKCR; Subkey: "irc\shell"; ValueType: string; ValueName: ""; ValueData: "open"; Flags: uninsdeletevalue; Tasks: not portable Root: HKCR; Subkey: "irc\shell\open\command"; ValueType: string; ValueName: ""; ValueData: "{app}\poxchat.exe --url=""%1"""; Flags: uninsdeletevalue; Tasks: not portable -Root: HKCR; Subkey: ".hct"; ValueType: none; ValueName: ""; ValueData: ""; Flags: deletekey uninsdeletekey; Components:xtm; Tasks: not portable -Root: HKCR; Subkey: ".hct"; ValueType: string; ValueName: ""; ValueData: "PoxChat Theme File"; Flags: uninsdeletevalue; Components:xtm; Tasks: not portable -Root: HKCR; Subkey: ".hct"; ValueType: string; ValueName: "PoxChat Theme File"; ValueData: ""; Flags: uninsdeletevalue; Components:xtm; Tasks: not portable -Root: HKCR; Subkey: ".hct\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\thememan.exe,0"; Flags: uninsdeletevalue; Components:xtm; Tasks: not portable -Root: HKCR; Subkey: ".hct\shell"; ValueType: string; ValueName: ""; ValueData: "open"; Flags: uninsdeletevalue; Components:xtm; Tasks: not portable -Root: HKCR; Subkey: ".hct\shell\open\command"; ValueType: string; ValueName: ""; ValueData: "{app}\thememan.exe ""%1"""; Flags: uninsdeletevalue; Components:xtm; Tasks: not portable - [Run] Filename: "{app}\poxchat.exe"; Description: "Run PoxChat after closing the Wizard"; Flags: nowait postinstall skipifsilent Filename: "https://github.com/evilnet/poxchat/releases"; Description: "See what's changed"; Flags: shellexec runasoriginaluser postinstall skipifsilent unchecked Filename: "{tmp}\vcredist.exe"; Parameters: "/install /quiet /norestart"; StatusMsg: "Installing Visual C++ Redistributable"; Flags: skipifdoesntexist; Tasks: not portable -Filename: "{tmp}\vcredist2013.exe"; Parameters: "/install /quiet /norestart"; StatusMsg: "Installing Visual C++ Redistributable"; Flags: skipifdoesntexist; Tasks: not portable -Filename: "{tmp}\dotnet4.exe"; Parameters: "/q /norestart"; StatusMsg: "Installing .NET"; Components: xtm; Flags: skipifdoesntexist; Tasks: not portable -Filename: "{tmp}\perl.msi"; StatusMsg: "Installing Perl"; Components: langs\perl; Flags: shellexec skipifdoesntexist; Tasks: not portable -Filename: "{tmp}\python.msi"; StatusMsg: "Installing Python"; Components: langs\python; Flags: shellexec skipifdoesntexist; Tasks: not portable -Filename: "{tmp}\python.exe"; Parameters: "InstallAllUsers=1 PrependPath=1"; StatusMsg: "Installing Python"; Components: langs\python; Flags: shellexec skipifdoesntexist; Tasks: not portable Filename: "{tmp}\spelling-dicts.exe"; Parameters: "/verysilent"; StatusMsg: "Installing Spelling Dictionaries"; Components: spell; Flags: skipifdoesntexist; Tasks: not portable [Files] @@ -155,6 +141,22 @@ Source: "pangocairo-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Componen Source: "pangoft2-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "pangowin32-1.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "zlib1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "sqlite3.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "jpeg62.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "tiff.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "harfbuzz-subset.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "cairo-gobject-2.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "cairo-script-interpreter-2.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "rsvg-2-2.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "pixman-1-0.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +Source: "libexpat.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: libs +; copy.vcxproj stages these conditionally, so mirror its optionality here +Source: "soup-3.0-0.dll"; DestDir: "{app}"; Flags: ignoreversion skipifsourcedoesntexist; Components: libs +Source: "libcurl.dll"; DestDir: "{app}"; Flags: ignoreversion skipifsourcedoesntexist; Components: libs +Source: "libcurl-x64.dll"; DestDir: "{app}"; Flags: ignoreversion skipifsourcedoesntexist; Components: libs +Source: "psl-5.dll"; DestDir: "{app}"; Flags: ignoreversion skipifsourcedoesntexist; Components: libs +Source: "icuuc*.dll"; DestDir: "{app}"; Flags: ignoreversion skipifsourcedoesntexist; Components: libs +Source: "icudt*.dll"; DestDir: "{app}"; Flags: ignoreversion skipifsourcedoesntexist; Components: libs Source: "plugins\hcnotifications-winrt.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: libs @@ -165,13 +167,8 @@ Source: "lib\enchant-2\*"; DestDir: "{app}\lib\enchant-2"; Flags: ignoreversion ; GTK4 uses CSS theming only - no theme engine DLLs needed -Source: "girepository-1.0-1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\lua +; LuaJIT only -- lgi and its typelibs are not built, see win32\ci\build-deps.ps1 Source: "lua51.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\lua -Source: "lib\lua\lgi\*.dll"; DestDir: "{app}\lib\lua\lgi"; Flags: ignoreversion; Components: langs\lua -Source: "lib\girepository-1.0\*.typelib"; DestDir: "{app}\lib\girepository-1.0"; Flags: ignoreversion; Components: langs\lua -Source: "share\lua\*.lua"; DestDir: "{app}\share\lua"; Flags: ignoreversion; Components: langs\lua -Source: "share\lua\lgi\*.lua"; DestDir: "{app}\share\lua\lgi"; Flags: ignoreversion; Components: langs\lua -Source: "share\lua\lgi\override\*.lua"; DestDir: "{app}\share\lua\lgi\override"; Flags: ignoreversion; Components: langs\lua Source: "plugins\hclua.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\lua Source: "plugins\hcchecksum.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: plugins\checksum @@ -188,16 +185,29 @@ Source: "WinSparkle.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: pl Source: "plugins\hcwinamp.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: plugins\winamp Source: "share\system.png"; DestDir: "{app}\share"; Flags: ignoreversion; Components: plugins\sysinfo Source: "plugins\hcsysinfo.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: plugins\sysinfo -Source: "plugins\hcperl.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\perl +; The python plugin is self-contained: hcpython3.dll links python313.dll and +; the CI-staged embeddable runtime beside it supplies the interpreter and +; stdlib -- python313._pth's '.' entry keeps {app} on sys.path, which is where +; *.pyd (the stdlib's extension modules plus cffi's _cffi_backend) live. +; python313 appears by name here on purpose; the version is pinned in +; build-deps.ps1 and the names below move with it. Source: "python\*.py"; DestDir: "{app}\python"; Flags: ignoreversion; Components: langs\python - Source: "plugins\hcpython3.dll"; DestDir: "{app}\plugins"; Flags: ignoreversion; Components: langs\python -Source: "_cffi_backend.cp3*.pyd"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "python313.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "python3.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "python313.zip"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "python313._pth"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "*.pyd"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "libffi-8.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "libcrypto-3.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "libssl-3.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "vcruntime140.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "vcruntime140_1.dll"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python +Source: "PYTHON-LICENSE.txt"; DestDir: "{app}"; Flags: ignoreversion; Components: langs\python Source: "poxchat.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: libs Source: "poxchat-text.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: xctext -Source: "thememan.exe"; DestDir: "{app}"; Flags: ignoreversion; Components: xtm [Icons] Name: "{group}\PoxChat"; Filename: "{app}\poxchat.exe"; AppUserModelID: "PoxChat.Desktop.Notify"; Tasks: not portable; Check: not WizardNoIcons @@ -206,7 +216,6 @@ Name: "{group}\PoxChat ChangeLog"; Filename: "{app}\changelog.url"; IconFilename Name: "{group}\PoxChat ReadMe"; Filename: "{app}\readme.url"; IconFilename: "{sys}\shell32.dll"; IconIndex: 23; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\PoxChat Config Folder"; Filename: "%APPDATA%\PoxChat\"; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\PoxChat-Text"; Filename: "{app}\poxchat-text.exe"; Components: xctext; Tasks: not portable; Check: not WizardNoIcons -Name: "{group}\PoxChat Theme Manager"; Filename: "{app}\thememan.exe"; Components: xtm; Tasks: not portable; Check: not WizardNoIcons Name: "{group}\Uninstall PoxChat"; Filename: "{uninstallexe}"; Tasks: not portable; Check: not WizardNoIcons Name: "{commondesktop}\PoxChat"; Filename: "{app}\poxchat.exe"; AppUserModelID: "PoxChat.Desktop.Notify"; Components: icons\desktopicon; Tasks: not portable Name: "{commonappdata}\Microsoft\Internet Explorer\Quick Launch\PoxChat"; Filename: "{app}\poxchat.exe"; Components: icons\quicklaunchicon; Tasks: not portable @@ -236,30 +245,12 @@ begin #endif end; -///////////////////////////////////////////////////////////////////// -function CheckDLL(DLLName: String): Boolean; -var - ResultCode: Integer; -begin - if ExecAsOriginalUser(GetSysDir() + 'where.exe', '/Q ' + DLLName, - '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then - Result := ResultCode = 0 // 0 is success - else - Result := False; -end; - ///////////////////////////////////////////////////////////////////// function CheckVCInstall(): Boolean; begin Result := FileExists(GetSysDir() + 'vcruntime140.dll');; end; -function CheckVC2013Install(): Boolean; -begin - Result := FileExists(GetSysDir() + 'msvcr120.dll');; -end; - - ///////////////////////////////////////////////////////////////////// function CheckSpellInstall(): Boolean; var @@ -275,22 +266,14 @@ begin end; ///////////////////////////////////////////////////////////////////// -function CheckDotNetInstall(): Boolean; -begin - Result := RegKeyExists(HKLM, 'SOFTWARE\Microsoft\NET Framework Setup\NDP\v4'); -end; - -///////////////////////////////////////////////////////////////////// -// Sets up the automatic downloads +// Sets up the automatic downloads. The scripting runtimes ship inside the +// installer these days -- LuaJIT and the embeddable CPython are ordinary +// [Files] entries -- so only vcredist and the spelling dictionaries are +// fetched at install time. ///////////////////////////////////////////////////////////////////// procedure CurPageChanged(CurPageID: Integer); var REDIST: String; - REDIST_2013: String; - PERL: String; - PY2: String; - PY3: String; - DOTNET: String; SPELL: String; begin if(CurPageID = wpReady) then @@ -302,40 +285,16 @@ begin #if APPARCH == "x64" REDIST := 'https://github.com/hexchat/gvsbuild/releases/download/hexchat-2.16.2/vcredist_2015_x64.exe'; - REDIST_2013 := 'https://github.com/hexchat/gvsbuild/releases/download/hexchat-2.16.2/vcredist_2013_x64.exe'; - PERL := 'https://github.com/hexchat/gvsbuild/releases/download/hexchat-2.16.2/Perl.5.20.0.x64.msi'; - PY3 := 'https://www.python.org/ftp/python/3.8.10/python-3.8.10-amd64.exe'; #else REDIST := 'https://github.com/hexchat/gvsbuild/releases/download/hexchat-2.16.2/vcredist_2015_x86.exe'; - REDIST_2013 := 'https://github.com/hexchat/gvsbuild/releases/download/hexchat-2.16.2/vcredist_2013_x86.exe'; - PERL := 'https://github.com/hexchat/gvsbuild/releases/download/hexchat-2.16.2/Perl.5.20.0.x86.msi'; - PY3 := 'https://www.python.org/ftp/python/3.8.10/python-3.8.10.exe'; #endif - DOTNET := 'https://github.com/hexchat/gvsbuild/releases/download/hexchat-2.16.2/dotnet_40.exe'; SPELL := 'https://github.com/hexchat/gvsbuild/releases/download/hexchat-2.16.2/HexChat.Spelling.Dictionaries.r2.exe'; if not CheckVCInstall() then idpAddFile(REDIST, ExpandConstant('{tmp}\vcredist.exe')); - if IsComponentSelected('xtm') and not CheckDotNetInstall() then - idpAddFile(DOTNET, ExpandConstant('{tmp}\dotnet4.exe')); - if IsComponentSelected('spell') and not CheckSpellInstall() then idpAddFile(SPELL, ExpandConstant('{tmp}\spelling-dicts.exe')); - - if not WizardSilent() then - begin - if IsComponentSelected('langs\perl') and not CheckDLL('perl520.dll') then - begin - if not CheckVC2013Install() then - idpAddFile(REDIST_2013, ExpandConstant('{tmp}\vcredist2013.exe')); - - idpAddFile(PERL, ExpandConstant('{tmp}\perl.msi')) - end; - - if IsComponentSelected('langs\python\python3') and not CheckDLL('python38.dll') then - idpAddFile(PY3, ExpandConstant('{tmp}\python.exe')); - end; end; end; end; diff --git a/win32/poxchat.props b/win32/poxchat.props index f1d87549..5d1838bd 100644 --- a/win32/poxchat.props +++ b/win32/poxchat.props @@ -7,7 +7,7 @@ c:\gtk-build\gtk4 c:\gtk-build\gendef C:\Strawberry\perl - C:\Python314\ + C:\Python313\ c:\gtk-build\WinSparkle C:\Program Files\OpenSSL