A contributor who only wants to try a change should not have to install vcpkg, Boost, Inno Setup and the Windows SDK. The Dev build workflow builds, packages and signs on the runner, and the artifact is a full installer plus its signing certificate. Three ways in: a feature-branch push builds automatically; a pull_request run gives reviewers and fork contributors an installer from the check page (pull_request deliberately, not pull_request_target -- building PR code executes scripts from that code, and pull_request_target would hand those scripts a writable token); workflow_dispatch stays for picking a single component or rebuilding without a push. develop, main and release-please maintenance branches never trigger it. The certificate is minted per run by installer/sign-dev-build.ps1 with the fixed subject CN=Metasequoia IME Dev Build Code Signing; the private key lives only in the runner's memory. installer/import-dev-trust.ps1 ships in the artifact for the user side: remove the previous certificate by subject, import the new one, so repeated builds do not grow the trust stores. The workflow reuses ci.yml's vcpkg cache scopes and sccache, downloads the locked dictionaries, embeds the uiAccess manifest and passes the dev version through MSIME_PRODUCT_VERSION_OVERRIDE so the about page shows the full dev string. Artifacts expire in 7 days. ci.yml remains the merge gate; nothing here creates a release or touches the update manifest.
7.8 KiB
参与 MSIME-Windows 开发
组织级的通用约定(行为准则、PR 要求、安全上报)见组织贡献指南。这份文档只讲本仓特有的东西:环境、怎么把它编出来、改哪一层、以及提交前要跑什么。
想找活干的话先看招募开源开发者和 good first issue。不写代码也有事情可做:词库条目、文档、图标资源、兼容性测试都在 no-code 标签下。
环境
- Windows 10 / 11
- Visual Studio 2026(需要 C++ 桌面开发工作负载)
- CMake 3.25+
- vcpkg,并把
VCPKG_ROOT设进环境变量 - Python 3.10+
- Inno Setup 6.6+(只有要打安装包时才需要)
Boost 按 -DBoost_ROOT=... → 环境变量 BOOST_ROOT → %USERPROFILE%\scoop\apps\boost\current 的顺序解析。preset 里的 vcpkg 路径取自 $env{VCPKG_ROOT},不需要改文件。
没有本地工具链时:dev-build workflow
只想验证一个小改动、不想为它装一整套工具链的话,让 CI 编。Dev build workflow 平时不跑主分支(develop 和 main 有自己的 CI 和发布流),三种触发方式:
# 特性分支一推就自动编,不需要任何手动操作
git push -u origin fix/xxx
# 或者手动触发,可选单个组件快速迭代
gh workflow run dev-build.yml --ref <你的分支> -f component=all
# 等 run 结束拿产物;agent 也可以在这里等
gh run list --workflow=dev-build.yml --branch <你的分支> --limit 1 --json databaseId,status
gh run watch <runId> --exit-status
gh run download <runId> -n dev-installer
开向 develop 的 PR 也会自动跑一次,评审者和 fork 贡献者都能从 PR 的检查页拿到安装包。安装只有两步:管理员 PowerShell 里运行解压出来的 import-dev-trust.ps1(导入本次构建的签名证书并清掉上一张),然后双击安装包。版本号带 -dev.<日期>.<commit>,一眼可辨,设置页的更新检查不会提示它升级。每次新构建的证书都不同,重装前重跑一次导入脚本即可;产物保留 7 天。
几个边界:workflow_dispatch 需要仓库写权限;fork PR 的构建用 pull_request 触发(只读 token,无 secrets),首个 run 要维护者点一次批准;component=tip 或 server 只编译单个组件出裸二进制;这个 workflow 不出 release、不碰更新清单,合并门槛仍然由 PR 上的 CI 把守。
取代码
git clone --recursive https://github.com/metasequoiaime/MSIME-Windows.git
cd MSIME-Windows
忘了 --recursive 的话补一句 git submodule update --init --recursive。vendor/ 下是 opencc 和 cpp-pinyin,缺了它们 Server 编不过。输入引擎在 engine/,是本仓的目录而不是 submodule,普通 clone 就有。
词库不在版本库里,构建时从 dict-* release 按锁定的 tag 和摘要取用:
python scripts/product_lock.py fetch-dictionaries --staging-root .
构建
没有顶层聚合的 CMakeLists.txt,这是有意的:TSF DLL 用静态 CRT、Server 用动态 CRT,两者的 vcpkg manifest 与编译选项互不兼容,合成一个 build tree 会互相污染。每个组件是独立的 CMake 工程,从仓库根目录指定 -S:
cmake -S windows -B windows/build64 -A x64 # TSF 文本服务 DLL
cmake -S server -B server/build -A x64 # Server
cmake -S ui -B ui/build -A x64 # 自研 GUI 框架 msimeui
server/ 通过 add_subdirectory(../ui ...) 把 msimeui 拉进自己的构建,这是唯一的跨组件构建引用。
每个组件也各自带了本地脚本,比手敲 cmake 省事:
.\windows\scripts\prepare_env.py # 生成 .clangd 并把 preset 指向本机 vcpkg/Boost
.\windows\scripts\lcompile.ps1 64 # Debug;换 32 编 32 位
.\server\scripts\lcompile.ps1
各组件更细的说明在各自的 README 与 AGENTS.md 里,那两份文件写给人和 AI 都一样有效:
windows/AGENTS.md— TSF 层的构建、注册与手工回归清单(这份清单是本仓最难替代的知识,改 TSF 前先读)server/README.md— Server 的开发构建与本地词库准备ui/README.md— GUI 框架的构建与边界约束installer/README.md— 打包AGENTS.md— 跨组件契约:协议只有一份来源,改哪边要同时改哪边
打一个可安装的包
从仓库根开始,严格按顺序。任一步失败先修,不要拿旧产物继续打包:
Set-Location .\windows
.\scripts\lcompile-release-both.ps1
Set-Location ..\server
.\scripts\lcompile-release.ps1
Set-Location ..\installer
.\Prepare-PackageFiles.ps1 -RepoRoot .. -TsfDirectory windows -ServerDirectory server -NoticesDirectory .
.\Sign-PackageBinaries-Local.ps1
.\Compile-Installer.ps1
Sign-PackageBinaries-Local.ps1 用的是本机测试证书,只用于内部安装验证;不要把本机证书指纹或私钥提交进仓库。
改动前要知道的几条边界
- 协议的唯一来源是
engine/contracts/。 IPC 线格式、opcode、语音分帧和设置窗口的消息定义都在那里,两侧引用同一份头文件,不要在任何一侧另写一份。 engine/是本仓的一等代码。 要为 Windows 改引擎就直接改,和改server/一样评审和测试;引擎和调用它的代码可以、也应该在同一个 PR 里。例外是engine/下的googlepinyinime-rev/、ngram/kenlm/、utfcpp/、voice/third_party/,那是上游副本。见 engine/UPSTREAM.md。ui/不许反向依赖产品。 它不读 Server 配置、IPC、引擎、词库或全局输入状态。ui/scripts/check-boundary.py在 CI 里检查。- 界面只有 Direct2D 一套,全部在
server/。 候选窗、工具栏、托盘菜单在server/src/window/,设置窗口在server/src/settings/native/,都用ui/的msimeui绘制。改设置窗口的消息type或 JSON 字段时,engine/contracts/webview/与settings_app.cpp一起改。 - 候选与输入状态的权威在 Server 和引擎,界面只负责展示。
提交前
ctest --test-dir server/build --output-on-failure # Server 单元测试(引擎随 Server 一起构建)
python -m unittest discover -s tests # 产品级组合验证
bash scripts/format.sh --check # 格式,覆盖 server/windows/ui/log/engine
bash scripts/ci/check-developer-paths.sh # 构建输入里不许出现个人目录路径
改了 TSF 层就照 windows/AGENTS.md 的手工回归清单跑一遍。输入法很难靠读代码判断对错,PR 里必须写清你怎么验证的:系统版本、宿主程序、操作步骤、观察到的结果、跑过的测试命令。
git status --short 确认只暂存本次任务涉及的路径,不要 git add -A。提交信息用 type(scope): 摘要,不要加 Co-Authored-By 或任何 AI 生成标记。
分支从 develop 切,PR 也合回 develop——它是本仓默认分支,开 PR 时不用改 base。main 是发布分支,只在发版时由维护者从 develop 合入;特性分支直接提到 main 会被 Branch guard 检查拦下,把 base 改回 develop 即可。发布链条见 docs/product-release.md。
不要在 PR、Issue、截图或日志里泄露 API Key。仓库开了 secret scanning 和 push protection,但那是最后一道防线不是第一道。