Repository navigation
#![windows_subsystem = "windows"] hides cargo test output #67159
Description
Problem
Calling cargo test on a project that has the #![windows_subsystem = "windows"] global attribute does not show the expected human-readable output.
Instead of showing
> cargo test
Compiling no_output v0.1.0 (C:\Programming\no_output)
Finished dev [unoptimized + debuginfo] target(s) in 0.71s
Running target\debug\deps\no_output-c8b57bda8502ba55.exe
running 1 test
test tests::test_panic ... FAILED
failures:
---- tests::test_panic stdout ----
thread 'tests::test_panic' panicked at 'This tape has just self-destructed!', src\main.rs:9:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
failures:
tests::test_panic
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--bin no_output'
it shows
> cargo test
Compiling no_output v0.1.0 (C:\Programming\no_output)
Finished dev [unoptimized + debuginfo] target(s) in 1.40s
Running target\debug\deps\no_output-c8b57bda8502ba55.exe
error: test failed, to rerun pass '--bin no_output'
which not quite as informative as the former message (it does not tell which tests failed).
Steps
This requires a Windows computer.
- Create a new project with
cargo new. - Copy-paste the following into your
main.rsfile:
#![windows_subsystem = "windows"]
fn main() {
println!("Hello, world!");
}
#[cfg(test)]
mod tests {
#[test]
fn test_panic() {
panic!("This tape has just self-destructed!");
}
}
- call
cargo teston your project.
Possible Solution(s)
My guess is that this is due to executables targeting the Windows subsystem having no console and standard output initialized by default on Windows. Therefore, 2 possible solutions come to my mind:
- forcing
cargo test-compiled executables to target the console subsystem when compiled for Windows; - or having cargo explicitly initialize the console in the test framework automatically included in test executables: AFAIK this can be achieved by calling the
AllocConsole()function provided by the Windows API.
Notes
Output of cargo version: this happens on pretty much any cargo version.
Tested on cargo 1.39.0 (1c6ec66d5 2019-09-30) and cargo 1.41.0-nightly (626f0f40e 2019-12-03).
Apologies if this has already been reported. I was unable to find a similar issue in the repository 😅
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fieldsNo status
Activity
ehuss commentedon Dec 8, 2019
Thanks for the report. I have moved this to rust-lang/rust, as that is where issues for libtest are tracked. This looks to be an issue with the libtest harness.
Interestingly, the output works when run from a cygwin/msys shell, but doesn't with cmd or powershell.
As a workaround, perhaps something like this well help:
#![cfg_attr(not(test), windows_subsystem = "windows")]jonas-schievink commentedon Dec 8, 2019
Isn't this expected behavior?
ehuss commentedon Dec 8, 2019
Good question, I have no idea! I could see an argument that when built with
--testthat rustc could ignore thewindows_subsystemattribute, since the intent is to write to the console. But I do not know what the consequences would be.retep998 commentedon Dec 9, 2019
I'm pretty sure this is due to defaults regarding how console and windows processes inherit stdout/stdin differently. By default console processes will inherit stdout/stdin from the parent process while windows processes do not. I believe the reason we allow stdout/stdin to be inherited instead of explicitly piping it is to allow console processes to emit colors using the conhost color API, because otherwise colors would not work in some situations on Windows.
Songtronix commentedon Jan 29, 2020
This issue isn't limited to tests only. I build a GUI currently and want to avoid popping up a console on start. However using the cli version is not possible anymore because it does not output anything due to stdout/stdin not being attached to anything.
It would be very helpful if there is a winapi call to make which allows to attach stdout/stdin to the parent. This can be used for
cargo testtoo.phiresky commentedon Dec 7, 2021
Here's a workaround to not show a console on start, but still output the normal output when started from powershell or cmd:
from here: https://www.reddit.com/r/learnrust/comments/jaqfcx/windows_print_to_hidden_console_window/
ChrisDenton commentedon Dec 7, 2021
That'll work but be aware that the console will not be waiting for output. This means the prompt may switch back to interactive mode while the program is still running.
EDIT: Just clarify the "may" there, it should be fine when running from cargo or another console process that will wait for the "windows" process to exit. But if you run it directly from powershell or cmd then it won't wait.
phiresky commentedon Dec 7, 2021
After testing, i can not recommend the above workaround. Like you said it doesn't make the console wait for the output, leading to weird output intermingling and undesired behaviour when the console is closed (program might get killed with broken pipe or it might not)
MunchyYDL commentedon Jan 9, 2022
This problem had me on a wild goose chase for a couple of hours yesterday. 🙂
As a relative newbie to Rust, it was a bit hard to know what to look for when I suddenly couldn't run my newly added tests.
After some digging around, my solution to this specific problem is to attribute only the main() function instead of setting it as a crate level attribute.
Maybe this needs to be mentioned somewhere in some docs relating to either
cargo testand/or the docs for the attribute, not only here in the problem report?Example:
My example is a bit contrived, as I really don't need to switch the subsystem for this example, but it exists there only to show how you can place the attribute on the main function only, instead of as a crate level attribute.
ehuss commentedon Jan 9, 2022
@MunchyYDL
#[windows_subsystem]is only valid at the crate root. I have posted #92701 to fix the warning for that.MunchyYDL commentedon Jan 10, 2022
Ah, yes, my bad, I tricked myself into thinking it worked, but I only started the program from within VS Code, not as a standalone. DOH!
Thanks for clearing that up for me! :)
04041b commentedon May 28, 2024
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]Allows console to show up in debug build but not release build.
yangcancai commentedon Mar 17, 2025
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
Can I use this property in lib crate or only in main crate?
retep998 commentedon Mar 17, 2025
Changing the subsystem is something that should only be done in a binary crate. It makes no sense to set it in a library crate and I'd argue it should emit an error if it doesn't already in that case.
fix: 测试二进制去除 windows_subsystem,恢复 cargo test 输出明细