Add VibeChat Windows installer and runtime packaging
This commit is contained in:
1 parent
30106c8f93
commit
2e70c3baed
2 files changed
+234
No files matched your search
@@ -0,0 +1,99 @@
|
||||
; Параметры комплекта и версии передаёт package_win.sh, пользовательских данных в комплекте нет.
|
||||
#ifndef AppVersion
|
||||
#error AppVersion must be supplied by package_win.sh
|
||||
#endif
|
||||
#ifndef PackageDir
|
||||
#error PackageDir must be supplied by package_win.sh
|
||||
#endif
|
||||
|
||||
[Setup]
|
||||
AppId={{3A06309E-A5D4-46A6-A946-298634697A22}
|
||||
AppName=VibeChat
|
||||
AppVersion={#AppVersion}
|
||||
AppPublisher=uTun
|
||||
DefaultDirName={autopf}\VibeChat
|
||||
DisableDirPage=no
|
||||
DisableProgramGroupPage=yes
|
||||
ArchitecturesAllowed=x64compatible
|
||||
ArchitecturesInstallIn64BitMode=x64compatible
|
||||
MinVersion=10.0
|
||||
PrivilegesRequired=admin
|
||||
OutputBaseFilename=VibeChat-{#AppVersion}-win64-setup
|
||||
Compression=lzma2
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
UninstallDisplayIcon={app}\vibechat.exe
|
||||
LicenseFile={#PackageDir}\licenses\LICENSE
|
||||
CloseApplications=yes
|
||||
CloseApplicationsFilter=*.exe,*.dll
|
||||
RestartApplications=no
|
||||
SetupLogging=yes
|
||||
UninstallLogging=yes
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "{#PackageDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\VibeChat"; Filename: "{app}\vibechat.exe"; WorkingDir: "{app}"
|
||||
Name: "{autodesktop}\VibeChat"; Filename: "{app}\vibechat.exe"; WorkingDir: "{app}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\vibechat.exe"; Description: "{cm:LaunchProgram,VibeChat}"; WorkingDir: "{app}"; Flags: nowait postinstall skipifsilent runasoriginaluser
|
||||
|
||||
[CustomMessages]
|
||||
english.FirewallFailed=Could not configure the VibeChat firewall rule. See the installation log for details.
|
||||
russian.FirewallFailed=Не удалось настроить правило брандмауэра VibeChat. Подробности в журнале установки.
|
||||
|
||||
[Code]
|
||||
// Удаляем только правило нашего инсталлятора для конкретного установленного EXE.
|
||||
procedure RemoveFirewallRule;
|
||||
var
|
||||
Parameters: String;
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
Parameters := 'advfirewall firewall delete rule name="VibeChat (installer)" program=' + AddQuotes(ExpandConstant('{app}\vibechat.exe'));
|
||||
if not Exec(ExpandConstant('{sys}\netsh.exe'), Parameters, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
|
||||
Log(Format('WARNING: cannot run firewall rule removal: error=%d', [ResultCode]))
|
||||
else if ResultCode <> 0 then
|
||||
Log(Format('Firewall removal: rule absent or removal failed, exit=%d', [ResultCode]))
|
||||
else
|
||||
Log('Firewall: previous VibeChat rule removed');
|
||||
end;
|
||||
|
||||
// После копирования EXE разрешаем входящие подключения; ошибка установки видна и в журнале, и в GUI.
|
||||
procedure CurStepChanged(CurStep: TSetupStep);
|
||||
var
|
||||
Parameters: String;
|
||||
ResultCode: Integer;
|
||||
begin
|
||||
if CurStep <> ssPostInstall then Exit;
|
||||
Log('VibeChat: installed to ' + ExpandConstant('{app}') + '; user config, keys and history are preserved');
|
||||
RemoveFirewallRule;
|
||||
Parameters := 'advfirewall firewall add rule name="VibeChat (installer)" dir=in action=allow program=' +
|
||||
AddQuotes(ExpandConstant('{app}\vibechat.exe')) + ' enable=yes profile=any';
|
||||
if not Exec(ExpandConstant('{sys}\netsh.exe'), Parameters, '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then begin
|
||||
Log(Format('ERROR: cannot run firewall rule creation: error=%d', [ResultCode]));
|
||||
RaiseException(CustomMessage('FirewallFailed'));
|
||||
end;
|
||||
if ResultCode <> 0 then begin
|
||||
Log(Format('ERROR: firewall rule creation failed: exit=%d', [ResultCode]));
|
||||
RaiseException(CustomMessage('FirewallFailed'));
|
||||
end;
|
||||
Log('Firewall: inbound VibeChat connections allowed for installed EXE');
|
||||
end;
|
||||
|
||||
// Деинсталлятор освобождает своё правило, не удаляя LocalAppData и пользовательские файлы.
|
||||
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
||||
begin
|
||||
if CurUninstallStep = usUninstall then begin
|
||||
RemoveFirewallRule;
|
||||
Log('VibeChat: uninstalling program files; user config, keys and history are preserved');
|
||||
end;
|
||||
end;
|
||||
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env bash
|
||||
# Чистый комплект из Windows-сборки и Inno Setup; ключи/БД/логи из build не копируются.
|
||||
set -euo pipefail
|
||||
|
||||
SRC_DIR=$(cd "$(dirname "$0")" && pwd)
|
||||
BUILD_DIR="$SRC_DIR/build"
|
||||
RUNTIME_PREFIX="${MSYSTEM_PREFIX:-/ucrt64}"
|
||||
STAGE=""
|
||||
trap 'rc=$?; if [[ $rc != 0 ]]; then echo "ERROR: installer packaging failed (exit=$rc)" >&2; fi
|
||||
if [[ -n "$STAGE" ]]; then rm -rf -- "$STAGE" || echo "WARN: cannot remove installer staging directory: $STAGE" >&2; fi' EXIT
|
||||
|
||||
[[ "${MSYSTEM:-}" = UCRT64 ]] || { echo "ERROR: Windows installer requires MSYS2 UCRT64" >&2; exit 1; }
|
||||
[[ $# = 0 || ( $# = 1 && $1 = --check ) ]] || { echo "ERROR: usage: bash package_win.sh [--check]" >&2; exit 1; }
|
||||
for tool in cygpath objdump pacman; do
|
||||
command -v "$tool" >/dev/null || { echo "ERROR: required packaging tool not found: $tool" >&2; exit 1; }
|
||||
done
|
||||
|
||||
if [[ -n "${ISCC:-}" ]]; then
|
||||
ISCC=$(cygpath -u "$ISCC")
|
||||
else
|
||||
ISCC=$(command -v ISCC.exe || command -v iscc.exe || true)
|
||||
if [[ -z "$ISCC" ]]; then
|
||||
for version in 7 6; do
|
||||
for variable in 'ProgramFiles(x86)' PROGRAMFILES 'ProgramFiles'; do
|
||||
program_dir=$(printenv "$variable" || true)
|
||||
[[ -n "$program_dir" ]] || continue
|
||||
candidate=$(cygpath -u "$program_dir/Inno Setup $version/ISCC.exe")
|
||||
if [[ -f "$candidate" ]]; then ISCC=$candidate; break 2; fi
|
||||
done
|
||||
[[ -z "$ISCC" ]] || break
|
||||
done
|
||||
fi
|
||||
fi
|
||||
[[ -n "$ISCC" && -f "$ISCC" ]] || {
|
||||
echo 'ERROR: Inno Setup 6.3+ not found; install it or set ISCC to the full path of ISCC.exe' >&2
|
||||
exit 1
|
||||
}
|
||||
echo "INFO: installer compiler: $ISCC"
|
||||
[[ "${1:-}" != --check ]] || exit 0
|
||||
|
||||
for file in vibechat.exe chatgui_version.txt chatgui_qt_package.txt; do
|
||||
[[ -f "$BUILD_DIR/$file" ]] || { echo "ERROR: missing build output: $BUILD_DIR/$file" >&2; exit 1; }
|
||||
done
|
||||
APP_VERSION=$(tr -d '\r\n' < "$BUILD_DIR/chatgui_version.txt")
|
||||
[[ "$APP_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || { echo "ERROR: invalid application version: $APP_VERSION" >&2; exit 1; }
|
||||
QT_PACKAGE=$(tr -d '\r\n' < "$BUILD_DIR/chatgui_qt_package.txt")
|
||||
[[ "$QT_PACKAGE" = Qt5 || "$QT_PACKAGE" = Qt6 ]] || { echo "ERROR: invalid Qt package: $QT_PACKAGE" >&2; exit 1; }
|
||||
for file in "${QT_PACKAGE}Core.dll" "${QT_PACKAGE}Gui.dll" "${QT_PACKAGE}Network.dll" "${QT_PACKAGE}Widgets.dll" \
|
||||
librlottie.dll platforms/qwindows.dll imageformats/qjpeg.dll imageformats/qwebp.dll; do
|
||||
[[ -f "$BUILD_DIR/$file" ]] || { echo "ERROR: missing runtime file: $BUILD_DIR/$file" >&2; exit 1; }
|
||||
done
|
||||
|
||||
STAGE=$(mktemp -d "$BUILD_DIR/installer-stage.XXXXXX")
|
||||
PACKAGE_DIR="$STAGE/package"
|
||||
mkdir -p "$PACKAGE_DIR/licenses" "$STAGE/output" "$BUILD_DIR/installer"
|
||||
cp "$BUILD_DIR/vibechat.exe" "$PACKAGE_DIR/"
|
||||
shopt -s nullglob nocasematch
|
||||
for file in "$BUILD_DIR/"*.dll; do
|
||||
name=${file##*/}
|
||||
if [[ "$name" = Qt[56]*.dll && "$name" != "$QT_PACKAGE"*.dll ]]; then
|
||||
echo "INFO: excluding DLL from other Qt version: $name"
|
||||
continue
|
||||
fi
|
||||
cp "$file" "$PACKAGE_DIR/"
|
||||
done
|
||||
for file in platforms/qwindows.dll imageformats/qjpeg.dll imageformats/qwebp.dll; do
|
||||
mkdir -p "$PACKAGE_DIR/${file%/*}"
|
||||
cp "$BUILD_DIR/$file" "$PACKAGE_DIR/$file"
|
||||
done
|
||||
for file in LICENSE LICENSING THIRD_PARTY_NOTICES; do
|
||||
cp "$SRC_DIR/../../$file" "$PACKAGE_DIR/licenses/"
|
||||
done
|
||||
mkdir -p "$PACKAGE_DIR/licenses/rlottie"
|
||||
cp "$SRC_DIR/rlottie_src/COPYING" "$PACKAGE_DIR/licenses/rlottie/"
|
||||
cp -R "$SRC_DIR/rlottie_src/licenses" "$PACKAGE_DIR/licenses/rlottie/"
|
||||
|
||||
# Проверяем архитектуру/полноту уже собранного комплекта, включая динамические Qt-плагины.
|
||||
SYSTEM_DIR=$(cygpath -u "${WINDIR:-C:\\Windows}/System32")
|
||||
declare -A LICENSE_PACKAGES=()
|
||||
for file in "$PACKAGE_DIR/vibechat.exe" "$PACKAGE_DIR/"*.dll "$PACKAGE_DIR/platforms/"*.dll "$PACKAGE_DIR/imageformats/"*.dll; do
|
||||
name=${file##*/}
|
||||
objdump -f "$file" > "$STAGE/headers.txt"
|
||||
rg_output=$(awk '/file format/ {print $NF}' "$STAGE/headers.txt")
|
||||
[[ "$rg_output" = pei-x86-64 ]] || { echo "ERROR: $name is not a Windows x64 binary: $rg_output" >&2; exit 1; }
|
||||
objdump -p "$file" > "$STAGE/imports.txt"
|
||||
while read -r dep; do
|
||||
[[ -n "$dep" ]] || continue
|
||||
[[ -f "$PACKAGE_DIR/$dep" ]] && continue
|
||||
case "$dep" in api-ms-win-*.dll|ext-ms-win-*.dll) continue ;; esac
|
||||
if [[ -f "$SYSTEM_DIR/$dep" && "$dep" != msvcp*.dll && "$dep" != vcruntime*.dll ]]; then continue; fi
|
||||
echo "ERROR: incomplete installer runtime: $name requires $dep" >&2
|
||||
exit 1
|
||||
done < <(awk '/DLL Name:/ {print $3}' "$STAGE/imports.txt")
|
||||
echo "INFO: verified installer runtime: ${file#"$PACKAGE_DIR/"}"
|
||||
|
||||
# Лицензии внешних библиотек берём из пакетов той же UCRT64-сборки.
|
||||
[[ "$name" != vibechat.exe && "$name" != librlottie.dll ]] || continue
|
||||
[[ ! -f "$SRC_DIR/ffmpeg/ffmpeg_build/install/bin/$name" ]] || continue
|
||||
runtime_file="$RUNTIME_PREFIX/bin/$name"
|
||||
if [[ "$file" = "$PACKAGE_DIR/platforms/"* || "$file" = "$PACKAGE_DIR/imageformats/"* ]]; then
|
||||
relative=${file#"$PACKAGE_DIR/"}
|
||||
runtime_file="$RUNTIME_PREFIX/share/qt${QT_PACKAGE#Qt}/plugins/$relative"
|
||||
[[ -f "$runtime_file" ]] || runtime_file="$RUNTIME_PREFIX/lib/qt${QT_PACKAGE#Qt}/plugins/$relative"
|
||||
fi
|
||||
[[ -f "$runtime_file" ]] || { echo "ERROR: cannot identify runtime source for $name" >&2; exit 1; }
|
||||
pkg=$(pacman -Qqo "$runtime_file")
|
||||
[[ -n "$pkg" ]] || { echo "ERROR: no package owns runtime file: $runtime_file" >&2; exit 1; }
|
||||
LICENSE_PACKAGES["$pkg"]=1
|
||||
done
|
||||
for pkg in "${!LICENSE_PACKAGES[@]}"; do
|
||||
pacman -Qql "$pkg" > "$STAGE/package-files.txt"
|
||||
while IFS= read -r file; do
|
||||
[[ "$file" = */share/licenses/* && -f "$file" ]] || continue
|
||||
relative=${file#*/share/licenses/}
|
||||
mkdir -p "$PACKAGE_DIR/licenses/runtime/${relative%/*}"
|
||||
cp "$file" "$PACKAGE_DIR/licenses/runtime/$relative"
|
||||
done < "$STAGE/package-files.txt"
|
||||
echo "INFO: included runtime license notices: $pkg"
|
||||
done
|
||||
if [[ -d "$SRC_DIR/ffmpeg/ffmpeg_build" ]]; then
|
||||
# Архив исходников FFmpeg остаётся распакованным после build_ffmpeg.sh.
|
||||
for file in "$SRC_DIR/ffmpeg/ffmpeg_build/ffmpeg-"*/COPYING* "$SRC_DIR/ffmpeg/ffmpeg_build/ffmpeg-"*/LICENSE.md; do
|
||||
mkdir -p "$PACKAGE_DIR/licenses/ffmpeg"
|
||||
cp "$file" "$PACKAGE_DIR/licenses/ffmpeg/"
|
||||
done
|
||||
fi
|
||||
|
||||
echo "INFO: compiling VibeChat $APP_VERSION installer (Qt package: $QT_PACKAGE)"
|
||||
# MSYS2 не должен преобразовывать ключи /D и /O; пути передаём явно в Windows-формате.
|
||||
MSYS2_ARG_CONV_EXCL='*' "$ISCC" "/DAppVersion=$APP_VERSION" "/DPackageDir=$(cygpath -w "$PACKAGE_DIR")" \
|
||||
"/O$(cygpath -w "$STAGE/output")" "$(cygpath -w "$SRC_DIR/installer/vibechat.iss")"
|
||||
INSTALLER_NAME="VibeChat-$APP_VERSION-win64-setup.exe"
|
||||
[[ -s "$STAGE/output/$INSTALLER_NAME" ]] || { echo "ERROR: compiler did not produce $INSTALLER_NAME" >&2; exit 1; }
|
||||
mv -f "$STAGE/output/$INSTALLER_NAME" "$BUILD_DIR/installer/$INSTALLER_NAME"
|
||||
echo "INFO: installer created: $BUILD_DIR/installer/$INSTALLER_NAME"
|
||||
Reference in new issue
Block a user