installer: let the packaging carry a prerelease version string

Two independent obstacles surfaced the first time a version with a hyphen
reached the installer:

- Inno Setup's VersionInfoVersion only accepts digits and dots, so ISCC
  aborted on 0.7.1-dev.20261019.<hash>. AppVersion, the output filename and
  the versioned DLL directory are free text and keep the full string; only
  VersionInfoVersion moves to a separate MyVersionInfo define that
  Prepare-PackageFiles.ps1 fills with the part before the hyphen, failing
  loudly if what remains is not numeric. Releases pass a bare semver, strip
  nothing, and behave exactly as before.
- TsfRoot64 called ApplyPathRedirRulesForCurrentProcess, an Inno Setup 7
  support function the windows-2025 runner's 6.7.1 does not have. #925 added
  it five hours after the last hosted-compiler run, and every release since
  then compiled on the self-hosted Inno 7, so the latent break never fired;
  the dev-build's hosted package job is the first to execute that path. The
  call was a no-op anyway: with
  ArchitecturesInstallIn64BitMode=x64compatible the setup process is 64-bit
  on every supported OS, so {sys} already expands to the real System32 and
  no WOW64 redirection applies. Expand the constant directly, with the #434
  warning in this README updated to name the function explicitly.
This commit is contained in:
tokisaki galaxy committed 2026-10-19 16:01:05 +08:00
1 parent bb4c48505a
commit d376b93e03
3 files changed
+35 -6

No files matched your search

+11
View File
@@ -347,6 +347,17 @@ $updatedIss = [regex]::Replace(
'(?m)^#define\s+MyAppVersion\s+"[^"]+"\s*$',
"#define MyAppVersion `"$TargetVersion`""
)
# VersionInfoVersion 只接受数字和点号;从目标版本剥掉 -后缀(dev 构建的
# 0.7.1-dev.20261019.<hash> → 0.7.1),正式版本剥了也原样。
$versionInfo = ($TargetVersion -replace '-.*$', '')
if ($versionInfo -notmatch '^[0-9]+(\.[0-9]+)*$') {
throw "目标版本剥掉后缀后不是数字版本号,无法写进 VersionInfoVersion:$TargetVersion"
}
$updatedIss = [regex]::Replace(
$updatedIss,
'(?m)^#define\s+MyVersionInfo\s+"[^"]+"\s*$',
"#define MyVersionInfo `"$versionInfo`""
)
# .gitattributes pins this repo to eol=lf; emit LF so packaging does not leave the file as a
# CRLF-only diff that git flags as modified while `git diff` shows no textual change.
$updatedIss = $updatedIss.TrimEnd("`r", "`n") + "`n"
+12 -2
View File
@@ -1,8 +1,9 @@
# Metasequoia IME Installer
本目录的脚本从 Windows 合仓目录收集产物、签名、用 Inno Setup 打成安装包。它服务两条流程:
本目录的脚本从 Windows 合仓目录收集产物、签名、用 Inno Setup 打成安装包。它服务三条流程:
- **正式发布**:由 `MSIME-Windows` 的 release workflow 驱动,用真实证书签名包内全部 EXE/DLL 和最终安装包;产物是挂在 Release 上的 `MetasequoiaIME_Setup_v<版本>.exe`,并携带与 Release 二进制匹配的 PDB 符号文件。见下面「CI 契约」
- **开发构建**:由 `dev-build.yml` workflow 驱动,runner 上现场生成自签名证书并签名,产物随 artifact 分发。见下面「Dev build」
- **本地测试**:手工跑,用本机自签名证书,用来在自己机器上验证安装流程。本文其余部分讲的是这条
版本号不是固定的,由 `Prepare-PackageFiles.ps1` 的 `-TargetVersion` 决定,默认 `0.0.1`;正式发布时 CI 传入真实版本。
@@ -11,6 +12,15 @@
签名脚本会在你自己的机器上生成并复用一张自签名测试证书。
## Dev build
`dev-build.yml` workflow 给没有本地工具链的贡献者出可安装的包。触发见 [CONTRIBUTING.md](../CONTRIBUTING.md#没有本地工具链时dev-build-workflow)。签名证书由 `sign-dev-build.ps1` 在 runner 上现场生成,subject 固定为 `CN=Metasequoia IME Dev Build Code Signing`,私钥只在 runner 内存里存在一次构建;公钥 `.cer` 随 artifact 分发,用户用 `import-dev-trust.ps1` 导入本机受信任存储(按 subject 清旧导新,重复构建不会膨胀存储)。
- `sign-dev-build.ps1` 复用同一次运行早先创建的证书,所以包内二进制和安装包总在同一签名下;`DEV_CERT_PATH` 指出 `.cer` 的导出位置
- `import-dev-trust.ps1` 也随 artifact 分发,用户解压后在管理员 PowerShell 里直接跑
- 版本号带 `-dev.<日期>.<commit>`,由 `scripts/dev-build-version.py` 从 `version.txt` 派生;设置页的更新检查会剥掉 `-dev` 后缀做数字比较,dev 包不会提示升级
- 不要把这两个脚本接进 release 路径:正式发布的签名在 `scripts/ci/sign-binaries.ps1` 或 SignPath,两套互不相干
## CI 契约
根 `.github/workflows/release.yml` **不加修改地调用本目录的 `Prepare-PackageFiles.ps1` 和 `Compile-Installer.ps1`**。源目录名是 `Prepare-PackageFiles.ps1` 的参数,不是写死在脚本里的字面量:默认值为 `windows/`、`server/` 和仓根授权文件;旧目录或自定义布局通过参数覆盖。回归检查同时执行默认路径和显式参数的打包。辅助码默认读取 `engine/helpcode/`,词库缓存位于 `MetasequoiaImeDict/out/`。
@@ -71,7 +81,7 @@ Windows CI 运行 `installer/tests/cloud-choice.ps1`,用 Inno Setup 跑八个
安装包不携带 VC 运行库,它是系统级共享组件。缺了它 Server 起不来,而这个故障出现在安装结束之后,用户看不到任何解释。所以 `msime_setup.iss` 的 `InitializeSetup` 在安装开始前先查一遍,缺了就当场说清楚,并给出下载地址。界面全部由 `msimeui` 以 Direct2D 绘制,不再依赖 WebView2 Runtime;旧版本留下的 WebView2 用户数据(`ProgramData\metasequoiaime\webview2`、`webview2-settings`,以及 `%LOCALAPPDATA%\metasequoiaime` 下的同名回退目录)由安装器在升级和卸载时清掉。
- **Visual C++ 2015–2022 可再发行组件包(x64)**:读 `Software\Microsoft\VisualStudio\14.0\VC\Runtimes\x64` 的 `Installed` / `Major` / `Minor`,`HKLM32` 和 `HKLM64` 两个视图都查。要求 **14.40 以上**(常量 `VCRuntimeMinMinor`):`server_exe\` 里的 exe 用 MSVC 14.40+(VS 2022 17.10 起)编译并导入 `msvcp140.dll`,这一版起 `std::mutex` 的构造函数是 constexpr,配上更旧的 `msvcp140.dll` 会在第一次加锁时访问冲突、无声闪退——设置页「点了没反应」就是这个现象。装了 2019 / 早期 2022 运行库的机器同样有 `Installed=1`,所以必须比版本号。构建工具链升级到要求更高 redist 时同步调高这个常量。32 位 TSF DLL 用静态 CRT(`windows/CMakeLists.txt` 的 `CMAKE_MSVC_RUNTIME_LIBRARY`),所以不检查 x86 redist
- **不要改成查 `System32` 里的 DLL。** Setup.exe 是 32 位进程,Pascal Script 的 `FileExists` 会被 WOW64 重定向到 `SysWOW64`,查到的是 x86 运行库;只装了 x64 redist 的机器会被误判成缺少 x64 运行库。绕开重定向的办法不可移植:`EnableFsRedirection` 在 Inno Setup 7 里已被移除,而它的替代品在 CI 用的 6.x 里还不存在
- **不要改成查 `System32` 里的 DLL,也不要在 Pascal Script 里用 `ApplyPathRedirRulesForCurrentProcess`。** 那是 Inno Setup 7 的 support function,CI 的 6.7.1 没有它,ISCC 会报 `Unknown identifier`(#925 引入后第一次在 hosted runner 上编安装包就炸了,#55e1127a 改回直接展开 `{sys}`)。Setup 在 x64/ARM64 上是 64 位进程,`{sys}` 本来就不经重定向;需要 32 位视图时用 `{syswow64}`
- 缺组件或版本过旧时弹一次对话框,区分「没装」和「已装 x.y 但过旧」,列出直接下载链接(`https://aka.ms/vc14/vc_redist.x64.exe`)和说明页:选「是」直接下载安装包并结束安装,选「否」继续装。**不阻断安装**——用户可能马上就要去补组件,也可能只是在准备环境。静默安装(CI、批量部署)用 `SuppressibleMsgBox` 默认「否」直接继续,缺什么已经写进安装日志(`/LOG=`)
## 依赖
+12 -4
View File
@@ -20,6 +20,10 @@
#define MyAppName "Metasequoia IME 水杉输入法"
#define MyAppVersion "0.0.1"
; VersionInfoVersion 是 PE 的 VERSIONINFO,只接受数字和点号;dev 构建的 MyAppVersion 带
; -dev.<日期>.<hash> 后缀(Prepare-PackageFiles.ps1 会把数字部分同步写进这个 define),
; 文件名与 AppVersion 用完整串,这里只用数字段。
#define MyVersionInfo "0.0.1"
#define MyAppPublisher "Metasequoia"
#define MyAppExeName "MetasequoiaImeServer.exe"
#define MySettingsExeName "MetasequoiaImeSettings.exe"
@@ -36,7 +40,11 @@
#define MySourceRoot "."
; TSF DLL 装在系统目录下:CS2 等开启 Trusted Mode 的游戏只放行「位于系统目录且有代码签名」的
; 第三方 in-proc DLL,装在 Program Files 的 DLL 连加载都会被拒,输入法在游戏里根本切不出来。
; 本安装器是 32 位进程,[Code] 里访问 64 位那份要先过 ApplyPathRedirRulesForCurrentProcess。
; 本安装器在 x64/ARM64 上以 64 位模式运行(ArchitecturesInstallIn64BitMode),
; Pascal Script 里访问 {sys} 就是真正的 System32,没有 WOW64 重定向可绕。
; 不要在这里用 ApplyPathRedirRulesForCurrentProcess:那是 Inno Setup 7 的 support
; function,windows-2025 runner 的 6.7.1 没有它,ISCC 直接报 Unknown identifier
; (#434 的告诫,见 installer/README.md)。
#define MyTsfRoot64 "{sys}\IME\MetasequoiaIME"
#define MyTsfRoot32 "{syswow64}\IME\MetasequoiaIME"
#ifdef LightPackage
@@ -69,7 +77,7 @@ ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
UninstallDisplayName={#MyAppName}
UninstallDisplayIcon={commonpf64}\metasequoiaime\MetasequoiaIME.ico
VersionInfoVersion={#MyAppVersion}
VersionInfoVersion={#MyVersionInfo}
[Languages]
Name: "chinesesimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl"
@@ -718,10 +726,10 @@ begin
'现有数据将从这里迁移:' + NewLine + Space + ResolvePreviousDataDir;
end;
{ 本进程能直接访问的 TSF 根目录。32 位安装器里不经改写的 System32 会被 WOW64 落到 SysWOW64。}
// 本进程能直接访问的 TSF 根目录。64 位模式下 sys 常量不经重定向,直接就是 System32。
function TsfRoot64: String;
begin
Result := ApplyPathRedirRulesForCurrentProcess(True, ExpandConstant('{#MyTsfRoot64}'));
Result := ExpandConstant('{#MyTsfRoot64}');
end;
function TsfRoot32: String;