Files
Windows-Gotify-Client-Rust/Cargo.toml
T
KennethCheng ac5d0cb1d0 feat(windows): Phase 6 C1 — 单实例 mutex + HKCU Run 启动项
- src/windows/mod.rs: cfg(windows) 模块入口,pub use single_
  instance + startup;其他 Phase 6 模块(C2 托盘 / C3 Toast / URL
  打开)在后续 commit 加
- src/windows/single_instance.rs: CreateMutexExW("Local\\...")
  → mutex 名称 user-scope(多 RDP 会话各自能跑一个实例);第
  二参 bInitialOwner=true 让 GetLastError() 可靠;返回 Acquired
  / AlreadyRunning enum
- src/windows/startup.rs: HKCU\Software\Microsoft\Windows\
  CurrentVersion\Run\WindowsGotifyClientRust = 当前 exe 路径;set_
  enabled / is_enabled 接口给 C2 Settings toggle 留口子;自定义
  Win32Error 类型(windows-sys 0.59 没有 core::Error)
- src/lib.rs: 加 #[cfg(windows)] pub mod windows 入口
- src/main.rs: 启动前 enforce_single_instance() 检查;已有实
  例直接 std::process::exit(0)(不抢前台窗口,留给 C2 tray
  拿 hwnd 后再做)
- Cargo.toml: windows-sys 0.59 features 加 Win32 / Win32_Security
  / Win32_Foundation / Win32_System_Threading / Win32_System_
  Registry / Win32_UI_WindowsAndMessaging / Win32_UI_Shell

避坑:
- windows-sys 0.59 没有 CreateMutexW(只是宏名 / 16-bit 兼容)
  → 用 CreateMutexExW
- HANDLE 不是 newtype struct,是裸 *mut c_void → 直接 as
  isize,不要 .0
- CreateMutex[A/ExA/ExW/W] 全部 cfg-gated 在 Win32_Security feature
  → 必须开
- windows-sys 子 feature(Win32_System_Threading 等)依赖顶层
  Win32 feature → 必须同时开
- std::mem::zeroed() 必须放 unsafe block 里

验证:cargo build / build --release 都 exit 0,0 warning
- cargo test: 15 passed; 0 failed
- debug   35.56 MB, subsystem = WINDOWS_CUI
- release  9.77 MB, subsystem = WINDOWS_GUI
- 实际功能(重复启动会 exit 0)只能手测;test 只能覆盖 JSON /
  Rust 内部状态
2026-09-19 07:03:29 +08:00

83 lines
2.7 KiB
TOML

# Cargo.toml — Phase 1 (Bootstrap).
#
# Dependency rationale lives in AGENTS.md §44. Only the crates actually used
# by Phase 1 are listed; the remaining crates (reqwest / tungstenite / serde /
# url / anyhow / ...) are added in later phases when their modules land.
[package]
name = "windows-gotify-client-rust"
version = "0.1.0"
edition = "2021"
rust-version = "1.75"
description = "Lightweight, modern, Windows-native Gotify desktop client (Rust + Slint)"
license = "MIT"
readme = "README.md"
authors = ["KennethCheng <a1478925630@163.com>"]
[[bin]]
name = "windows-gotify-client-rust"
path = "src/main.rs"
[dependencies]
# --- UI ---
# `slint` crate. The `slint!{}` macro is compiled in via the default feature
# set in 1.x (verified against 1.18.0 — `internal-interpreter` was removed in
# 1.x). The Windows GUI backend (`backend-winit`) is also part of defaults.
# Phase 2 will likely switch from the embedded macro to `include_slint!()`
# + standalone .slint files under `ui/`.
slint = "1"
# --- Logging ---
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
# --- Error handling ---
thiserror = "2"
# --- Serialization (Phase 2 C3 storage) ---
serde = { version = "1", features = ["derive"] }
serde_json = "1"
# --- Networking (Phase 3 Gotify HTTP) ---
reqwest = { version = "0.12", default-features = false, features = ["blocking", "json", "rustls-tls"] }
# --- Date/time (Phase 3 C2 convert Gotify RFC3339) ---
chrono = { version = "0.4", default-features = false, features = ["clock", "serde"] }
# --- Windows-only (Phase 6 integration) ---
# `windows-sys` is the low-level ABI layer of `windows-rs`. We only pull
# the focused feature subsets we actually use (mutex, registry, message
# loop, windowing); AGENTS.md §1 forbids pulling the umbrella `windows`
# crate wholesale. `Win32` is the umbrella feature that gates the
# `Win32_*` sub-features.
windows-sys = { version = "0.59", features = [
"Win32",
"Win32_Foundation",
"Win32_Security",
"Win32_System_Threading",
"Win32_System_Registry",
"Win32_UI_WindowsAndMessaging",
"Win32_UI_Shell",
] }
# --- WebSocket (Phase 4 real-time stream) ---
tungstenite = { version = "0.21", default-features = false, features = ["rustls-tls-webpki-roots", "handshake"] }
url = "2"
http = "1"
# Slint's `.slint` files are compiled by `build.rs`; see build.rs.
[build-dependencies]
slint-build = "1"
[profile.release]
# See AGENTS.md §42. The `release-balanced` profile below is the practical
# default after benchmarking — adjust if startup time regresses.
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
strip = true
[profile.release-balanced]
inherits = "release"
opt-level = 3