我正在构建一个 macOS 的菜单栏应用程序。在我的 Mac 上运行完美。现在我需要知道它是否能在干净的 macOS 环境中正常工作:没有我的配置、没有我的权限、没有我的数据。一个全新安装的用户环境。

如何测试这种情况?你需要一个虚拟机。

“简单”,我想。“我安装了 UTM。打开向导,创建一个 macOS 虚拟机,然后运行。”

事情并没有那么简单。

UTM:漂亮但难以驯服

UTM 是一个很棒的应用程序。精心设计的界面,支持在 Apple Silicon 上运行 macOS 客户机,全屏显示,共享剪贴板。手动使用确实很棒。

当你试图自动化时问题就出现了。

UTM 有一个叫做 utmctl 的命令行界面。可以列出虚拟机、启动它们、停止它们、克隆它们。它不能做的是创建虚拟机。对于 macOS 客户机,甚至 UTM 的 AppleScript 也不允许创建它们——操作系统字段被硬编码为 Linux。

简单来说:如果你想在 UTM 中创建 macOS 虚拟机,你必须通过向导手动创建。每次都是。需要点击、下载 IPSW(Apple Silicon 的 macOS 安装映像——相当于传统的 ISO,但由 Apple 打包)、等待安装。

对于需要在质量保证流程中频繁创建和销毁虚拟机的开发者来说,这真是个麻烦事。

Tart:为开发者设计的 macOS 虚拟机

Tart 是当有人在设计虚拟化工具时考虑开发者而不是最终用户的结果。

它使用与 UTM 完全相同的 Apple Virtualization.framework。相同的技术,相同的功能,相同的原生速度。区别在于界面:Tart 是命令行优先的。

1
brew install cirruslabs/cli/tart

就这样。没有图形界面配置,没有向导。只是在你的 PATH 中的一个二进制文件。

一个命令统治一切

创建一个使用最新可用版本的 macOS 虚拟机:

1
tart create mi-vm --from-ipsw latest

就是这样。latest 告诉 Tart “给我这台 Mac 支持的最新 macOS 版本”。Tart 查询 Apple 的 API,下载 IPSW(约 15 GB——是的,macOS 很大),创建虚拟磁盘,安装操作系统,并为你准备好可以启动的虚拟机。去喝杯咖啡吧,因为需要一段时间——但你不需要动手做任何事情。

启动虚拟机:

1
tart run mi-vm

打开一个带有 macOS 桌面的窗口。鼠标、键盘、显示器。与 UTM 完全相同,但是通过 tart run 启动。

共享文件夹:决定性的细节

这就是 Tart 征服我的地方。我需要将我的应用程序从主机 Mac 复制到虚拟机。在 UTM 中,你必须手动配置 VirtioFS,从客户机终端挂载它,并祈祷 config.plist 不会损坏(有已知的错误)。

在 Tart 中:

1
tart run mi-vm --dir=shared:~/code/tokamak/build

在虚拟机内部,文件夹出现在 /Volumes/My Shared Files/shared。将应用程序拖到 /Applications 就完成了。无需配置任何东西,无需挂载任何东西。

我的实际质量保证流程

这是我在干净的 macOS 环境中测试应用程序的做法:

1
2
3
4
5
6
7
8
# 创建虚拟机(仅第一次)
tart create tokamak-qa --from-ipsw latest --disk-size 50

# 编译应用程序
cd ~/code/tokamak && make build

# 启动虚拟机并共享构建
tart run tokamak-qa --dir=build:~/code/tokamak/build/Build/Products/Debug

在虚拟机内部:

  1. 打开 /Volumes/My Shared Files/build/
  2. Tokamak.app 拖到 /Applications/
  3. 执行并验证:登录、权限、沙盒、菜单栏、通知

如果我需要从头开始(测试首次启动体验):

1
2
tart delete tokamak-qa
tart create tokamak-qa --from-ipsw latest --disk-size 50

销毁并重新创建。没有询问,没有确认,没有向导。

配置资源

默认情况下,Tart 分配合理的资源,但你可以调整它们:

1
2
3
4
5
# 4 核心,8 GB 内存
tart set mi-vm --cpu 4 --memory 8192

# 调整磁盘大小
tart set mi-vm --disk-size 80

Tart 没有的功能(以及为什么不重要)

它没有带每个虚拟机缩略图的图形界面管理器。没有 ISO 的拖放功能。没有漂亮的"新建虚拟机"按钮。

如果你需要的是一个桌面应用程序来管理虚拟机,使用 UTM。它在这方面很出色。

但如果你需要的是在干净的 macOS 环境中测试应用程序,销毁虚拟机,重新创建它,共享文件夹,并从脚本或 Makefile 中完成所有这些工作…UTM 做不到。Tart 可以。

完整配方

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 安装
brew install cirruslabs/cli/tart

# 创建 macOS 虚拟机(下载约 15 GB,需要约 20 分钟)
tart create test-vm --from-ipsw latest --disk-size 50

# 启动并共享文件夹
tart run test-vm --dir=app:~/mi-proyecto/build

# 其他有用的命令
tart list                    # 现有虚拟机
tart stop test-vm            # 停止
tart clone test-vm copia-vm  # 克隆(快速)
tart delete test-vm          # 删除
tart ip test-vm              # SSH 的 IP

文档就是一个 README。学习曲线就是一杯咖啡的时间。如果你为 macOS 开发而没有使用 Tart,你正在让事情变得比必要的更困难。