Files
DarkRoom/apps/darkroom-desktop/src/main.rs
T
dtourolle fa4dca327f Give the desktop executable a version flag and a Windows identity
Three things the Windows build showed the entry point was missing, and
that a Linux build never asks for.

`--version`, answered before the logger and the crash hook install: a
binary built on a machine that cannot run the application — the Linux
CI producing the Windows executable, checked under Wine — needs an
exit that proves it starts without opening a window or touching the
user's directories. It is the smoke test in docs/windows.md §6.

A GUI-subsystem executable in release, or Windows keeps a console
window open behind the application for the life of the process. Debug
builds keep the console, which is where their log goes.

A resource block, or Explorer, the Start Menu and the taskbar show the
generic executable icon and the Details tab is empty. build.rs wraps
the PNG every other platform uses into an .ico at build time — an ICO
entry may be a PNG, so the wrapper is a 22-byte header — and hands it
to winresource with the version cargo already knows. The crate is an
unconditional build-dependency because a cfg(windows) on one is
evaluated against the host, which here is Linux; the script itself
returns before touching it on any other target.
2026-09-12 00:54:11 +02:00

73 lines
3.4 KiB
Rust

//! DarkRoom desktop entry point.
//!
//! darkroom-desktop <file-or-directory>...
//! darkroom-desktop --version
// TRACES: FR-PLAT-WIN-2
// A GUI-subsystem executable, or Windows opens a console window behind the
// application for the life of the process. Release only: the console is where
// the log goes when there is no file, and a debug build is run from one.
// `--version` still prints under this — stdout is simply not attached when
// launched from Explorer, which is not where anyone asks for a version.
#![cfg_attr(all(windows, not(debug_assertions)), windows_subsystem = "windows")]
use std::path::PathBuf;
use dr_plat::diagnostics::Installed;
fn main() -> anyhow::Result<()> {
// TRACES: FR-PLAT-WIN-3
// Before the logger, the crash hook and everything else: this exists so a
// build made on a machine that cannot run the application — the Linux CI
// producing the Windows binary, checked under Wine — has an exit that
// proves the executable starts without opening a window or touching the
// user's directories (docs/windows.md §6).
if std::env::args().nth(1).as_deref() == Some("--version") {
println!("darkroom-desktop {}", env!("CARGO_PKG_VERSION"));
return Ok(());
}
// Built rather than `init`ed, so the same logger can be handed to the
// diagnostics tee: `env_logger` keeps writing to stderr exactly as before,
// and every record it accepts is also appended to the on-disk log
// (NFR-OPS-1). `filter()` is asked afterwards because the environment may
// have overridden the default below, and the file must not be quieter than
// the terminal.
let console = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or(
"info,wgpu_core=warn,wgpu_hal=warn,zbus=warn,tracing=warn,calloop=warn,rawler=warn",
))
.build();
let level = console.filter();
let logging = dr_plat::diagnostics::install(Box::new(console), level);
// Immediately after the logger and before anything that could fail. Until
// now a panic on desktop went to stderr and died with the terminal, which
// means every panic a user has ever hit was unreportable: the process
// survives (the panicking worker does not), a control goes dead, and there
// is nothing on disk to say why. The record is local and stays local —
// there is no upload path, by design; see `dr_plat::crash`.
dr_plat::crash::install(env!("CARGO_PKG_VERSION"));
log::info!("DarkRoom v{}", env!("CARGO_PKG_VERSION"));
// First thing in the file, so a user asked for "the log" can find it
// without being told a path over the phone.
match &logging {
Installed::ToFile(path) => log::info!("logging to {}", path.display()),
Installed::ConsoleOnly(why) => log::warn!("no log file this session: {why}"),
}
let paths: Vec<PathBuf> = std::env::args().skip(1).map(PathBuf::from).collect();
if paths.is_empty() {
eprintln!("usage: darkroom-desktop <file-or-directory>...");
}
dr_ui::run(paths)?;
// Skip Rust's normal static/thread-local teardown on the way out: a
// background zbus/keyring connection opened by dr_ui::launch_ui can
// still be alive here, and unwinding through it races its async-io
// reactor thread, panicking with "thread local ... during or after
// destruction" when the window is closed.
std::process::exit(0);
}