-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMakefile
More file actions
273 lines (239 loc) · 13.5 KB
/
Copy pathMakefile
File metadata and controls
273 lines (239 loc) · 13.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# HVM Makefile
# 唯一构建入口 (Xcode 打开 app/Package.swift 作为开发期辅助, 不做权威构建)
CONFIGURATION ?= release
BUILD_DIR := build
PKG_DIR := app
SWIFTPM_DIR := $(PKG_DIR)/.build
# 签名身份: 空/auto = bundle.sh 自动探测 (Apple Development 优先, 否则 ad-hoc)
SIGN_IDENTITY ?= auto
ENTITLEMENTS := $(PKG_DIR)/Resources/HVM.entitlements
-include makefile.local
ifeq ($(SIGN_IDENTITY),auto)
ifneq ($(strip $(MACOS_CODESIGN_IDENTITY)),)
SIGN_IDENTITY := $(MACOS_CODESIGN_IDENTITY)
endif
endif
# GUI: 老 GUI (app/Sources/HVM/UI/**) 已随 QEMU-only 转向退役删除.
# 唯一 GUI 走 app/Sources/HVM/GUI/** (NewGUIAppLauncher).
# 老的 `#if NEW_GUI` 条件编译 guards 已全部去除 (GUI/** 无条件编译), 不再需要 -DNEW_GUI.
SWIFT_DEFINES :=
# QEMU 后端产物 (由 scripts/qemu-build.sh 生成, 仓库 ignore)
# stage 即裁剪 + 签名 + LICENSE/MANIFEST 后的最终成品, bundle.sh 直接拷进 .app
# 不再有 third_party/qemu/ 中间 vendor 层
QEMU_STAGE := third_party/qemu-stage
QEMU_BIN := $(QEMU_STAGE)/bin/qemu-system-aarch64
EDK2_BIN := third_party/edk2-stage/edk2-aarch64-code.fd
# Windows guest helper EXE (由 make guest-helper / build.sh 生成, 仓库 ignore)
HELPER_BIN := patches/guest/helper-win/dist/aarch64/hvm-guest-helper.exe
# SwiftPM 产物路径 (CONFIGURATION 决定 release / debug 子目录).
# 让 bundle stamp 依赖三个 binary mtime —— SwiftPM no-op 时 mtime 不变, 整个 bundle 跳过.
SWIFT_PLATFORM ?= arm64-apple-macosx
SWIFT_BUILD_DIR := $(SWIFTPM_DIR)/$(SWIFT_PLATFORM)/$(CONFIGURATION)
HVM_BIN := $(SWIFT_BUILD_DIR)/HVM
HVM_CLI_BIN := $(SWIFT_BUILD_DIR)/hvm-cli
HVM_DBG_BIN := $(SWIFT_BUILD_DIR)/hvm-dbg
BUNDLE_STAMP := $(BUILD_DIR)/.bundle-stamp
.PHONY: all build bundle compile dev verify clean help icon register-types qemu qemu-clean edk2 edk2-clean guest-helper guest-helper-clean build-all xed xcode-gen open-xcode install uninstall run-app open dev-open
# 默认: release 模式 + 完整 .app 签名
all: build
build: $(BUNDLE_STAMP)
help:
@echo "HVM 构建命令:"
@echo " make build — release 模式, 组装 .app + 签名 (默认; QEMU 缺则跳过嵌入)"
@echo " make dev — debug 模式, 组装 .app + 签名"
@echo " make verify — smoke test, 验证 .app 可启动"
@echo " make icon — 从 app/Resources/AppIcon-src.png 生成 AppIcon.icns"
@echo " make xed — Xcode 打开 SwiftPM 包 (开发期辅助, 非权威构建路径)"
@echo " make xcode-gen — 生成 app/HVM.xcodeproj (XcodeGen; team ID 走 makefile.local APPLE_DEV_TEAM; DerivedData → app/.build/xcode)"
@echo " make open-xcode — 生成并用 Xcode 打开工程"
@echo " make install — 把 build/HVM.app 安装到 /Applications/ (覆盖旧版)"
@echo " make uninstall — 从 /Applications/ 卸载 HVM.app"
@echo " make run-app — build + 重启 build/HVM.app GUI 主进程 (release; 不动 host 子进程; 不写 /Applications/)"
@echo " make open — run-app 的短别名 (release; 改一行 ~14s)"
@echo " make dev-open — debug 模式 dev loop, 改一行 ~3-5s; 推荐日常迭代用"
@echo " 注: open / dev-open 不再同步 /Applications/HVM.app, 想测 hvm-cli start 先 make install"
@echo " make clean — 清除 build/ 和 app/.build/"
@echo
@echo "QEMU 后端 (Win arm64 / 可选 Linux arm64):"
@echo " make edk2 — 拉 EDK2 + apply Win11 patch + 编译 (~5 分钟; 仅打包者跑; Win11 ARM64 装机必需)"
@echo " make edk2-clean — 清除 third_party/edk2-src/, third_party/edk2-stage/"
@echo " make qemu — 装 brew 依赖 + 拉源码 + 编译 QEMU (10-30 分钟; 仅打包者跑)"
@echo " make qemu-clean — 清除 third_party/qemu-src/, third_party/qemu-stage/"
@echo " make guest-helper — 编 Windows guest helper 成无 DLL 单 exe (缺 llvm-mingw 自动下载; 仅打包者跑)"
@echo " make build-all — make edk2 + qemu + guest-helper + build (发布完整流程)"
# 1. SwiftPM 编译全部 executable
# $(SWIFT_DEFINES) 现为空 (GUI guards 已去, 不再需要条件编译 flag); 保留变量占位以防未来需要
compile:
swift build --package-path $(PKG_DIR) -c $(CONFIGURATION) $(SWIFT_DEFINES) --product HVM
swift build --package-path $(PKG_DIR) -c $(CONFIGURATION) $(SWIFT_DEFINES) --product hvm-cli
swift build --package-path $(PKG_DIR) -c $(CONFIGURATION) $(SWIFT_DEFINES) --product hvm-dbg
# 2. 生成图标 (源图不存在则跳过, 不阻断构建)
icon:
@bash scripts/gen-icon.sh
# 3. 组装 .app + 签名 (增量: 只在 SwiftPM 产物 / bundle.sh / entitlements / 入包脚本 任一
# 更新时重跑. 日常改 docs → swift build no-op → binary mtime 不变 → 跳过 bundle.sh, 30s → ~5s.
# install-vmnet-daemons.sh 也跟踪, 因 bundle.sh 把它拷进 Resources/scripts/, GUI VMnetSupervisor
# 严格只查 Bundle.main 路径, 改这脚本不重 bundle 会让线上 .app 跑老脚本.)
$(BUNDLE_STAMP): $(HVM_BIN) $(HVM_CLI_BIN) $(HVM_DBG_BIN) \
$(wildcard $(QEMU_BIN)) \
scripts/bundle.sh \
scripts/install-vmnet-daemons.sh \
$(PKG_DIR)/Resources/HVM.entitlements \
$(PKG_DIR)/Resources/QEMU.entitlements \
$(PKG_DIR)/Resources/Info.plist.template \
$(wildcard patches/guest/helper-win/dist/aarch64/hvm-guest-helper.exe) \
$(wildcard patches/guest/helper-win/dist/aarch64/libunwind.dll) \
$(wildcard makefile.local) \
| icon
@CONFIGURATION=$(CONFIGURATION) SIGN_IDENTITY="$(SIGN_IDENTITY)" bash scripts/bundle.sh
@mkdir -p $(@D)
@touch $@
# 三个 binary 是 SwiftPM 产物 — compile 是 PHONY 总跑 swift build, 但 no-op 时不更新 binary mtime,
# 因此不会触发 BUNDLE_STAMP 规则. 改源码后 SwiftPM 会重链接, mtime 更新, 才重 bundle.
$(HVM_BIN) $(HVM_CLI_BIN) $(HVM_DBG_BIN): compile
@:
# 老调用方 (run-app / register-types / install) 调 bundle 兼容
bundle: $(BUNDLE_STAMP)
# debug 变体
dev:
@$(MAKE) build CONFIGURATION=debug
verify:
@bash scripts/verify-build.sh
clean:
rm -rf $(BUILD_DIR) $(SWIFTPM_DIR)
@echo "✔ 已清除 build/ 与 $(SWIFTPM_DIR)/"
# EDK2 build (仅打包者跑; 详见 scripts/edk2-build.sh)
# 第一次跑会拉 edk2-stable202508 + submodules, apply Win11 patch, cross compile ~3-5 分钟
edk2:
@bash scripts/edk2-build.sh
# 仅清 EDK2 相关产物, 不动 QEMU / SwiftPM
edk2-clean:
rm -rf third_party/edk2-src third_party/edk2-stage
@echo "✔ 已清除 third_party/edk2-src/, third_party/edk2-stage/"
# QEMU 后端构建 (仅打包者跑; 详见 scripts/qemu-build.sh)
# 第一次跑会自动装 Homebrew + 一组锁定 brew 依赖, 拉 v10.2.0 源码, 编译 ~10-30 分钟
# 优先用 third_party/edk2-stage/ 里的 patched firmware (给 Win11 ARM64); 没有则降级 QEMU 自带
qemu:
@bash scripts/qemu-build.sh
# 仅清 QEMU 相关产物, 不动 SwiftPM 与 .app
qemu-clean:
rm -rf third_party/qemu-src third_party/qemu-stage
@echo "✔ 已清除 third_party/qemu-src/, third_party/qemu-stage/"
# Windows guest helper EXE 构建 (仅打包者跑; 详见 patches/guest/helper-win/build.sh)
# 出【无 DLL 单 exe】到 dist/aarch64/; 缺 llvm-mingw 自动下载锁定版本到 third_party/llvm-mingw/.
# 产物随 bundle.sh 入 .app/Contents/Resources/GuestHelper/. 改 helper Rust 源后跑此 + make install.
guest-helper:
@bash patches/guest/helper-win/build.sh
# 仅清 helper 构建产物 (不删 llvm-mingw 工具链, 重编快)
guest-helper-clean:
rm -rf patches/guest/helper-win/target
@echo "✔ 已清除 patches/guest/helper-win/target/"
# 完整发布: 确保 EDK2 + QEMU + guest helper 已就绪 (缺则触发 make edk2 / qemu / guest-helper) + 组装 .app
build-all:
@if [ ! -f "$(EDK2_BIN)" ]; then \
echo "ℹ EDK2 产物不存在 ($(EDK2_BIN)), 先跑 make edk2"; \
$(MAKE) edk2; \
fi
@if [ ! -x "$(QEMU_BIN)" ]; then \
echo "ℹ QEMU 产物不存在 ($(QEMU_BIN)), 先跑 make qemu"; \
$(MAKE) qemu; \
fi
@if [ ! -f "$(HELPER_BIN)" ]; then \
echo "ℹ guest helper 产物不存在 ($(HELPER_BIN)), 先跑 make guest-helper"; \
$(MAKE) guest-helper; \
fi
@$(MAKE) build
# Xcode 打开 SwiftPM 包 (开发期编辑/补全用, 产物无 entitlement 不签名; 真实运行仍走 make build)
xed:
xed $(PKG_DIR)/Package.swift
# 生成 Xcode 工程 app/HVM.xcodeproj (XcodeGen, 开发期辅助; 非权威构建, 仍走 make build).
# team ID 从 makefile.local 的 APPLE_DEV_TEAM 注入 DEVELOPMENT_TEAM; 不硬编码进提交文件.
xcode-gen:
@command -v xcodegen >/dev/null 2>&1 || { echo "✗ 需要 xcodegen (brew install xcodegen)"; exit 1; }
@if [ -z "$(strip $(APPLE_DEV_TEAM))" ]; then \
echo "✗ 未设置 APPLE_DEV_TEAM. 请在 makefile.local (git-ignore) 写入:"; \
echo " APPLE_DEV_TEAM := <你的 Apple 开发者 Team ID>"; \
exit 1; \
fi
@cd $(PKG_DIR) && DEVELOPMENT_TEAM="$(APPLE_DEV_TEAM)" xcodegen generate
@# GUI 的 DerivedData 重定向到 app/.build/xcode — 写 per-user IDEWorkspaceUserSettings.
@# (仅 Xcode.app GUI 读; xcodebuild 不读此设置, 只认 -derivedDataPath)
@USERD="$(PKG_DIR)/HVM.xcodeproj/project.xcworkspace/xcuserdata/$$(id -un).xcuserdatad"; \
mkdir -p "$$USERD"; \
sed 's|__DERIVED_DATA_ABS__|$(abspath $(PKG_DIR))/.build/xcode|' \
$(PKG_DIR)/xcode-support/WorkspaceSettings.xcsettings > "$$USERD/WorkspaceSettings.xcsettings"
@echo "✔ 已生成 $(PKG_DIR)/HVM.xcodeproj (DEVELOPMENT_TEAM 已注入)"
@echo " GUI DerivedData → $(PKG_DIR)/.build/xcode (Xcode.app 生效; 首次请确认)"
@echo " 打开: make open-xcode"
# 生成 (确保 team / DerivedData 注入) 并用 Xcode 打开工程.
open-xcode: xcode-gen
open $(PKG_DIR)/HVM.xcodeproj
# 安装到 /Applications/ (覆盖旧版). admin 用户对 /Applications 有写权限, 不需 sudo;
# /Applications/HVM.app 若存在则先删 (.app 是 directory, 不能直接 cp 覆盖).
# 安装后 lsregister 刷新 LaunchServices, 让 .hvmz 关联 + Spotlight 索引立即生效.
install:
@$(MAKE) build
@if [ ! -d "$(BUILD_DIR)/HVM.app" ]; then \
echo "✗ $(BUILD_DIR)/HVM.app 不存在; 先 make build"; exit 1; \
fi
@if [ -e /Applications/HVM.app ]; then \
echo "ℹ 覆盖旧版 /Applications/HVM.app"; \
rm -rf /Applications/HVM.app; \
fi
cp -R $(BUILD_DIR)/HVM.app /Applications/HVM.app
@LSREG="/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister"; \
"$$LSREG" -f /Applications/HVM.app 2>/dev/null || true
@echo "✔ 已安装: /Applications/HVM.app"
# 开发期 dev loop: 编译 + 重启 GUI 主进程 (保留运行中的 VM host 子进程).
# 启动的是 $(BUILD_DIR)/HVM.app — bundle.sh 输出的带签名 + entitlement 的 .app, **不**走
# /Applications/HVM.app, 避免 dev 期污染线上副本; 想测 hvm-cli start (它只查 /Applications/
# 与 ~/Applications/ 见 HostLauncher.locateHVMBinary) 单独跑 `make install`.
# 主 GUI 进程 cmdline 第二个 token 以 .../HVM.app/Contents/MacOS/HVM 结尾 (build/ 与
# /Applications/ 两条路径都满足); host 子进程 cmdline 带 --host-mode-bundle 后缀 (regex
# 不匹配, 不被误杀). regex 同时杀 build/ 与 /Applications/ 的 GUI 主进程, 避免两份并存.
run-app:
@$(MAKE) build
@OLDPID=$$(ps -axo pid,command | awk '$$2 ~ /\/HVM\.app\/Contents\/MacOS\/HVM$$/ {print $$1}' | head -1); \
if [ -n "$$OLDPID" ]; then \
echo "ℹ 重启 GUI 主进程 pid=$$OLDPID (host 子进程不动)"; \
kill $$OLDPID 2>/dev/null || true; \
sleep 1; \
fi
@open $(BUILD_DIR)/HVM.app
@echo "✔ 已启动 $(BUILD_DIR)/HVM.app"
# run-app 的短别名 (习惯性 `make open` 即编译 + 关旧 + 启新; 透传 GUI=old/new)
open: run-app
# debug 模式 dev loop: 跳过 release 全模块优化 (~14s → ~3-5s).
# debug / release 各自走 .build/debug / .build/release 子目录, BUNDLE_STAMP 在 build/
# 顶层只一份, 切 CONFIGURATION 会 invalidate stamp 重 bundle — 跟 swift build 同步.
# QEMU-only: 主进程不带 virtualization entitlement, HVF 由 QEMU 子进程 (QEMU.entitlements hypervisor) 承载.
# 想要 release 性能测试或发布走 `make open` / `make build`.
dev-open:
@$(MAKE) open CONFIGURATION=debug
# 从 /Applications/ 卸载 (用户数据 ~/Library/Application Support/HVM/ 不动)
uninstall:
@if [ -e /Applications/HVM.app ]; then \
rm -rf /Applications/HVM.app; \
echo "✔ 已卸载 /Applications/HVM.app (用户数据 ~/Library/Application Support/HVM/ 保留)"; \
else \
echo "ℹ /Applications/HVM.app 不存在, 无需卸载"; \
fi
# 让 Finder 立刻识别 .hvmz 为 package. 仅当 Finder 图标未更新时手动跑一次
register-types: build
@LSREG="/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister"; \
"$$LSREG" -f $(BUILD_DIR)/HVM.app; \
killall Finder 2>/dev/null || true; \
echo "✔ Launch Services 已刷新, Finder 已重启"
# 重置指定 VM 的运行时残留 + EFI nvram, 用于启动卡住时一键清理
# 用法: make reset-vm NAME=ubuntu24-m1
.PHONY: reset-vm
reset-vm:
@test -n "$(NAME)" || { echo "用法: make reset-vm NAME=<vm-name>"; exit 1; }
@BUNDLE="$$HOME/Library/Application Support/HVM/VMs/$(NAME).hvmz"; \
test -d "$$BUNDLE" || { echo "✗ 未找到 $$BUNDLE"; exit 1; }; \
pkill -9 -f "HVM.app/Contents/MacOS/HVM" 2>/dev/null || true; \
sleep 1; \
rm -f "$$BUNDLE/.lock"; \
rm -f "$$BUNDLE/nvram/efi-vars.fd"; \
rm -f "$$HOME/Library/Application Support/HVM/run/"*.sock 2>/dev/null || true; \
echo "✔ 已重置 $(NAME) 的运行时残留 + EFI nvram"