From 24df6439eabe695b1914f275fb7f40d2c5a8a733 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Tue, 28 Oct 2025 11:38:52 -0700 Subject: [PATCH] feat: set windows subsytem to windows for gui apps (#4855) * feat: set windows subsytem to windows for gui apps * typo * clippy --- packages/cli/src/build/request.rs | 56 ++++++++++++++++++++----------- packages/cli/src/cli/target.rs | 8 +++++ 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/packages/cli/src/build/request.rs b/packages/cli/src/build/request.rs index a84df6ea1..3a1b7454b 100644 --- a/packages/cli/src/build/request.rs +++ b/packages/cli/src/build/request.rs @@ -855,6 +855,27 @@ impl BuildRequest { let mut custom_linker = cargo_config.linker(triple.to_string()).ok().flatten(); let mut rustflags = cargo_config2::Flags::default(); + // Make sure to take into account the RUSTFLAGS env var and the CARGO_TARGET__RUSTFLAGS + for env in [ + "RUSTFLAGS".to_string(), + format!("CARGO_TARGET_{triple}_RUSTFLAGS"), + ] { + if let Ok(flags) = std::env::var(env) { + rustflags + .flags + .extend(cargo_config2::Flags::from_space_separated(&flags).flags); + } + } + + // Use the user's linker if the specify it at the target level + if let Ok(target) = cargo_config.target(triple.to_string()) { + if let Some(flags) = target.rustflags { + rustflags.flags.extend(flags.flags); + } + } + + // When we do android builds we need to make sure we link against the android libraries + // We also `--export-dynamic` to make sure we can do shenanigans like `dlsym` the `main` symbol if matches!(bundle, BundleFormat::Android) { rustflags.flags.extend([ "-Clink-arg=-landroid".to_string(), @@ -869,6 +890,22 @@ impl BuildRequest { ]); } + // On windows, we pass /SUBSYSTbEM:WINDOWS to prevent a console from appearing + if matches!(bundle, BundleFormat::Windows) + && !rustflags + .flags + .iter() + .any(|f| f.starts_with("-Clink-arg=/SUBSYSTEM:")) + { + let subsystem = args + .windows_subsystem + .clone() + .unwrap_or_else(|| "WINDOWS".to_string()); + rustflags + .flags + .push(format!("-Clink-arg=/SUBSYSTEM:{}", subsystem)); + } + // Make sure we set the sysroot for ios builds in the event the user doesn't have it set if matches!(bundle, BundleFormat::Ios) { let xcode_path = Workspace::get_xcode_path() @@ -897,25 +934,6 @@ impl BuildRequest { ); } - // Make sure to take into account the RUSTFLAGS env var and the CARGO_TARGET__RUSTFLAGS - for env in [ - "RUSTFLAGS".to_string(), - format!("CARGO_TARGET_{triple}_RUSTFLAGS"), - ] { - if let Ok(flags) = std::env::var(env) { - rustflags - .flags - .extend(cargo_config2::Flags::from_space_separated(&flags).flags); - } - } - - // Use the user's linker if the specify it at the target level - if let Ok(target) = cargo_config.target(triple.to_string()) { - if let Some(flags) = target.rustflags { - rustflags.flags.extend(flags.flags); - } - } - // If no custom linker is set, then android falls back to us as the linker if custom_linker.is_none() && bundle == BundleFormat::Android { let min_sdk_version = config.application.android_min_sdk_version.unwrap_or(28); diff --git a/packages/cli/src/cli/target.rs b/packages/cli/src/cli/target.rs index ee3a8a4a7..d62c5acad 100644 --- a/packages/cli/src/cli/target.rs +++ b/packages/cli/src/cli/target.rs @@ -153,6 +153,14 @@ pub(crate) struct TargetArgs { /// Automatically pass `--features=js_cfg` when building for wasm targets. This is enabled by default. #[clap(long, default_value_t = true, help_heading = HELP_HEADING, num_args = 0..=1)] pub(crate) wasm_js_cfg: bool, + + /// The Windows subsystem to use when building for Windows targets. This can be either `CONSOLE` or `WINDOWS`. + /// + /// By default, DX uses `WINDOWS` since it assumes a GUI application, but you can override this behavior with this flag. + /// + /// See for more information. + #[clap(long, help_heading = HELP_HEADING)] + pub(crate) windows_subsystem: Option, } impl Anonymized for TargetArgs {