Reputation: 271
I have a Rust program that I want to compile for the "windows" subsystem when I'm building it for distribution. Currently I am using this in my main.rs:
#![feature(windows_subsystem)]
#![windows_subsystem = "windows"]
This works, but when I run the tests on a Windows machine, the Windows subsystem does not have access to the console so I cannot see the output. I need to comment out the above lines of code in order to see the result of my tests.
Is there a way to conditionally compile which subsystem I'm running on in order to get the tests to work?
Upvotes: 4
Views: 2520
Reputation: 1942
I prefer to take this approach to solving the problem of "seeing debug output when run from a console, but don't spawn a console window when running normally" for desktop apps.
First, I always add the #![windows_subsystem = "windows"]
attribute.
Then I take a dependency on the windows
crate. In Cargo.toml:
windows = { version = "{put in the current version here}", features = ["Win32_System_Console"] }
I use that crate to call AttachConsole
at the start of my main
function, passing the argument ATTACH_PARENT_PROCESS
. For cross-platform development, you can do this in a function that is a no-op on non-Windows platforms. Typically I just ignore the result code of that function.
The end result is that when the program is run from a terminal, it attaches to the parent terminal and STDOUT/STDERR make it there. When run without a terminal, it opens with no console.
The downside of this approach is the extra dependency and its build time, but I've found that the windows
crate does a pretty good job of using cargo features to limit the amount of code you need to build. The dependency build is cached as well so it's a one-time cost per machine.
Full example code:
#![windows_subsystem = "windows"]
#[cfg(windows)]
fn attach_parent_console() {
use windows::Win32::System::Console::*;
let _ = unsafe { AttachConsole(ATTACH_PARENT_PROCESS) };
}
#[cfg(not(windows))]
fn attach_parent_console() {
// no-op
}
fn main() {
attach_parent_console();
println!("Hello world!");
}
Upvotes: 0
Reputation: 432059
As described in The Rust Programming Language, specifically the chapter on conditional compilation:
You can also set another attribute based on a
cfg
variable withcfg_attr
:#[cfg_attr(a, b)]
Will be the same as
#[b]
ifa
is set bycfg
attribute, and nothing otherwise.
In this case, it should be something like
#![cfg_attr(my_feature_name_i_made_up, windows_subsystem = "windows")]
Upvotes: 9