Files
ykxmz/installer/build_installer.py
T
xmz7891 de5018bbbe 按用户规矩升到 1.9.0(有新内容+重构,不是只修 bug)+ 加版本号一致性检查
用户定的规矩:
    只修 bug        -> 最后一位 +1    1.8.2 -> 1.8.3
    加新内容/重构    -> 第二位 +1,最后一位清 0    1.8.2 -> 1.9.0

这一轮既有新东西(设置窗口的中转服务器字段、允许新设备接入开关、
双击开设置窗口)又有重构(手表面板切换收成 showOnly()),
所以是 **1.9.0**,不是我之前说的 1.8.3。

== 顺手加了个「版本号一致性」检查(回归阶段 3a8)==

版本号散落在 8 个地方,靠脚本+人工替换很容易漏。实测漏了两个,
而且**漏了不报错**,只是用户看到一个对不上的版本号:

  * windows/version_info.txt 写着 1.7.1
    -> 用户在「文件属性 -> 详细信息」里看到的版本,错了三个版本
  * docs/LICENSE.txt 写着 1.7.1
    -> 安装时许可页上显示 1.7.1

第二个的根因值得记:installer/build_installer.py 会从 docs/ 里三份
文档**重新生成** license-combined.txt,所以光改生成物没用 ——
下次构建又变回去(我第一次就是这么被骗的)。改成在 build_license()
里**统一注入当前版本**,源文档写什么都不影响。

新增:
  _tests/check_version_consistency.py   检查 8 处版本号一致
  _build/add_verify_stage.py            给套件加阶段(不经 shell,
                                        不会被 PowerShell 吃掉 \$ 变量)
  _build/fix_license_version.py         按行精确修 license

== 另外修了两个我自己的坑 ==

1. verify_all.ps1 被 PowerShell heredoc 吃掉了 \ / \,
   整个脚本语法错。**同一个坑踩了两次**(3a7 和 3a8)。
   以后给 .ps1 加含 \$ 的内容一律写 Python 脚本文件再跑。

2. build_exe.ps1 被 edit 工具吃掉了 UTF-8 BOM
   (PowerShell 5.1 会按 GBK 读,中文注释乱码)。

全量回归 43 个阶段全部通过。
2026-10-07 22:10:14 +08:00

147 lines
5.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
r"""编译 Inno Setup 安装包。
做三件事:
1. 把三份文档合并成 license-combined.txt(Inno 的 LicenseFile 只认一个文件)
2. 把 .iss 里的版本号同步成当前版本
3. 调 ISCC.exe 编译
"""
from __future__ import annotations
import re
import subprocess
import sys
from pathlib import Path
ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote")
INSTALLER = ROOT / "installer"
ISS = INSTALLER / "ykxmz.iss"
COMBINED = INSTALLER / "license-combined.txt"
ISCC = Path(r"C:\Program Files (x86)\Inno Setup 6\ISCC.exe")
DOCS = ("LICENSE.txt", "BEFORE-INSTALL.txt", "AFTER-INSTALL.txt")
def current_version() -> str:
text = (ROOT / "_build" / "package_remote.py").read_text(encoding="utf-8")
match = re.search(r'VERSION\s*=\s*"([^"]+)"', text)
return match.group(1) if match else "0.0.0"
def build_license() -> None:
"""三份文档拼成一份,给 Inno 的许可页用。
每份之间加分隔线,免得读起来像一份文档。
⚠ 这里**顺手把版本号注入进去**,不让它依赖源文档里写的是什么。
为什么:源文档里的版本号是硬编码的,实测 docs/LICENSE.txt 一直
停在 1.7.1(升级脚本只替换当时那个版本号,比如 1.8.2 ->
1.9.0,而 LICENSE.txt 里写的是 1.7.1,就永远匹配不上)。
结果安装时许可页上显示的是 1.7.1。
改成在这里统一注入之后,源文档写什么都不影响:
版本:X.Y.Z -> 版本:<当前版本>
软件:ykxmz X.Y.Z -> 软件:ykxmz <当前版本>
⚠ 只改**头部和落款**这两个格式,不改"八、版本记录"里的历史条目
—— 那是变更日志,本来就是一堆旧版本号。
"""
version = current_version()
parts = []
for index, name in enumerate(DOCS):
path = ROOT / "docs" / name
if not path.is_file():
print(f" [警告] 缺少 {name}")
continue
text = path.read_text(encoding="utf-8-sig").strip()
# 把"版本:x.y.z"和"软件:ykxmz x.y.z"换成当前版本,
# 但跳过"版本记录"那一段(历史日志)。
out_lines = []
in_history = False
for line in text.splitlines():
stripped = line.strip()
if "版本记录" in stripped:
in_history = True
if not in_history:
if re.match(r"^版本:\d+\.\d+\.\d+$", stripped):
line = line.replace(stripped, f"版本:{version}")
elif re.match(r"^软件:ykxmz \d+\.\d+\.\d+$", stripped):
line = line.replace(stripped, f"软件:ykxmz {version}")
out_lines.append(line)
text = "\n".join(out_lines)
if index:
parts.append("")
parts.append("=" * 70)
parts.append("")
parts.append(text)
body = "\n".join(parts) + "\n"
# 装许可页的正文要 UTF-8 **带 BOM**,否则 Inno 在中文系统上会显示乱码
COMBINED.write_bytes(b"\xef\xbb\xbf" + body.encode("utf-8"))
print(f" 合并三份文档 -> {COMBINED.name}"
f"({len(body)} 字符,版本注入为 {version})")
def sync_version(version: str) -> None:
text = ISS.read_text(encoding="utf-8")
new = re.sub(r'#define MyAppVersion "[^"]*"',
f'#define MyAppVersion "{version}"', text)
if new != text:
ISS.write_text(new, encoding="utf-8", newline="\r\n")
print(f" .iss 版本号 -> {version}")
else:
print(f" .iss 版本号已经是 {version}")
def main() -> int:
if not ISCC.is_file():
print(f" [失败] 找不到 Inno Setup: {ISCC}")
return 1
version = current_version()
print(f" 编译 ykxmz 安装包 v{version}")
print()
build_license()
sync_version(version)
agent = ROOT / "dist_exe" / "ykxmz" / "ykxmz.exe"
if not agent.is_file():
print(f" [失败] 被控端还没构建:{agent}")
print(" 先跑 windows\\build_exe.ps1")
return 1
print()
print(" 调 ISCC 编译…")
proc = subprocess.run([str(ISCC), str(ISS)],
capture_output=True, text=True,
encoding="utf-8", errors="replace", timeout=1800)
out = (proc.stdout or "") + (proc.stderr or "")
for line in out.splitlines():
line = line.strip()
if line and ("Error" in line or "error" in line
or "Successful" in line or "compil" in line.lower()
or "warning" in line.lower()):
print(f" {line}")
if proc.returncode != 0:
print(f" [失败] ISCC 退出码 {proc.returncode}")
print(out[-1500:])
return 1
exe = ROOT / "dist" / f"ykxmz-setup-{version}.exe"
if not exe.is_file():
print(f" [失败] 没生成 {exe}")
return 1
size = exe.stat().st_size / 1024 / 1024
print()
print(f" ✓ 安装包: {exe.name} {size:.2f} MB")
return 0
if __name__ == "__main__":
sys.exit(main())