Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ cargo clippy --all-targets --all-features -- -D warnings

CI runs on **macos-latest only** (`.github/workflows/ci.yml`) and requires `cargo fmt`, `cargo clippy -D warnings`, full `cargo test`, frontend `pnpm test`, `pnpm build`, and `pnpm tauri build` smoke. Push to `main` or `develop`, or open a PR against them.

### DNS mode dev workflow (issue #155)

`pnpm tauri dev` does **not** auto-build the `mhost-dns-proxy` sidecar binary — it's a `[[bin]]` declared in `crates/mhost-dns/Cargo.toml`, separate from the workspace root `mhost` bin. Without it, system DNS gets rewritten to `127.0.0.1:53` but nothing listens → all queries hang. Use one of:

```bash
pnpm dev:full # recommended: wraps `cargo build -p mhost-dns --bin mhost-dns-proxy` + tauri dev
bash scripts/dev.sh # same as dev:full
(cd src-tauri && cargo build -p mhost-dns --bin mhost-dns-proxy) && pnpm tauri dev # manual; -p 必须显式给
```

`enable_dns_mode` pre-checks the binary and returns a clear `Err` instead of silently enabling an unusable mode, so a missing binary is now visible to the UI rather than a black hole. See `src-tauri/crates/mhost-dns/src/platform.rs::enable_dns_mode` for the `[ ! -x ]` / `kill -0` script-level defenses.

## Repository layout

```txt
Expand Down
46 changes: 46 additions & 0 deletions doc/dev-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,58 @@ pnpm install

### 开发模式(推荐日常使用)

> **⚠️ DNS mode 用户必读(issue #155)**:`pnpm tauri dev` **不会**自动
> 构建 `mhost-dns-proxy` 这个独立 sidecar binary(它在 workspace member
> `crates/mhost-dns/` 里,是一个 `[[bin]]`)。第一次启用 DNS mode 时,
> 如果 `src-tauri/target/debug/mhost-dns-proxy` 不存在,DNS 查询会
> 全部卡死(系统 DNS 被改成 127.0.0.1:53 但 53 端口没人监听)。

**推荐工作流**(一键构建 proxy + 启动 dev):

```bash
pnpm dev:full
```

或直接调脚本:

```bash
bash scripts/dev.sh
```

等价于:

```bash
cd src-tauri && cargo build -p mhost-dns --bin mhost-dns-proxy
pnpm tauri dev
```

> 必须用 `-p mhost-dns --bin ...` 显式指定包:从 workspace root 跑
> `cargo build --bin mhost-dns-proxy` 会 fail 报
> "no bin target named 'mhost-dns-proxy' in default-run packages"
> (mhost-dns 是 workspace member 而不是 default-run package)。

临时用普通 dev 模式时,单独构建一次 proxy 也行:

```bash
(cd src-tauri && cargo build -p mhost-dns --bin mhost-dns-proxy) && pnpm tauri dev
```

构建完成后 `src-tauri/target/debug/mhost-dns-proxy` 就在 `current_exe()`
同目录下,被 `enable_dns_mode` 通过 `current_exe().parent().join(...)`
定位到。

```bash
pnpm tauri dev
```

同时启动 Vite 热更新(http://localhost:1420)和 Rust 后端,弹出桌面窗口。前端改代码自动刷新,Rust 改代码自动重编译。

> 注:`pnpm tauri dev` 之后修改 Rust 代码不需要重新构建 proxy —— proxy
> 是常驻 root 进程,编码由 release/commit 时决定的 `#[bin]` 形态决定;
> 普通 Rust 修改走的是 `cargo run` 路径(主 binary `mhost`),proxy
> binary 不参与热重载。需要重新构建 proxy 的场景只有修改了
> `crates/mhost-dns/` 源码本身。

### 运行测试

```bash
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite",
"dev:full": "bash scripts/dev.sh",
"build": "tsc && vite build",
"preview": "vite preview",
"tauri": "tauri",
Expand Down
87 changes: 87 additions & 0 deletions scripts/dev.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/env bash
# ---------------------------------------------------------------------------
# scripts/dev.sh — 一键启动 dev 模式
#
# issue #155 的工作流:`pnpm tauri dev` 默认不会构建 `mhost-dns-proxy`
# 这个独立 sidecar binary;本文先 build proxy 再启 dev,避免磁盘清理
# / 新克隆后 dev 模式拿不到 53 端口的 listener。
#
# 用法:
# bash scripts/dev.sh # debug 构建 + 启动 dev(默认)
# bash scripts/dev.sh --release # release 构建 + 启动 dev
# bash scripts/dev.sh -h|--help # 打印用法
#
# Bash 兼容性(F6, PR #156 review):
# * 不在 `set -u` 下展开空数组 —— macOS 自带的 /bin/bash 3.2.57 会
# 把 "${arr[@]}" 在空数组时当成 unbound variable
# * 用 `case` + `if` 显式分流,避免 silent ignore(F7)
# ---------------------------------------------------------------------------
set -euo pipefail

PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$PROJECT_ROOT"

# 1. 参数解析(F6/F7)
case "${1:-}" in
"")
CARGO_FLAGS=()
TARGET_DIR="debug"
PROFILE_LABEL="debug"
;;
"--release")
CARGO_FLAGS=(--release)
TARGET_DIR="release"
PROFILE_LABEL="--release"
;;
"-h"|"--help")
cat <<USAGE
Usage: $0 [OPTIONS]

Build the mhost-dns-proxy sidecar binary and start 'pnpm tauri dev'.
Without arguments, builds the debug profile (target/debug/mhost-dns-proxy).

OPTIONS:
--release build the release profile and invoke 'pnpm tauri dev --release'
-h, --help print this help and exit

USAGE
exit 0
;;
*)
echo "$0: unknown argument: $1" >&2
echo "Try '$0 --help' for usage." >&2
exit 2
;;
esac

SRC_TAURI_TARGET="src-tauri/target/${TARGET_DIR}"

echo "==> Building mhost-dns-proxy (${PROFILE_LABEL} profile)..."
(
cd src-tauri
# 必须用 `-p mhost-dns --bin ...` 显式指定包:workspace root 的
# `cargo build --bin mhost-dns-proxy` 会 fail 报 "no bin target named
# 'mhost-dns-proxy' in default-run packages",因为 mhost-dns 是
# workspace member、不是 default-run package。
if [ "${#CARGO_FLAGS[@]}" -gt 0 ]; then
cargo build --package mhost-dns --bin mhost-dns-proxy "${CARGO_FLAGS[@]}"
else
cargo build --package mhost-dns --bin mhost-dns-proxy
fi
)

PROXY_BIN="${SRC_TAURI_TARGET}/mhost-dns-proxy"
if [[ ! -x "$PROXY_BIN" ]]; then
echo "❌ Build reported success but ${PROXY_BIN} not found or not executable." >&2
exit 1
fi

# 2. 启动 dev
echo "==> mhost-dns-proxy ready at ${PROXY_BIN}"
echo "==> Starting pnpm tauri dev (${PROFILE_LABEL})..."
# F6 fix:不在 set -u 下展开空数组
if [ "${#CARGO_FLAGS[@]}" -gt 0 ]; then
exec pnpm tauri dev "${CARGO_FLAGS[@]}"
else
exec pnpm tauri dev
fi
Loading
Loading