Release 只附加发布用 ZIP(ShogiBoardQ-macos.zip),不另行附加 Qt 源代码或相关文档。应用程序内许可文档的准备请参阅 Qt 文档与发布附件的方针(日文)。
DMG 中只放入运行 ShogiBoardQ 所需的文件(最小构成)。与 Linux 版一样,用于普通对局的 Hayanagi(USI 引擎)和诘棋题集放在 DMG 之外,与 DMG 一起放入发布用 ZIP(5.2)。界面语言有日语、英语、中文(简体、繁体)4 种,附带 4 个翻译文件。
目录
1. 前提条件
| 项目 | 版本 |
|---|---|
| macOS | 推荐 12 (Monterey) 以上 |
| Xcode | 14 以上(含 Command Line Tools) |
| CMake | 3.16 以上 |
| Qt | 6.7 以上(Widgets、Charts、Network、Concurrent、Multimedia、Sql、LinguistTools) |
| C++ | 支持 C++17 的编译器 |
2. 搭建开发环境
2.1 Xcode Command Line Tools
xcode-select --install
2.2 用 Homebrew 安装依赖工具
brew install cmake ninja
2.3 安装 Qt 6
方法 A:Qt Online Installer(推荐)
从 Qt 官方网站下载安装程序,并选择以下组件:
- Qt 6.x > macOS
- Qt 6.x > Qt Charts
- Qt 6.x > Qt Multimedia
- Developer and Designer Tools > CMake
安装后,将 Qt 的路径设置到环境变量中:
# 添加到 ~/.zshrc(Qt 的安装路径请根据实际环境修改)
export Qt6_DIR="$HOME/Qt/6.x.x/macos/lib/cmake/Qt6"
export PATH="$HOME/Qt/6.x.x/macos/bin:$PATH"
方法 B:Homebrew
brew install qt@6
使用 Homebrew 时,CMake 会自动检测到 Qt,因此多数情况下不需要设置环境变量。
2.4 确认安装
cmake --version # 3.16 以上
qmake --version # Qt 6.x
clang++ --version # Apple Clang
3. 构建
用于普通对局的 Hayanagi 是子模块,因此获取时要加上 --recurse-submodules(不加时 CMake 会停止):
git clone --recurse-submodules https://github.com/hnakada123/ShogiBoardQ.git
cd ShogiBoardQ
对于已获取的仓库,运行 git submodule update --init --recursive 获取所记录版本的 Hayanagi。
构建脚本(推荐)
使用 scripts/build-macos.sh,可以一次完成从 Release 构建到代码签名、制作 DMG 的全部步骤:
# 普通构建 + 制作 DMG
./scripts/build-macos.sh
# 构建通用二进制(arm64 + x86_64)
./scripts/build-macos.sh --universal
# 清理后构建,不制作 DMG
./scripts/build-macos.sh --clean --skip-dmg
# 尚未准备 Qt 许可文档时的测试用 DMG(不用于发布)
./scripts/build-macos.sh --clean --skip-qt-licenses
# 用 Developer ID 签名(默认为临时签名)
./scripts/build-macos.sh --sign-identity "Developer ID Application: Your Name (TEAMID)"
# 用 Developer ID 签名,公证 DMG 后再制作 ZIP
export APPLE_ID="your@email.com" APPLE_TEAM_ID="TEAMID" APPLE_APP_PASSWORD="app-specific-password"
./scripts/build-macos.sh --sign-identity "Developer ID Application: Your Name (TEAMID)" --notarize
| 选项 | 说明 |
|---|---|
--universal | 构建通用二进制(arm64 + x86_64) |
--deployment-target VER | 最低支持的 macOS 版本(默认:环境变量 MACOSX_DEPLOYMENT_TARGET,未设置时为 26.0) |
--sign-identity ID | 代码签名身份(默认:- = 临时(ad hoc)签名)。指定 Developer ID 时,会启用强化运行时(Hardened Runtime)并附加时间戳进行签名,DMG 也会签名 |
--notarize | 将 DMG 提交 Apple 公证,装订公证结果后再制作发布用 ZIP。需要用 --sign-identity 指定 Developer ID,并设置环境变量 APPLE_ID、APPLE_TEAM_ID、APPLE_APP_PASSWORD(App 专用密码) |
--skip-dmg | 跳过 DMG 和发布用 ZIP 的制作(只生成 .app 包) |
--skip-qt-licenses | 跳过添加 Qt 文档(日文),只保留构建时附带的简易文档(Contents/MacOS/licenses)。发布时不要使用 |
--clean | 删除 build 目录后再构建 |
--help | 显示帮助 |
脚本会自动执行以下处理:
- 确认所需工具(cmake、ninja、macdeployqt、codesign、vtool、python3、create-dmg)
- CMake 配置(指定
CMAKE_OSX_DEPLOYMENT_TARGET)+ Ninja 构建 - 确认构建产物(.app、可执行文件的最低 macOS 版本、.qm 翻译文件)
- 用 macdeployqt 打包框架
- 删除未使用的 Qt 组件,并把 Qt 二进制精简为 arm64(4.4。使用
--universal时不精简为 arm64)+ 验证 - 附带 Qt 许可文档(使用
--skip-qt-licenses时跳过) - 对整个应用程序包进行代码签名 + 用
codesign --verify --deep --strict验证 - 用 create-dmg 制作 DMG(使用 Developer ID 时也对 DMG 签名)
- 使用
--notarize时,对 DMG 进行公证和装订 + 验证 - 制作包含 DMG、Hayanagi 和诘棋题集的发布用 ZIP(
ShogiBoardQ-macos.zip)(5.2)
关于最低 macOS 版本:如果不指定部署目标(deployment target),构建主机的 macOS 版本就会成为最低支持版本(例:在 macOS 27 上构建后,无法在 macOS 26 上启动)。脚本默认指定
26.0,构建后如果可执行文件的minos不一致就会停止。关于代码签名:macdeployqt 会改写二进制,因此运行后的应用程序包只剩链接器签名,无法通过严格的签名验证。脚本在 macdeployqt 之后重新对整个应用程序包签名,然后再制作 DMG。
关于 macdeployqt 显示的 ERROR:会出现
.qm: is not an object file(对翻译文件运行了 otool)、找不到 ODBC / PostgreSQL / Mimer SQL 驱动的依赖项,以及 macdeployqt 自身的签名错误,但都无害。这些驱动会在下一步删除,签名也会由脚本重新进行并严格验证。
以下是手动逐条运行命令时的步骤。
3.1 Release 构建
cd /path/to/ShogiBoardQ
# 配置(Release 构建)
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release
# 构建(并行构建)
cmake --build build --config Release -- -j$(sysctl -n hw.ncpu)
使用 Ninja 时(更快):
cmake -B build -S . -G Ninja -DCMAKE_BUILD_TYPE=Release
ninja -C build
3.2 确认构建产物
# 确认已生成 .app 包
ls -la build/ShogiBoardQ.app/
# 确认包内的结构
find build/ShogiBoardQ.app -type f | head -20
构建后的包结构:
ShogiBoardQ.app/
├── Contents/
│ ├── Info.plist
│ ├── MacOS/
│ │ ├── ShogiBoardQ ← 可执行文件
│ │ ├── ShogiBoardQ_ja_JP.qm ← 日语翻译
│ │ ├── ShogiBoardQ_en.qm ← 英语翻译
│ │ ├── ShogiBoardQ_zh_CN.qm ← 简体中文翻译
│ │ ├── ShogiBoardQ_zh_TW.qm ← 繁体中文翻译
│ │ └── licenses/ ← 许可文档(简易版)
│ └── Resources/
│ └── shogiboardq.icns ← 应用程序图标
3.3 运行确认
# 启动构建好的应用程序
open build/ShogiBoardQ.app
4. 制作应用程序包
注:使用
scripts/build-macos.sh时,本节的步骤会自动执行,无需手动运行。
4.1 用 macdeployqt 打包 Qt 框架
仅仅构建的话,Qt 的动态库不会包含在应用程序包中。使用 macdeployqt 将所需的 Qt 框架和插件复制到包内。
macdeployqt build/ShogiBoardQ.app -verbose=2
macdeployqt 自动执行的处理:
- 将依赖的 Qt 框架(QtWidgets、QtCharts、QtNetwork、QtMultimedia、QtGui、QtCore 等)复制到
Contents/Frameworks/ - 将 Qt 插件(platforms/cocoa、imageformats/svg 等)复制到
Contents/PlugIns/ - 改写库的
@rpath(install_name_tool) - 在
Contents/Resources/中生成qt.conf
4.2 确认打包后的结构
# 确认框架已正确打包
ls build/ShogiBoardQ.app/Contents/Frameworks/
# 确认包含插件
ls build/ShogiBoardQ.app/Contents/PlugIns/
# 确认依赖关系中没有残留外部路径
otool -L build/ShogiBoardQ.app/Contents/MacOS/ShogiBoardQ
如果 otool 的输出中残留 /usr/local/ 或 /opt/homebrew/ 的路径,说明打包不完整。
4.3 确认翻译文件
CMake 的构建后步骤会把 .qm 文件放到 Contents/MacOS/。确认运行 macdeployqt 后文件仍然存在:
ls build/ShogiBoardQ.app/Contents/MacOS/*.qm # 4 个(ja_JP / en / zh_CN / zh_TW)
Qt 标准对话框的翻译(qtbase_ja / qtbase_zh_CN / qtbase_zh_TW)嵌入在可执行文件的资源中,因此不需要单独的文件。
4.4 删除未使用的 Qt 组件(最小构成)
macdeployqt 会按类别放入所有 Qt 插件,并通过虚拟键盘插件连带引入 Qt Quick / QML(约 187MB)。删除 ShogiBoardQ 不使用的部分,在仅面向 Apple 芯片的发布中还要去掉 Qt 的 x86_64 部分(约 89MB,DMG 约 50MB)。
| 删除的内容 | 理由 |
|---|---|
PlugIns/platforminputcontexts/、QtQml* / QtQuick / QtVirtualKeyboard* | 不使用虚拟键盘和 QML |
PlugIns/tls/ 中 SecureTransport 以外的后端、PlugIns/networkinformation/ | 网络对局的“TLS(加密)”使用基于 macOS 标准 Security 框架的 SecureTransport 后端(OpenSSL 后端需要同捆 libssl)。不使用网络信息插件 |
PlugIns/multimedia/libffmpegmediaplugin.dylib、libav* / libsw* | 棋子音效使用 macOS 标准的 darwin 后端播放 |
PlugIns/sqldrivers/ 中 SQLite 以外的驱动 | 只使用 SQLite |
PlugIns/imageformats/ 中的 gif / wbmp / macheif / icns / tga / macjp2 | 只使用 SVG / ICO(图标)和 JPEG / TIFF / WebP(导出棋盘图片) |
C=build/ShogiBoardQ.app/Contents
rm -rf $C/PlugIns/platforminputcontexts $C/PlugIns/networkinformation \
$C/PlugIns/multimedia/libffmpegmediaplugin.dylib $C/Frameworks/libav*.dylib $C/Frameworks/libsw*.dylib \
$C/Frameworks/QtQml*.framework $C/Frameworks/QtQuick.framework $C/Frameworks/QtVirtualKeyboard*.framework
find $C/PlugIns/tls -name '*.dylib' ! -name libqsecuretransportbackend.dylib -delete
find $C/PlugIns/sqldrivers -name '*.dylib' ! -name libqsqlite.dylib -delete
for p in gif wbmp macheif icns tga macjp2; do rm -f $C/PlugIns/imageformats/libq$p.dylib; done
# 把 Qt 精简为只含 arm64(发布通用二进制时不要执行)
find $C -type f \( -perm +111 -o -name '*.dylib' \) | while read -r f; do
if lipo -archs "$f" 2>/dev/null | grep -q x86_64; then
lipo "$f" -thin arm64 -output "$f.thin" && chmod "$(stat -f %Lp "$f")" "$f.thin" && mv "$f.thin" "$f"
fi
done
保留的是 12 个 Qt 框架(Charts、Concurrent、Core、DBus、Gui、Multimedia、Network、OpenGL、OpenGLWidgets、Sql、Svg、Widgets)和 10 个插件(cocoa、macstyle、svgicon、darwin multimedia、sqlite、securetransport、ico / jpeg / tiff / webp)。删除后要重新对整个应用程序包签名(6.4。临时签名时为 codesign --force --deep --sign - build/ShogiBoardQ.app)。
启动后,确认加载的库全部来自包内:
open build/ShogiBoardQ.app
lsof -p "$(pgrep -x ShogiBoardQ)" | grep -E '/Qt/|homebrew' # 没有任何输出即可
5. 制作 DMG 文件
注:使用
scripts/build-macos.sh时,会用方法 B(create-dmg)自动制作,无需手动运行。也可以用--skip-dmg选项只跳过 DMG 的制作。手动制作时,也要在放入 DMG 之前完成 4.4 的删除和签名。方法 A 由 macdeployqt 直接制作 DMG,因此不是最小构成。
方法 A:macdeployqt 的 -dmg 选项(简易)
macdeployqt build/ShogiBoardQ.app -dmg
会生成 build/ShogiBoardQ.dmg。方法简单,但没有背景图片,也没有指向 Applications 文件夹的链接。
方法 B:create-dmg(推荐 - 自定义 DMG)
制作外观美观、用户可以拖放到 Applications 文件夹的 DMG。
安装
brew install create-dmg
制作 DMG
# 用 macdeployqt 制作应用程序包(不加 -dmg)
macdeployqt build/ShogiBoardQ.app
# 制作 DMG
create-dmg \
--volname "ShogiBoardQ" \
--volicon "resources/icons/shogiboardq.icns" \
--window-pos 200 120 \
--window-size 600 400 \
--icon-size 100 \
--icon "ShogiBoardQ.app" 150 190 \
--hide-extension "ShogiBoardQ.app" \
--app-drop-link 450 190 \
"ShogiBoardQ.dmg" \
"build/ShogiBoardQ.app"
选项说明
| 选项 | 说明 |
|---|---|
--volname | 装载时的卷名 |
--volicon | 卷图标 |
--window-pos | DMG 窗口的显示位置(x y) |
--window-size | DMG 窗口的大小(宽 高) |
--icon-size | 图标大小(px) |
--icon | 应用程序图标的显示位置(名称 x y) |
--hide-extension | 隐藏 .app 扩展名 |
--app-drop-link | 指向 Applications 文件夹的链接位置(x y) |
方法 C:hdiutil(手动 - 完全控制)
# 创建临时目录
mkdir -p dmg_staging
cp -R build/ShogiBoardQ.app dmg_staging/
ln -s /Applications dmg_staging/Applications
# 制作 DMG
hdiutil create -volname "ShogiBoardQ" \
-srcfolder dmg_staging \
-ov -format UDZO \
"ShogiBoardQ.dmg"
# 清理
rm -rf dmg_staging
5.1 验证 DMG
# 装载后确认运行
hdiutil attach ShogiBoardQ.dmg
open /Volumes/ShogiBoardQ/ShogiBoardQ.app
# 推出
hdiutil detach /Volumes/ShogiBoardQ
5.2 发布用 ZIP
脚本在制作 DMG 之后,会在仓库根目录制作 ShogiBoardQ-macos.zip。结构与 Linux 版的 ZIP 相同。
ShogiBoardQ-macos/
├── ShogiBoardQ.dmg
├── README.md ← resources/platform/README-macos.md
├── LICENSE
├── Hayanagi/
│ ├── hayanagi ← 用于普通对局的 USI 引擎(arm64,最低 macOS 版本与应用程序相同)
│ ├── book/hayanagi_book.db ← Hayanagi 的定式
│ └── README.md
└── data/tsumeshogi/
├── tsume_{3,5,7,9,11,13}ply_1000_YYYYMMDD.txt
└── README.md
- 题集每种手数只能有 1 个文件。如果残留旧版本等文件,脚本会停止。
hayanagi使用对build/Hayanagi/hayanagi执行strip -x后的文件,并用与应用程序相同的身份(默认为临时签名)重新签名。- 定式文件
hayanagi_book.db使用构建时复制到build/Hayanagi/book/的文件,放入Hayanagi/book/。Hayanagi 从工作目录的book/读取定式,而 ShogiBoardQ 以引擎所在的目录作为工作目录启动引擎,因此解压后即可直接使用定式。 - 下载的
hayanagi会带有隔离属性,因此 README 中说明了xattr -d com.apple.quarantine Hayanagi/hayanagi。
unzip -l ShogiBoardQ-macos.zip
# 确认 Hayanagi 能响应并读取定式(与 ShogiBoardQ 一样在 Hayanagi/ 中启动)
(cd build/ShogiBoardQ-macos/Hayanagi && (printf 'usi\nisready\nposition startpos\ngo movetime 300\n'; sleep 1.5; echo quit) | ./hayanagi | grep -E 'book|usiok|readyok|bestmove')
6. 代码签名与公证
对外发布时,为了通过 Apple 的 Gatekeeper,需要进行代码签名和公证。不经公证也能运行,但首次打开下载的应用程序时会显示 Gatekeeper 的警告,需要用户允许(6.6)。
6.1 加入 Apple Developer Program
代码签名和公证需要加入 Apple Developer Program(年费 99 美元)。
6.2 获取签名用证书
在 Xcode > Settings > Accounts 中创建以下证书:
- Developer ID Application — 用于对应用程序本身签名
- Developer ID Installer — 用于对 DMG / pkg 签名(可选)
6.3 用 macdeployqt 制作带代码签名的应用程序包
macdeployqt build/ShogiBoardQ.app \
-sign-for-notarization="Developer ID Application: Your Name (TEAMID)"
使用这个选项时,macdeployqt 会:
- 打包 Qt 框架和插件
- 对所有框架、插件和可执行文件进行代码签名
- 启用
--options=runtime(强化运行时)
6.4 手动进行代码签名
不使用 macdeployqt 的签名选项时:
# 递归地对包内的所有二进制签名
codesign --deep --force --verify --verbose \
--sign "Developer ID Application: Your Name (TEAMID)" \
--options runtime \
build/ShogiBoardQ.app
# 验证签名
codesign --verify --deep --strict --verbose=2 build/ShogiBoardQ.app
6.5 公证(Notarization)
使用脚本时,用 --sign-identity 指定 Developer ID 并加上 --notarize,脚本会把 DMG 提交公证并装订,然后再制作发布用 ZIP(3. 构建)。公证未通过时会显示提交 ID 并停止。以下是手动进行时的步骤。
# 制作 DMG(使用已签名的应用程序包)
# ...(按第 5 节的方法制作 DMG)
# 提交公证
xcrun notarytool submit ShogiBoardQ.dmg \
--apple-id "your@email.com" \
--team-id "TEAMID" \
--password "app-specific-password" \
--wait
# 装订(把公证结果嵌入 DMG)
xcrun stapler staple ShogiBoardQ.dmg
# 验证装订
xcrun stapler validate ShogiBoardQ.dmg
注意:
--password使用的不是 Apple 账户的密码,而是 App 专用密码。
6.6 不经公证发布时
不经公证就发布时,下载的应用程序在首次启动时会被 Gatekeeper 拦截。从 macOS 15 开始,无法再通过在 Finder 中右键点按 → “打开”来打开,因此请向用户说明以下步骤:
- 打开应用程序,显示警告后将其关闭
- 打开“系统设置”→“隐私与安全性”,点按“仍要打开”,并按提示允许
或者在终端中解除 Gatekeeper 的隔离属性(没有显示“仍要打开”时也使用这个方法):
xattr -cr /Applications/ShogiBoardQ.app
7. 在 GitHub Releases 上发布
7.1 创建标签
版本号只在发布当天改为当天的日期(版本号与发布的运作方式,日文)。制作发布包之前,先修改 CMakeLists.txt 中的 APP_VERSION 并提交,用该提交制作发布包,然后在同一提交上打上相同版本号的标签。标签不加 v。
git tag -a 2026.10.07 -m "ShogiBoardQ 2026.10.07"
git push origin main 2026.10.07
7.2 用 GitHub CLI 创建 Release
使用 GitHub CLI (gh):
# 安装
brew install gh
# 登录(仅首次)
gh auth login
创建 Release 并上传附件:
gh release create 2026.10.07 \
--title "ShogiBoardQ 2026.10.07" \
--notes-file RELEASE_NOTES.md \
ShogiBoardQ-macos.zip
同时发布 Windows 的 ZIP 时,添加附件:
gh release create 2026.10.07 \ --title "ShogiBoardQ 2026.10.07" \ --notes-file RELEASE_NOTES.md \ ShogiBoardQ-macos.zip \ ShogiBoardQ-windows.zip
自动生成发布说明
不准备发布说明文件时,由 GitHub 自动生成:
gh release create 2026.10.07 \
--title "ShogiBoardQ 2026.10.07" \
--generate-notes \
ShogiBoardQ-macos.zip
向已有的 Release 添加附件
已在 Windows 端先创建了 Release 时,添加 macOS 的 ZIP:
gh release upload 2026.10.07 ShogiBoardQ-macos.zip
7.3 在网页界面上创建 Release(替代方法)
- GitHub 仓库 → Releases → Draft a new release
- Choose a tag → 输入新标签(例:
2026.10.07)并创建 - 输入 Release title(例:
ShogiBoardQ 2026.10.07) - 在 Description 中填写发布说明
- 将
ShogiBoardQ-macos.zip拖放到 Attach binaries - 点击 Publish release
7.4 发布说明的写法(模板)
## ShogiBoardQ 2026.10.07
### 下载
| OS | 文件 |
|---|---|
| macOS | `ShogiBoardQ-macos.zip` |
| Windows (64-bit) | `ShogiBoardQ-windows.zip` |
### 在 macOS 上启动
1. 解压 ZIP,打开 `ShogiBoardQ.dmg`
2. 将 ShogiBoardQ.app 拖放到 Applications 文件夹
3. 从 Applications 启动
> 由于未经 Apple 公证,首次启动时会显示警告而无法打开。
> 在“系统设置”→“隐私与安全性”中点按“仍要打开”即可启动。
### 变更内容
- ...
8. 故障排除
找不到 Qt
CMake Error: Could not find a package configuration file provided by "Qt6"
明确指定 Qt 的安装路径:
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH="$HOME/Qt/6.x.x/macos"
找不到 macdeployqt
# 确认 Qt 的安装路径
which macdeployqt
# 找不到时,添加到 PATH
export PATH="$HOME/Qt/6.x.x/macos/bin:$PATH"
# 使用 Homebrew 时
export PATH="$(brew --prefix qt@6)/bin:$PATH"
macdeployqt 没有打包 Qt Charts
macdeployqt 有时无法自动检测到 Qt Charts。这时需要手动复制:
# 确认是否遗漏打包
otool -L build/ShogiBoardQ.app/Contents/MacOS/ShogiBoardQ | grep Charts
# 手动复制(需要时)
cp -R "$HOME/Qt/6.x.x/macos/lib/QtCharts.framework" \
build/ShogiBoardQ.app/Contents/Frameworks/
# 用 install_name_tool 修正引用路径
install_name_tool -change \
@rpath/QtCharts.framework/Versions/A/QtCharts \
@executable_path/../Frameworks/QtCharts.framework/Versions/A/QtCharts \
build/ShogiBoardQ.app/Contents/MacOS/ShogiBoardQ
首次启动时无法打开(未经公证时)
向用户说明以下任一方法:
- 在“系统设置”→“隐私与安全性”中点按“仍要打开”(仅首次。从 macOS 15 开始,在 Finder 中右键点按 → “打开”无法打开)
- 在终端中运行
xattr -cr /Applications/ShogiBoardQ.app
无法加载翻译
确认包内存在 .qm 文件:
find build/ShogiBoardQ.app -name "*.qm"
Contents/MacOS/ 中没有 .qm 文件时,手动复制:
cp build/ShogiBoardQ_{ja_JP,en,zh_CN,zh_TW}.qm build/ShogiBoardQ.app/Contents/MacOS/
制作通用二进制(Intel + Apple 芯片)
制作同时支持两种架构的二进制时:
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"
cmake --build build --config Release
注意:Qt 本身也必须安装通用二进制版本。