☰
itch 桌面应用上架 Epic Games Store:用 BuildPatchTool 发布 itch-setup 引导器的完整流程
2026/10/14 15:35:41 网站建设 项目流程
  • 桌面应用

【免费下载链接】itch

🎮 The best way to play your itch.io games

项目地址:https://gitcode.com/gh_mirrors/it/itch
点击查看免费下载

本文基于 itch 桌面应用仓库中的 Epic Games Store 发布指南,完整讲解如何仅上传 itch-setup 引导器(而非整个 Electron 应用)来上架 Epic 商店:包括 BuildPatchTool(BPT)的前置准备、bpt_creds凭据文件结构、Windows/macOS 双平台的UploadBinary命令参数、Live标签上线与回滚机制,并结合仓库源码说明为什么--prefer-launch参数是这套方案能成立的关键。读完后你可以复现从下载二进制、组装 BuildRoot、上传到打标上线的全套 CLI 操作,并理解商店更新频率为何远低于应用本身。

核心思路:上传引导器,而不是整个应用

itch 是一个 Electron 应用(主进程 + React 渲染进程),游戏下载、安装、自更新由两个外部 Go 组件完成:butler(游戏操作守护进程)与 itch-setup(应用安装与自更新引导器),两者都通过自建的 broth 分发服务托管,架构图见 README.md 的 "App Architecture" 一节。

这一架构直接决定了 Epic 商店的发布策略,发布指南 开宗明义:

We upload the itch-setup bootstrapper as the "game", not the full app. Epic's launcher runs itch-setup, which installs the real app and keeps it updated through our own channels. Store updates are only needed when itch-setup changes.

也就是说:

  • Epic 商店里的"游戏本体"只是 itch-setup 引导器(Windows 下即itch-setup.exe,macOS 下即Install itch.app内的 universal 二进制);
  • Epic 启动器每次运行 itch-setup,由它安装真正的 itch 应用,并通过 itch 自己的更新通道(broth 服务 + self-update 逻辑)持续更新应用;
  • 因此只有当 itch-setup 本身发生变化时,才需要向商店推送新的二进制。商店端更新频率与 itch-setup 的发版节奏解耦,大幅降低了商店侧的发布负担。

从源码可以印证这条"应用自更新不依赖商店"的链路:self-update.ts 中actions.checkForComponentUpdates会调用 broth 的manager.upgrade(),对butler、itch-setup以及应用自身三个包统一做版本升级(包列表定义见 manager.ts 第 15 行的regularPackageNames = ["butler", "itch-setup"]);组件约束声明在 formulas.ts,itch-setup 的稳定通道约束为^1.8.0。这些更新全部走 broth.itch.zone,与 Epic 完全无关。

此外,上传工具选用 Epic 官方的 BuildPatchTool(BPT),它自带原生 Linux 二进制,所以整个 Windows 平台二进制的上传过程不需要 Windows 机器或 Wine。

前置准备:BuildPatchTool 与 bpt_creds 凭据文件

指南列出的前置条件有两项。

1. 下载 BuildPatchTool

从 Epic Dev Portal 的 Library Items 页面下载,Linux 下的可执行文件位于Engine/Binaries/Linux/BuildPatchTool。

2. 准备 bpt_creds 文件

该文件保存在仓库之外(含凭据,不入库),每行一条KEY="value":

BPT_CLIENT_ID="..." BPT_CLIENT_SECRET="..." ORGANIZATION_ID="..." PARMESAN_PRODUCT_ID="..." LIBRARY_PARMESAN_STAGING_ID="..." LIBRARY_PARMESAN_PRODUCTION_ID="..."

各字段来源:

  • LIBRARY_*是 Dev Portal 中的 library item ID;在 BPT 的命令行语义里它们被称为ArtifactId(注意这个命名对应关系,后面命令会用到);
  • 客户端凭据(BPT_CLIENT_ID/BPT_CLIENT_SECRET)来自 Product Settings 中的 "BPT credentials" 标签页;
  • STAGING/PRODUCTION两个 library ID 分别对应预发布与生产环境,日常上传针对生产环境。

统一的环境准备片段

指南中所有命令共享同一段 shell 准备逻辑,其作用是把凭据导入环境变量、定位 BPT 二进制、并把公共参数打包成一个 shell 数组:

set -a; source /path/to/bpt_creds; set +a BPT=/path/to/BuildPatchTool_1.8.8/Engine/Binaries/Linux/BuildPatchTool CREDS=( -OrganizationId="$ORGANIZATION_ID" -ProductId="$PARMESAN_PRODUCT_ID" -ArtifactId="$LIBRARY_PARMESAN_PRODUCTION_ID" -ClientId="$BPT_CLIENT_ID" -ClientSecretEnvVar=BPT_CLIENT_SECRET )

几个值得注意的细节:

  • set -a; source ...; set +a:set -a使 source 进来的变量自动导出为环境变量,set +a之后关闭该行为;
  • -ClientSecretEnvVar=BPT_CLIENT_SECRET:注意这里传的是环境变量名而不是值——BPT 约定从环境读取 secret,避免 secret 出现在命令行/进程列表中;
  • PARMESAN_PRODUCT_ID:itch 应用在该文档中的 Epic 产品标识就叫 PARMESAN(代码库中也无其他关联,仅作为商店侧命名出现);
  • 数组展开"${CREDS[@]}"保证每个-Xxx参数独立传递,含空格的路径(如Install itch.app/...)也能安全拼接。

查看当前状态:ListBinaries 与 ExtractMetaData

上传前后都应先查一遍现状:

"$BPT" -mode=ListBinaries "${CREDS[@]}"
  • 追加-OutputFile=binaries.json可得到含签名 manifest URL的 JSON 输出;
  • 要检查某个已上传二进制的启动配置与文件清单,先下载它的 manifest URL,再执行:
"$BPT" -mode=ExtractMetaData -InputFile=x.manifest -OutputFile=x.json

ExtractMetaData在 macOS 上传流程中承担上线前校验职责(见下文),也可随时用来排查"商店启动入口到底指向什么、带了什么参数"。

上传 Windows 平台二进制

完整命令如下(X.Y.Z 替换为 itch-setup 的实际版本号):

mkdir buildroot-win64 curl -sL https://broth.itch.zone/itch-setup/windows-amd64/LATEST/archive.zip -o win64.zip unzip -d buildroot-win64 win64.zip # contains itch-setup.exe "$BPT" -mode=UploadBinary "${CREDS[@]}" \ -BuildRoot="$PWD/buildroot-win64" \ -BuildVersion="itch-setup-X.Y.Z-win64" \ -AppLaunch="itch-setup.exe" \ -AppArgs="--prefer-launch" \ -CloudDir="$PWD/clouddir"

步骤拆解:

  1. 从 broth 分发端拉取 itch-setup 的windows-amd64最新版archive.zip(URL 结构与 README.md 中 "Remote Distribution" 一节描述一致:https://broth.itch.zone/{package}/{platform}/{version});
  2. 解压出itch-setup.exe作为 BuildRoot 内容;
  3. 调用 BPT 的UploadBinary模式上传。

各参数的含义与约束:

参数说明
-BuildRoot上传根目录,Epic 会将其内的文件原样安装到用户机器
-BuildVersion构建版本号,同一 artifact 下跨平台必须唯一;允许字符a-z A-Z 0-9 . + - _,不能含空格
-AppLaunchEpic 启动器每次运行时实际执行的入口,这里就是itch-setup.exe
-AppArgs传给入口的固定参数,必须带--prefer-launch
-CloudDir上传过程的本地暂存目录(scratch space),用完即删

指南给出的两条关键注意事项:

  1. 先加-DryRun验证再真上传:-DryRun模式只校验不上传,适合首次接触某个 BuildRoot 结构时使用;
  2. --prefer-launch是必需的:Epic 每次启动都会直接执行这个 exe;没有该参数时 itch-setup 每次都会弹出安装器窗口,而带上它则直接进入"启动已安装应用"的快路径。

--prefer-launch在 itch 代码库中并非孤例,它正是 itch-setup 作为"稳定启动 shim"的统一约定:

  • preboot.ts 中registerUrlProtocols将itchio:///itch://协议注册到itch-setup.exe --prefer-launch --appname <app> -- ...,注释明确说明这是为了避免指向版本化的app-X.Y.Z可执行文件而在自更新后失效;
  • open-at-login.ts 中 Windows 登录项同样注册为--prefer-launch --appname <app>;
  • itch-setup.ts 中runItchSetup/syncItchSetupLauncher通过--appname、--sync-launcher等参数驱动引导器同步各入口指向。

也就是说,无论 URL 协议、开机自启还是 Epic 启动器,所有外部入口都收敛到同一个"永不移动的 itch-setup shim",--prefer-launch保证它优先直接拉起已安装的应用而非展示安装界面。

上传 macOS 平台二进制

macOS 上传有三个要点:上传的是签名后的Install itch.app(从 install-itch DMG 中提取),而不是 DMG 本身;bundle 内的 itch-setup 是 universal(x86_64 + arm64),一次上传同时覆盖两种架构;由于在 Linux 上操作,需要额外用 FileAttributeList 标记二进制可执行。

curl -sL https://broth.itch.zone/install-itch/darwin-universal/LATEST/archive.zip -o mac.zip unzip mac.zip # contains Install itch.dmg mkdir buildroot-mac && cd buildroot-mac 7z x "../Install itch.dmg" # extracts Install itch.app cd .. # Mark the binary executable (we upload from Linux). \r\n ending required. printf '"Install itch.app/Contents/MacOS/itch-setup" executable\r\n' > mac-attributes.txt "$BPT" -mode=UploadBinary "${CREDS[@]}" \ -BuildRoot="$PWD/buildroot-mac" \ -BuildVersion="itch-setup-X.Y.Z-mac" \ -AppLaunch="Install itch.app/Contents/MacOS/itch-setup" \ -AppArgs="--prefer-launch" \ -FileAttributeList="$PWD/mac-attributes.txt" \ -CloudDir="$PWD/clouddir-mac"

逐条说明:

  1. 为什么不用 DMG:Epic 的安装器是"把文件原样落盘"的模型,无法挂载 disk image,所以必须把.appbundle 拆开上传;用7z可以直接解出Install itch.dmg内的Install itch.app;
  2. -FileAttributeList的格式要求:每行一个<相对路径> <属性>条目,且必须以 CRLF(\r\n)结尾——这就是示例中printf ... \r\n的原因。从 Linux 上传时 tar/7z 解出的文件不带可执行位,不标记的话 Epic 客户端安装后无法执行入口二进制;
  3. -AppLaunch含空格的路径:Install itch.app/Contents/MacOS/itch-setup,再次体现把参数放在 shell 数组中、整体引号展开的必要性;
  4. 上线前校验:指南要求用ExtractMetaData确认 itch-setup 的 manifest 元数据中IsExecutable: true,即:
"$BPT" -mode=ExtractMetaData -InputFile=x.manifest -OutputFile=x.json

上线:LabelBinary 打标与回滚

上传本身对用户不产生任何影响,直到Live标签指向该二进制:

"$BPT" -mode=LabelBinary "${CREDS[@]}" \ -BuildVersion="itch-setup-X.Y.Z-win64" \ -Label="Live" \ -Platform="Windows" # or "Mac"

要点:

  • -Platform取"Windows"或"Mac",Windows 与 macOS 需要分别打标;
  • 打标语义:应用Live后,原 live 二进制会被降级为Rollback,而旧的 rollback 则被取消标签(unlabel)——即系统始终保留一层自动回滚点;
  • 回滚方式:把Live重新指向上一版本号即可,无需重新上传;
  • 每次打标后按指南要求用ListBinaries复核各平台 Live / Rollback 指向是否如预期。

完整工作流小结

将上述步骤串起来,一次 itch-setup 商店发布的标准流程是:

  1. 准备:set -a; source bpt_creds; set +a,设置BPT与CREDS数组;
  2. ListBinaries查看当前 Live / Rollback 状态;
  3. Windows:拉取broth.itch.zone/itch-setup/windows-amd64/LATEST/archive.zip,解压到buildroot-win64,UploadBinary(建议先-DryRun);
  4. macOS:拉取broth.itch.zone/install-itch/darwin-universal/LATEST/archive.zip,用7z解出Install itch.app,写 CRLF 结尾的mac-attributes.txt,UploadBinary并带上-FileAttributeList;
  5. 用ExtractMetaData确认(尤其 macOS 的IsExecutable: true);
  6. LabelBinary -Label=Live -Platform=...分别对 Windows 与 Mac 打标;
  7. ListBinaries最终核验;删除clouddir/clouddir-mac等临时目录。

整个方案的技术核心在于"商店分发引导器、引导器负责安装与自更新"的分层:Epic 侧只承担 itch-setup 的下载与差分分发,itch 应用自身的持续更新由 broth 版本管理(formulas.ts的 semver 约束 + self-update.ts 的定时upgrade流程)独立完成。这也解释了为什么该发布指南如此简短——商店端的变化面被刻意压缩到了"一个引导器二进制 + 两个平台标签"的最小集合。

  • 桌面应用

【免费下载链接】itch

🎮 The best way to play your itch.io games

项目地址:https://gitcode.com/gh_mirrors/it/itch
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询