From 568dbe798a63bb36551eb3851b7496b0fa4ca437 Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Thu, 28 Oct 2021 18:57:21 +1000 Subject: [PATCH] make console optional on Windows --- qt/package/Cargo.lock | 13 ++++++++++++ qt/package/Cargo.toml | 5 ++++- qt/package/rustfmt.toml | 4 ++++ qt/package/src/anki.rs | 35 +++++++++++++++++++++++++++++++++ qt/package/src/main.rs | 6 ++++-- qt/package/win/anki-console.bat | 5 +++++ 6 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 qt/package/rustfmt.toml create mode 100644 qt/package/src/anki.rs create mode 100644 qt/package/win/anki-console.bat diff --git a/qt/package/Cargo.lock b/qt/package/Cargo.lock index a1518ebe7..f20266efd 100644 --- a/qt/package/Cargo.lock +++ b/qt/package/Cargo.lock @@ -17,9 +17,12 @@ version = "0.1.0" dependencies = [ "embed-resource", "jemallocator", + "libc", + "libc-stdhandle", "mimalloc", "pyembed", "snmalloc-rs", + "winapi", ] [[package]] @@ -204,6 +207,16 @@ version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013" +[[package]] +name = "libc-stdhandle" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dac2473dc28934c5e0b82250dab231c9d3b94160d91fe9ff483323b05797551" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "libmimalloc-sys" version = "0.1.22" diff --git a/qt/package/Cargo.toml b/qt/package/Cargo.toml index 2403cc008..e5be3f0cb 100644 --- a/qt/package/Cargo.toml +++ b/qt/package/Cargo.toml @@ -4,7 +4,10 @@ version = "0.1.0" build = "build.rs" edition = "2018" -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[target.'cfg(windows)'.dependencies] +winapi = {version = "0.3", features = ["wincon"]} +libc = "0.2" +libc-stdhandle = "=0.1.0" [dependencies.pyembed] git = "https://github.com/ankitects/PyOxidizer.git" diff --git a/qt/package/rustfmt.toml b/qt/package/rustfmt.toml new file mode 100644 index 000000000..3c812a2b9 --- /dev/null +++ b/qt/package/rustfmt.toml @@ -0,0 +1,4 @@ +# this is not supported on stable Rust, and is ignored by the Bazel rules; it is only +# useful for manual invocation with 'cargo +nightly fmt' +imports_granularity = "Crate" +group_imports = "StdExternalCrate" diff --git a/qt/package/src/anki.rs b/qt/package/src/anki.rs new file mode 100644 index 000000000..3cf960028 --- /dev/null +++ b/qt/package/src/anki.rs @@ -0,0 +1,35 @@ +// Copyright: Ankitects Pty Ltd and contributors +// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html + +pub(super) fn init() { + #[cfg(target_os = "windows")] + attach_console(); + + println!("Anki starting..."); +} + +/// If parent process has a console (eg cmd.exe), redirect our output there. +#[cfg(target_os = "windows")] +fn attach_console() { + use std::ffi::CString; + + use libc_stdhandle::*; + use winapi::um::wincon; + + let console_attached = unsafe { wincon::AttachConsole(wincon::ATTACH_PARENT_PROCESS) }; + if console_attached == 0 { + return; + } + + let conin = CString::new("CONIN$").unwrap(); + let conout = CString::new("CONOUT$").unwrap(); + let r = CString::new("r").unwrap(); + let w = CString::new("w").unwrap(); + + // Python uses the CRT for I/O, and it requires the descriptors are reopened. + unsafe { + libc::freopen(conin.as_ptr(), r.as_ptr(), stdin()); + libc::freopen(conout.as_ptr(), w.as_ptr(), stdout()); + libc::freopen(conout.as_ptr(), w.as_ptr(), stderr()); + } +} diff --git a/qt/package/src/main.rs b/qt/package/src/main.rs index 6b4084e8a..d424d4f26 100644 --- a/qt/package/src/main.rs +++ b/qt/package/src/main.rs @@ -3,7 +3,9 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. -#![windows_subsystem = "console"] +#![windows_subsystem = "windows"] + +mod anki; use pyembed::{MainPythonInterpreter, OxidizedPythonInterpreterConfig}; @@ -14,7 +16,7 @@ static GLOBAL: jemallocator::Jemalloc = jemallocator::Jemalloc; include!(env!("DEFAULT_PYTHON_CONFIG_RS")); fn main() { - println!("Anki starting..."); + anki::init(); let exit_code = { let config: OxidizedPythonInterpreterConfig = default_python_config(); diff --git a/qt/package/win/anki-console.bat b/qt/package/win/anki-console.bat new file mode 100644 index 000000000..7b488cdd9 --- /dev/null +++ b/qt/package/win/anki-console.bat @@ -0,0 +1,5 @@ +@echo off +anki +pause + +