【免费下载链接】Whisky
Active community fork of the archived whisky-app/whisky — a modern Wine wrapper for macOS built with SwiftUI
Whisky 是一款用 SwiftUI 原生构建的 macOS Wine 封装器,其核心库 WhiskyKit 通过Bottle 管理、Wine 执行、Program 发现三层协作,让你在 Mac 上无痛运行 Windows 游戏与程序。本文将用图解方式拆解这三层各自的职责与数据流向,帮助新手快速理解 Whisky 的架构设计。
一分钟认识 Whisky 与 WhiskyKit
| 组件 | 定位 |
|---|---|
| Whisky.app | 面向用户的 SwiftUI 图形界面 |
| WhiskyCmd | 命令行工具(whisky run等) |
| WhiskyKit | 可复用的 Swift 包,三层架构的核心 |
| WhiskyWine | Wine 11.0 运行时(首次启动时自动下载) |
WhiskyKit 的官方架构文档见 Architecture.md,它将整个系统组织为"应用层 → WhiskyKit → Wine 运行时"三个纵向层次:
┌─────────────────────────────────────────────────────┐ │ 应用层 (Whisky.app / WhiskyCmd) │ ├─────────────────────────────────────────────────────┤ │ WhiskyKit │ │ ┌───────────┐ ┌────────────┐ ┌────────────────┐ │ │ │ Bottle │ │ Wine │ │ WhiskyWine │ │ │ │ 管理 │ │ 执行 │ │ Installer │ │ │ └───────────┘ └────────────┘ └────────────────┘ │ │ ┌───────────┐ ┌────────────┐ │ │ │ Program │ │ PE File │ │ │ │ 发现 │ │ 解析 │ │ │ └───────────┘ └────────────┘ │ ├─────────────────────────────────────────────────────┤ │ Wine 运行时 (wine64 二进制) │ └─────────────────────────────────────────────────────┘理解这套结构的关键在于:Bottle 提供"房间",Wine 负责"点火",Program 则是"房间里能运行的东西"。下面逐层拆解。
第一层:Bottle 管理——为每个游戏建一座"隔离沙盒"
一个Bottle(瓶)就是一个 Wine Prefix——一个自包含的目录,内部有仿 Windows 的文件系统、注册表和配置。你在 UI 中点击"Create"创建的 Bottle 默认存放在~/Library/Containers/Whisky/Bottles,其磁盘结构如下:
MyBottle/ ├── Metadata.plist # 序列化的 BottleSettings ├── drive_c/ # 虚拟 Windows C 盘 │ ├── windows/ │ ├── Program Files/ │ └── users/ └── Program Settings/ # 每个程序的独立配置 └── game.exe.plist核心实现集中在 Bottle.swift:
settings(L86-L88):Bottle 级配置,包括 Windows 版本、Retina 模式、DXVK/Metal 开关等。最巧妙的是didSet { saveSettings() }——任何设置被修改都会自动持久化到Metadata.plist,无需手动保存。- 配置模块化:BottleSettings.swift 把设置拆成
BottleMetalConfig、BottleDXVKConfig、BottlePerformanceConfig等独立结构体,职责清晰。 - 多 Bottle 互不干扰:同一个游戏可以拥有"Windows 10 + DXVK"和"Windows 7 + DXMT"两个 Bottle,配置完全隔离。
第二层:Wine 执行——把配置变成运行的进程
上面截图里的每一项设置(Windows Version、Retina Mode、DXVK Async…)最终都会汇入Wine 执行层。入口是 Wine.swift 中的runProgram(at:bottle:environment:),其执行链路为:
prepareProgramLaunch:检查 Bottle、按需启用 DXVK、构建启动参数- 构建环境变量:这是三层协作最关键的一步
- 启动
wine64 start /unix:以异步流AsyncStream<ProcessOutput>逐条输出进程事件 - 记录 RunLog:退出码、日志文件自动归档,供排查问题
环境变量的 9 层级联机制
WhiskyKit 没有简单"拼接"环境变量,而是设计了 EnvironmentBuilder.swift 的分层优先级:
base(WINEPREFIX 等基础项) → platform(macOS 兼容修复) → bottleManaged(DXVK/Metal/同步模式) → launcherManaged(Steam/Epic 启动器兼容) → gameProfile(GameDB 游戏档案) → bottleUser(用户自定义 Bottle 变量) → programUser(单程序设置与语言环境) → featureRuntime(临时诊断注入) → callsiteOverride(调用方显式覆盖)规则很简单:靠后的层覆盖靠前的层。例如programUser层设置DXVK_ASYNC=0就会覆盖bottleManaged层的值——这正是"单游戏专属设置 > 全局 Bottle 设置"这一 UX 承诺背后的机制。每层还记录reason(覆盖原因),可在诊断界面追溯。
Wine 进程的 GPU 工作负载甚至可以在 Xcode 中逐帧调试:
第三层:Program 发现——自动找出 Bottle 里的一切 .exe
你不需要手动录入游戏列表。WhiskyKit 的 Bottle.swift 提供了discoverInstalledExecutables(driveC:blocklist:),它会:
- 递归扫描
drive_c下的Program Files与Program Files (x86) - 过滤
.exe之外的文件、隐藏文件、ClickOnce 缓存噪声和崩溃报告器等干扰项 - 支持用户黑名单(blocklist),把不想要的条目永久排除
- 扫描任务通过
coalesceProgramScan合并去重——大 Bottle 重复触发扫描时只跑一次,UI 不会卡顿
每个被发现的.exe都会包装成一个 Program 对象:
| 成员 | 作用 |
|---|---|
settings | 程序级配置(语言、环境变量、启动参数),持久化为game.exe.plist,可覆盖 Bottle 默认值 |
peFile | 用内置 PE 解析器读取的元数据:架构(32/64 位)、图标、版本信息 |
pinned | 一键置顶,写入 Bottle 的pins列表,在界面顶部快速启动 |
generateEnvironment() | 生成该程序的专属环境变量,交给第二层执行 |
其中 PE 解析器是 WhiskyKit 的一个亮点:它在 macOS 上原生解析 Windows 可执行文件(PE/ 目录),不启动 Wine 就能提取图标和架构信息,所以程序列表加载飞快。
数据流图解:一次"点击运行"的完整旅程
把三层串起来,从你点击Run到游戏窗口出现,数据是这样流动的:
┌──────────────┐ │ 用户点击 Run │ └──────┬───────┘ ▼ ┌─────────────────────────┐ │ Program(第三层) │ │ 读取 program.exe.plist │ │ generateEnvironment() │ └──────┬──────────────────┘ ▼ ┌─────────────────────────┐ │ Wine.runProgram(第二层)│ │ prepareProgramLaunch: │ │ ① 启用 DXVK(如开启) │ │ ② EnvironmentBuilder │ │ 合并 9 层环境变量 │ │ ← 读取 Bottle.settings│ └──────┬──────────────────┘ ▼ ┌─────────────────────────┐ │ Bottle(第一层) │ │ WINEPREFIX 指向 Bottle │ │ 目录,隔离的 C 盘/注册表 │ └──────┬──────────────────┘ ▼ ┌─────────────────────────┐ │ wine64 进程启动游戏 │ │ 输出流 → RunLog + 日志文件│ │ 退出码 → 运行历史 │ └─────────────────────────┘反向的数据流同样重要:设置持久化是即时且自动的(settings.didSet→Metadata.plist);运行记录由RunLogStore写入 Bottle 内,配合稳定性诊断(Stability Diagnostics)实现一键生成崩溃报告。
源码目录导航:快速定位三层核心文件
| 层 | 关键文件 |
|---|---|
| Bottle 管理 | Bottle.swift · BottleSettings.swift |
| Wine 执行 | Wine.swift · EnvironmentBuilder.swift · WineEnvironment.swift |
| Program 发现 | Program.swift · ProgramSettings.swift · PE/ |
| 架构文档 | Architecture.md · GettingStarted.md |
总结:一张图记住 WhiskyKit 三层协作
🥃Bottle 管"环境",Wine 管"启动",Program 管"内容":
- Bottle 管理提供隔离的 Wine Prefix 与自动持久化的模块化配置;
- Wine 执行通过 9 层环境变量级联把配置翻译成进程启动,并全程记录日志;
- Program 发现自动扫描、解析、置顶程序,让单程序设置精确覆盖全局默认。
这套分层设计让 Whisky 既对新手"零门槛"(一键创建、自动发现),又对深度玩家"可折腾"(每层环境变量都可追溯、可覆盖)——这正是它作为 macOS 上最现代 Wine 封装器的架构底气。
【免费下载链接】Whisky
Active community fork of the archived whisky-app/whisky — a modern Wine wrapper for macOS built with SwiftUI
相关推荐
拆解 CC Pocket 架构:App、Bridge 与 Agent 三层如何协同工作的完整指南
拆解 CC Pocket 架构:App、Bridge 与 Agent 三层如何协同工作的完整指南 CC Pocket 是一款免费的移动端编程代理客户端:通过 W
人工智能AI Agent移动开发代码智能体后端OpenGUI三层架构深度解析:主图、执行子图与待命派发如何协同完成手机AI任务
OpenGUI三层架构深度解析:主图、执行子图与待命派发如何协同完成手机AI任务 📱 OpenGUI 是一个运行在真实安卓手机上的 GUI 智能体(Phone
WhisperLiveKit 安装:5 步搞定 iOS 实时语音识别的完整教程
WhisperLiveKit 安装:5 步搞定 iOS 实时语音识别的完整教程 想给你的应用加上实时语音识别能力吗?WhisperLiveKit 是一个面向 i
人工智能语音模型推理服务本地部署
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考