[Installer] Add an Inno Setup generator next to NSIS.

COCKATRICE_WIN_INSTALLER chooses which tool writes the Windows installer.
NSIS stays the default, so nothing on the existing path changes; InnoSetup
selects CPack's own INNOSETUP generator (CMake >= 3.27) and builds from the
same install() rules. Both can be built from one tree and the resulting
installers compared on an upgrade from 3.1.x.

What the Inno path does differently:

- Installs over the previous version instead of running the old uninstaller
  first, which is what the backup/restore pair in the NSIS template exists
  to survive.
- Closes and restarts a running application through Windows Restart Manager
  (CloseApplications/RestartApplications) instead of the two PowerShell
  process guards the template needed.
- Removes stale runtime with one [InstallDelete] of *.dll and Plugins,
  instead of RetryDllPurge and its diagnostics.
- Writes a log on every run through SetupLogging, instead of CockLog.
- Resolves the install directory from the legacy NSIS registration, and
  deletes that registration after a successful install so the old
  uninstaller (whose blanket directory removal caused the 3.1.x data loss)
  cannot be run after the upgrade.
- Keeps the portable mode the client detects, the C++ runtime bootstrap and
  the /PORTABLE switch.

The in-app updater still passes the NSIS switches (/R, /PID=); the installer
logs them so the first Windows run settles whether Inno Setup accepts them or
the switch-over needs a client version gate.

The installer content check in .ci/compile.sh learns to strip Inno Setup's
{app} prefix from the paths 7-Zip lists, so the required-runtime comparison
works for either archive format.
This commit is contained in:
Lukas Brübach 2026-10-26 07:52:44 +01:00
parent 675e1f7447
commit 2c8e47a0a4
5 changed files with 333 additions and 20 deletions

View file

@ -590,20 +590,22 @@ if [[ $MAKE_PACKAGE ]]; then
fi
# 7-Zip writes CRLF on Windows, so the \r has to come off before any
# whole-line comparison below. Normalize separators to /, and strip the
# install-root prefixes an NSIS listing may carry, so the entries can be
# compared as exact relative paths. -xF keeps a '.' in a DLL name from
# being a wildcard; -i because that is how the installed tree behaves -
# the uninstaller clears both $INSTDIR\plugins and $INSTDIR\Plugins.
# The archive side and the manifest side have to agree on line endings.
# CMake writes required-runtime.txt with the platform's line ending and
# 7-Zip writes CRLF on Windows, so a trailing \r survives on $entry and
# defeats the whole-line match - every entry then reads as missing even
# though the listing holds it verbatim.
# install-root prefixes a listing may carry - $INSTDIR/$OUTDIR/$PLUGINSDIR
# from NSIS, {app} from Inno Setup - so the entries can be compared as exact
# relative paths. -xF keeps a '.' in a DLL name from being a wildcard; -i
# because that is how the installed tree behaves - the uninstaller clears
# both $INSTDIR\plugins and $INSTDIR\Plugins. The archive side and the
# manifest side have to agree on line endings. CMake writes
# required-runtime.txt with the platform's line ending and 7-Zip writes CRLF
# on Windows, so a trailing \r survives on $entry and defeats the whole-line
# match - every entry then reads as missing even though the listing holds it
# verbatim.
# [$] rather than \$ so the literal dollar is a bracket expression and the
# linter does not read these as unexpanded shell variables (SC2016).
# linter does not read these as unexpanded shell variables (SC2016). The
# same goes for the braces of Inno Setup's {app} prefix.
installer_paths="$("$seven_zip" l -slt "$package" | tr -d '\r' |
sed -n 's/^Path = //p' |
sed -e 's|\\|/|g' -e 's|^[$]INSTDIR/||' -e 's|^[$]OUTDIR/||' -e 's|^[$]PLUGINSDIR/||' -e 's|^\./||' -e 's|^/||')"
sed -e 's|\\|/|g' -e 's|^[$]INSTDIR/||' -e 's|^[$]OUTDIR/||' -e 's|^[$]PLUGINSDIR/||' -e 's|^[{]app[}]/||' -e 's|^\./||' -e 's|^/||')"
manifest="$(tr -d '\r' <required-runtime.txt)"
missing=""
checked=0