From dd2232e6d3149e7b4b1aff6368bb2b99d924eb99 Mon Sep 17 00:00:00 2001
From: htngr <124245785+htngr@users.noreply.github.com>
Date: Fri, 22 Nov 2024 11:14:32 +0100
Subject: [PATCH] feat: codchiw.exe for Windows
---
.github/workflows/build-windows.yml | 2 +
{codchi => build}/.msvc_manifest.json | 0
build/build-rust-package.nix | 224 +++++++++++++++++++++++++
build/msix/AppxManifest.xml | 9 +-
codchi/default.nix | 225 +-------------------------
codchi/src/cli.rs | 8 -
codchi/src/main.rs | 24 +--
codchi/src/platform/windows/host.rs | 15 +-
codchiw/.gitignore | 1 +
codchiw/Cargo.lock | 180 +++++++++++++++++++++
codchiw/Cargo.toml | 8 +
codchiw/default.nix | 22 +++
codchiw/src/main.rs | 51 ++++++
flake.nix | 2 +
14 files changed, 513 insertions(+), 258 deletions(-)
rename {codchi => build}/.msvc_manifest.json (100%)
create mode 100644 build/build-rust-package.nix
create mode 100644 codchiw/.gitignore
create mode 100644 codchiw/Cargo.lock
create mode 100644 codchiw/Cargo.toml
create mode 100644 codchiw/default.nix
create mode 100644 codchiw/src/main.rs
diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
index b7100c7a..61d4b71a 100644
--- a/.github/workflows/build-windows.yml
+++ b/.github/workflows/build-windows.yml
@@ -21,6 +21,8 @@ jobs:
- run: |
nix build .#windows -L
cp result/bin/*.exe .
+ nix build .#codchiw-windows -L
+ cp result/bin/*.exe .
nix build .#store-wsl.config.build.tarball -L
cp result store.tar.gz
nix build .#machine-wsl.config.build.tarball -L
diff --git a/codchi/.msvc_manifest.json b/build/.msvc_manifest.json
similarity index 100%
rename from codchi/.msvc_manifest.json
rename to build/.msvc_manifest.json
diff --git a/build/build-rust-package.nix b/build/build-rust-package.nix
new file mode 100644
index 00000000..d16a095c
--- /dev/null
+++ b/build/build-rust-package.nix
@@ -0,0 +1,224 @@
+{ self
+, runCommand
+, runCommandLocal
+, runtimeShell
+, writeShellScript
+, writeShellScriptBin
+, fetchFromGitHub
+
+, lib
+
+, store-lxd-tarball
+, machine-lxd-tarball
+, platform
+
+, makeRustPlatform
+, rust-bin
+
+, makeWrapper
+, pkg-config
+, gtk3
+, libayatana-appindicator
+
+, llvmPackages
+, cargo-xwin
+, wine64
+
+, installShellFiles
+, pandoc
+, ...
+}:
+
+args:
+
+let
+ rustConfig = {
+ extensions = [
+ "rust-src"
+ "rust-analyzer"
+ ];
+ targets = [
+ "x86_64-unknown-linux-gnu"
+ "x86_64-pc-windows-msvc"
+ "wasm32-wasi"
+ ];
+ };
+ # rustOrig = rust-bin.stable.latest.default.override rustConfig;
+ rustOrig = rust-bin.selectLatestNightlyWith (toolchain: toolchain.default.override rustConfig);
+ rustPlatformOrig = makeRustPlatform { cargo = rustOrig; rustc = rustOrig; };
+ xwin = rustPlatformOrig.buildRustPackage rec {
+ name = "xwin";
+ src = fetchFromGitHub {
+ owner = "Jake-Shadle";
+ repo = "xwin";
+ rev = "0.5.0";
+ sha256 = "sha256-qHlh1PjEzm8nJW3IemikCaaxLtUCZRQccGQg/DgnJ4k=";
+ };
+ checkPhase = ":";
+ cargoLock.lockFile = "${src}/Cargo.lock";
+ };
+ nix-git = writeShellScriptBin "nix-git-commit" ''
+ echo ${self.rev or self.dirtyRev or "dirty"}
+ '';
+
+ native = {
+ win = rec {
+ passthru = {
+ inherit xwin nix-git;
+ splatted = runCommand "splat"
+ {
+ nativeBuildInputs = [ passthru.xwin ];
+ outputHashMode = "recursive";
+ outputHashAlgo = "sha256";
+ outputHash = "sha256-5ZZeEBuemx+lRmc9PczMfd13JwTvI6qMNvNmHdtK+1U=";
+ }
+ ''
+ mkdir -p $out/xwin
+ xwin --accept-license --manifest ${./.msvc_manifest.json} splat --output $out/xwin --copy
+ '';
+
+ # wrap cargo by checking and injecting xwin where it is needed
+ rust = (runCommandLocal "cargo-xwinize" { } ''
+ cp -r ${rustOrig} $out
+ chmod +w $out/bin
+ mv $out/bin/cargo $out/bin/.cargo
+ cat << EOF > $out/bin/cargo
+ #!${runtimeShell}
+ case "\$1" in
+ build|check|clippy|run|rustc|test)
+ # replace linux target with msvc
+ if [ -z "\$CARGO_ENCODED_RUSTFLAGS" ]; then
+ args=()
+ prev_was_target=
+ for i in "\$@"; do
+ if [ -n "\$prev_was_target" ]; then
+ args+=("${CARGO_BUILD_TARGET}");
+ prev_was_target=
+ continue
+ fi
+ case "\$i" in
+ --target)
+ prev_was_target=1
+ ;;
+ --)
+ # duplicate '--' to satisfy xwin test
+ if [ "\$1" = "test" ]; then
+ args+=("\$i");
+ fi
+ ;;
+ esac
+ args+=("\$i");
+ done
+ exec -a "\$0" $out/bin/.cargo xwin "\''${args[@]}"
+ fi
+ ;;
+ esac
+ exec -a "\$0" $out/bin/.cargo "\$@"
+ EOF
+ chmod +x $out/bin/cargo
+ '')
+ //
+ { inherit (rustOrig) meta; };
+ rustPlatform = makeRustPlatform { cargo = passthru.rust; rustc = passthru.rust; };
+
+ setupXWin = topDir: /* bash */ ''
+ if [ ! -d "${topDir}" ]; then
+ mkdir -p "${topDir}"
+ fi
+ export WINEPREFIX="${topDir}/.wine"
+ export XWIN_ARCH="x86_64"
+ export XWIN_CACHE_DIR="${topDir}/.xwin"
+ if [ ! -d $XWIN_CACHE_DIR ]; then
+ mkdir -p $XWIN_CACHE_DIR
+ cp -r ${passthru.splatted}/xwin $XWIN_CACHE_DIR
+ chmod -R +w $XWIN_CACHE_DIR
+ echo "x86_64" > $XWIN_CACHE_DIR/xwin/DONE
+ fi
+ '';
+ };
+
+ auditable = false; # disable cargo auditable
+
+ CARGO_BUILD_TARGET = "x86_64-pc-windows-msvc";
+ CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUNNER = writeShellScript "wine-wsl" ''
+ if ! command -v /bin/wslpath &> /dev/null; then
+ ${wine64}/bin/wine64 "$@"
+ else
+ "$@"
+ fi
+ '';
+
+ # On Windows MSVC, statically link the C runtime so that the resulting EXE does
+ # not depend on the vcruntime DLL.
+ RUSTFLAGS = "-C target-feature=+crt-static";
+
+ nativeBuildInputs = [
+ llvmPackages.llvm
+ llvmPackages.bintools
+ llvmPackages.clang
+ llvmPackages.lld
+ cargo-xwin
+ nix-git
+ pandoc
+ ];
+
+ preConfigure = passthru.setupXWin "$(mktemp -d)";
+
+ installPhase = ''
+ mkdir -p $out/bin
+ cp target/${CARGO_BUILD_TARGET}/*/*.exe $out/bin
+ '';
+
+ CODCHI_WSL_VERSION_MIN = "2.0.14";
+ CODCHI_WSL_VERSION_MAX = "2.3.26";
+
+ };
+ linux = rec {
+ CARGO_BUILD_TARGET = "x86_64-unknown-linux-gnu";
+
+ CODCHI_LXD_CONTAINER_STORE = store-lxd-tarball;
+ CODCHI_LXD_CONTAINER_MACHINE = machine-lxd-tarball;
+
+ passthru = {
+ inherit xwin nix-git;
+ rust = rustOrig;
+ rustPlatform = rustPlatformOrig;
+ };
+ nativeBuildInputs = [
+ pkg-config
+ nix-git
+ makeWrapper
+ pandoc
+ installShellFiles
+ ];
+ buildInputs = [
+ gtk3
+ libayatana-appindicator.out
+ ];
+
+ outputs = [ "out" "docs" ];
+
+ postInstall = ''
+ installManPage ./target/codchi/man/*
+ installShellCompletion --cmd codchi \
+ --bash ./target/codchi/completions/codchi.bash \
+ --fish ./target/codchi/completions/codchi.fish \
+ --zsh ./target/codchi/completions/_codchi
+
+ mkdir -p $docs
+ cp -r ./target/codchi/md $docs/usage
+ '';
+
+ postFixup = ''
+ patchelf "$out/bin/codchi" \
+ --add-rpath ${lib.makeLibraryPath buildInputs}
+ wrapProgram "$out/bin/codchi" \
+ --set CODCHI_LXD_CONTAINER_STORE $CODCHI_LXD_CONTAINER_STORE \
+ --set CODCHI_LXD_CONTAINER_MACHINE $CODCHI_LXD_CONTAINER_MACHINE
+ '';
+ };
+ }.${platform};
+
+
+in
+native.passthru.rustPlatform.buildRustPackage (lib.recursiveUpdate args native)
diff --git a/build/msix/AppxManifest.xml b/build/msix/AppxManifest.xml
index 8d8f66e0..64ea17c1 100755
--- a/build/msix/AppxManifest.xml
+++ b/build/msix/AppxManifest.xml
@@ -51,7 +51,14 @@
-
+
+
+
+
+
+
diff --git a/codchi/default.nix b/codchi/default.nix
index 4e8c73dc..0034aebc 100644
--- a/codchi/default.nix
+++ b/codchi/default.nix
@@ -1,226 +1,13 @@
-{ self
-, runCommand
-, runCommandLocal
-, runtimeShell
-, writeShellScript
-, writeShellScriptBin
-, fetchFromGitHub
-
+{ callPackage
, lib
-
-, store-lxd-tarball
-, machine-lxd-tarball
+, self
, platform
-
-, makeRustPlatform
-, rust-bin
-
-, makeWrapper
-, pkg-config
-, gtk3
-, libayatana-appindicator
-
-, llvmPackages
-, cargo-xwin
-, wine64
-
-, installShellFiles
-, pandoc
-, ...
}:
let
Cargo = builtins.fromTOML (builtins.readFile ./Cargo.toml);
-
- rustConfig = {
- extensions = [
- "rust-src"
- "rust-analyzer"
- ];
- targets = [
- "x86_64-unknown-linux-gnu"
- "x86_64-pc-windows-msvc"
- "wasm32-wasi"
- ];
- };
- # rustOrig = rust-bin.stable.latest.default.override rustConfig;
- rustOrig = rust-bin.selectLatestNightlyWith (toolchain: toolchain.default.override rustConfig);
- rustPlatformOrig = makeRustPlatform { cargo = rustOrig; rustc = rustOrig; };
- xwin = rustPlatformOrig.buildRustPackage rec {
- name = "xwin";
- src = fetchFromGitHub {
- owner = "Jake-Shadle";
- repo = "xwin";
- rev = "0.5.0";
- sha256 = "sha256-qHlh1PjEzm8nJW3IemikCaaxLtUCZRQccGQg/DgnJ4k=";
- };
- checkPhase = ":";
- cargoLock.lockFile = "${src}/Cargo.lock";
- };
- nix-git = writeShellScriptBin "nix-git-commit" ''
- echo ${self.rev or self.dirtyRev or "dirty"}
- '';
-
- native = {
- win = rec {
- passthru = {
- inherit xwin;
- splatted = runCommand "splat"
- {
- nativeBuildInputs = [ passthru.xwin ];
- outputHashMode = "recursive";
- outputHashAlgo = "sha256";
- outputHash = "sha256-5ZZeEBuemx+lRmc9PczMfd13JwTvI6qMNvNmHdtK+1U=";
- }
- ''
- mkdir -p $out/xwin
- xwin --accept-license --manifest ${./.msvc_manifest.json} splat --output $out/xwin --copy
- '';
-
- # wrap cargo by checking and injecting xwin where it is needed
- rust = (runCommandLocal "cargo-xwinize" { } ''
- cp -r ${rustOrig} $out
- chmod +w $out/bin
- mv $out/bin/cargo $out/bin/.cargo
- cat << EOF > $out/bin/cargo
- #!${runtimeShell}
- case "\$1" in
- build|check|clippy|run|rustc|test)
- # replace linux target with msvc
- if [ -z "\$CARGO_ENCODED_RUSTFLAGS" ]; then
- args=()
- prev_was_target=
- for i in "\$@"; do
- if [ -n "\$prev_was_target" ]; then
- args+=("${CARGO_BUILD_TARGET}");
- prev_was_target=
- continue
- fi
- case "\$i" in
- --target)
- prev_was_target=1
- ;;
- --)
- # duplicate '--' to satisfy xwin test
- if [ "\$1" = "test" ]; then
- args+=("\$i");
- fi
- ;;
- esac
- args+=("\$i");
- done
- exec -a "\$0" $out/bin/.cargo xwin "\''${args[@]}"
- fi
- ;;
- esac
- exec -a "\$0" $out/bin/.cargo "\$@"
- EOF
- chmod +x $out/bin/cargo
- '')
- //
- { inherit (rustOrig) meta; };
- rustPlatform = makeRustPlatform { cargo = passthru.rust; rustc = passthru.rust; };
-
- setupXWin = topDir: /* bash */ ''
- if [ ! -d "${topDir}" ]; then
- mkdir -p "${topDir}"
- fi
- export WINEPREFIX="${topDir}/.wine"
- export XWIN_ARCH="x86_64"
- export XWIN_CACHE_DIR="${topDir}/.xwin"
- if [ ! -d $XWIN_CACHE_DIR ]; then
- mkdir -p $XWIN_CACHE_DIR
- cp -r ${passthru.splatted}/xwin $XWIN_CACHE_DIR
- chmod -R +w $XWIN_CACHE_DIR
- echo "x86_64" > $XWIN_CACHE_DIR/xwin/DONE
- fi
- '';
- };
-
- auditable = false; # disable cargo auditable
-
- CARGO_BUILD_TARGET = "x86_64-pc-windows-msvc";
- CARGO_TARGET_X86_64_PC_WINDOWS_MSVC_RUNNER = writeShellScript "wine-wsl" ''
- if ! command -v /bin/wslpath &> /dev/null; then
- ${wine64}/bin/wine64 "$@"
- else
- "$@"
- fi
- '';
-
- # On Windows MSVC, statically link the C runtime so that the resulting EXE does
- # not depend on the vcruntime DLL.
- RUSTFLAGS = "-C target-feature=+crt-static";
-
- nativeBuildInputs = [
- llvmPackages.llvm
- llvmPackages.bintools
- llvmPackages.clang
- llvmPackages.lld
- cargo-xwin
- nix-git
- pandoc
- ];
-
- preConfigure = passthru.setupXWin "$(mktemp -d)";
-
- installPhase = ''
- mkdir -p $out/bin
- cp target/${CARGO_BUILD_TARGET}/*/*.exe $out/bin
- '';
-
- CODCHI_WSL_VERSION_MIN = "2.0.14";
- CODCHI_WSL_VERSION_MAX = "2.3.26";
-
- };
- linux = rec {
- CARGO_BUILD_TARGET = "x86_64-unknown-linux-gnu";
-
- CODCHI_LXD_CONTAINER_STORE = store-lxd-tarball;
- CODCHI_LXD_CONTAINER_MACHINE = machine-lxd-tarball;
-
- passthru = {
- inherit xwin;
- rust = rustOrig;
- rustPlatform = rustPlatformOrig;
- };
- nativeBuildInputs = [
- pkg-config
- nix-git
- makeWrapper
- pandoc
- installShellFiles
- ];
- buildInputs = [
- gtk3
- libayatana-appindicator.out
- ];
-
- outputs = [ "out" "docs" ];
-
- postInstall = ''
- installManPage ./target/codchi/man/*
- installShellCompletion --cmd codchi \
- --bash ./target/codchi/completions/codchi.bash \
- --fish ./target/codchi/completions/codchi.fish \
- --zsh ./target/codchi/completions/_codchi
-
- mkdir -p $docs
- cp -r ./target/codchi/md $docs/usage
- '';
-
- postFixup = ''
- patchelf "$out/bin/codchi" \
- --add-rpath ${lib.makeLibraryPath buildInputs}
- wrapProgram "$out/bin/codchi" \
- --set CODCHI_LXD_CONTAINER_STORE $CODCHI_LXD_CONTAINER_STORE \
- --set CODCHI_LXD_CONTAINER_MACHINE $CODCHI_LXD_CONTAINER_MACHINE
- '';
- };
- }.${platform};
-
-
in
-native.passthru.rustPlatform.buildRustPackage (lib.recursiveUpdate
+callPackage ../build/build-rust-package.nix
+{ inherit self platform; }
{
pname = "codchi";
inherit (Cargo.package) version;
@@ -229,7 +16,6 @@ native.passthru.rustPlatform.buildRustPackage (lib.recursiveUpdate
"^src.*$"
"^assets.*$"
"^Cargo\..*"
- "^\.msvc_manifest.json$"
"^build.*$"
];
cargoLock.lockFile = ./Cargo.lock;
@@ -237,7 +23,4 @@ native.passthru.rustPlatform.buildRustPackage (lib.recursiveUpdate
# "tray-icon-0.16.0" = "sha256-LxkEP31myIiWh6FDOzr9rZ8KAWISbja0jmEx0E2lM44=";
# "clap-4.5.19" = "sha256-YRuZlp7jk05QLI551shgcVftcqKytTkxHlKbVejT1eE=";
};
-
- passthru = { inherit nix-git; };
}
- native)
diff --git a/codchi/src/cli.rs b/codchi/src/cli.rs
index 4a60acb2..29e7c944 100644
--- a/codchi/src/cli.rs
+++ b/codchi/src/cli.rs
@@ -22,9 +22,6 @@ pub static DEBUG: LazyLock = LazyLock::new(|| {
.unwrap()
>= Level::Debug
});
-#[cfg(target_os = "windows")]
-pub static TERMINAL: LazyLock =
- LazyLock::new(|| CLI_ARGS.get().and_then(|cli| cli.terminal) != Some(false));
type DefaultLogLevel = InfoLevel;
@@ -81,11 +78,6 @@ pub struct Cli {
#[arg(long, global = true)]
pub json: bool,
- /// Hide or show console window on Windows. Used when launching GUI apps via shortcuts.
- #[cfg(target_os = "windows")]
- #[arg(long, hide = true, default_value = "true")]
- pub terminal: Option,
-
#[command(subcommand)]
pub command: Option,
}
diff --git a/codchi/src/main.rs b/codchi/src/main.rs
index 7c731dde..af65713b 100644
--- a/codchi/src/main.rs
+++ b/codchi/src/main.rs
@@ -34,30 +34,8 @@ fn main() -> anyhow::Result<()> {
logging::init(cli.verbose.log_level_filter())?;
- #[cfg(target_os = "windows")]
- {
- // https://github.com/rust-lang/cargo/issues/1721
- use util::dbg_duration;
- use windows::Win32::{
- System::Console::GetConsoleWindow,
- UI::WindowsAndMessaging::{self, ShowWindow},
- };
- if cli.terminal == Some(false) {
- dbg_duration("hide console", || {
- let window = unsafe { GetConsoleWindow() };
- if !window.0.is_null() {
- if let Err(err) =
- unsafe { ShowWindow(window, WindowsAndMessaging::SW_HIDE).ok() }
- {
- log::error!("Failed to hide console window. Reason: {err}");
- }
- println!();
- }
- });
- }
- }
-
log::trace!("Started codchi with args: {:?}", cli);
+
// preload config
let cfg = CodchiConfig::get();
diff --git a/codchi/src/platform/windows/host.rs b/codchi/src/platform/windows/host.rs
index 291f8feb..0c4403fe 100644
--- a/codchi/src/platform/windows/host.rs
+++ b/codchi/src/platform/windows/host.rs
@@ -31,6 +31,10 @@ impl Host for HostImpl {
.cleanup_and_get()?;
let codchi_exe = env::current_exe()?;
+ let codchiw_exe = codchi_exe
+ .parent()
+ .with_context(|| format!("Missing parent of {codchi_exe:?}"))?
+ .join("codchiw.exe");
for DesktopEntry {
app_name,
@@ -40,16 +44,17 @@ impl Host for HostImpl {
is_terminal,
} in apps
{
- let mut lnk = ShellLink::new(codchi_exe.clone())?;
+ let mut lnk = ShellLink::new(if *is_terminal {
+ codchi_exe.clone()
+ } else {
+ codchiw_exe.clone()
+ })?;
if let Some(ico_path) = icon {
let target = ico_folder.join(format!("{app_name}.ico"));
fs::copy(ico_path, &target)?;
lnk.set_icon_location(Some(target.to_string_lossy().to_string()));
}
- // lnk.set_name(Some(name.clone()));
- lnk.set_arguments(Some(format!(
- "--terminal {is_terminal} exec {machine_name} {exec}"
- )));
+ lnk.set_arguments(Some(format!("exec {machine_name} {exec}")));
lnk.set_working_dir(
get_known_folder_path(KnownFolder::Profile)
.map(|p| p.to_string_lossy().to_string()),
diff --git a/codchiw/.gitignore b/codchiw/.gitignore
new file mode 100644
index 00000000..eb5a316c
--- /dev/null
+++ b/codchiw/.gitignore
@@ -0,0 +1 @@
+target
diff --git a/codchiw/Cargo.lock b/codchiw/Cargo.lock
new file mode 100644
index 00000000..5fe83541
--- /dev/null
+++ b/codchiw/Cargo.lock
@@ -0,0 +1,180 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "anyhow"
+version = "1.0.93"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
+
+[[package]]
+name = "codchiw"
+version = "0.1.0"
+dependencies = [
+ "anyhow",
+ "windows",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.92"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.37"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "syn"
+version = "2.0.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
+
+[[package]]
+name = "windows"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
+dependencies = [
+ "windows-core",
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-result",
+ "windows-strings",
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.58.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-result"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
+dependencies = [
+ "windows-result",
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_gnullvm",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
diff --git a/codchiw/Cargo.toml b/codchiw/Cargo.toml
new file mode 100644
index 00000000..69609a17
--- /dev/null
+++ b/codchiw/Cargo.toml
@@ -0,0 +1,8 @@
+[package]
+name = "codchiw"
+version = "0.1.0"
+edition = "2021"
+
+[dependencies]
+anyhow = "1.0.93"
+windows = { version = "0.58.0", features = ["Win32_Foundation", "Win32_System_Console", "Win32_System_Threading", "Win32_UI_WindowsAndMessaging"] }
diff --git a/codchiw/default.nix b/codchiw/default.nix
new file mode 100644
index 00000000..62b64125
--- /dev/null
+++ b/codchiw/default.nix
@@ -0,0 +1,22 @@
+{ callPackage
+, lib
+, self
+, platform
+, ...
+}:
+let
+ Cargo = builtins.fromTOML (builtins.readFile ./Cargo.toml);
+in
+callPackage
+ ../build/build-rust-package.nix
+{ inherit self platform; }
+{
+ pname = "codchiw";
+ inherit (Cargo.package) version;
+ src = lib.sourceByRegex ./. [
+ "^src.*$"
+ "^Cargo\..*"
+ ];
+ cargoLock.lockFile = ./Cargo.lock;
+ passthru = { };
+}
diff --git a/codchiw/src/main.rs b/codchiw/src/main.rs
new file mode 100644
index 00000000..32cd4803
--- /dev/null
+++ b/codchiw/src/main.rs
@@ -0,0 +1,51 @@
+#![windows_subsystem = "windows"]
+
+use std::{
+ env,
+ os::windows::process::CommandExt,
+ process::{Command, Stdio},
+};
+use windows::Win32::{
+ Foundation::HWND,
+ System::Threading::CREATE_NO_WINDOW,
+ UI::WindowsAndMessaging::{MessageBoxW, MB_ICONERROR, MB_OK},
+};
+
+fn main() {
+ let result = (|| {
+ let args: Vec = env::args().skip(1).collect();
+ let codchi_exe = env::current_exe()?.parent().unwrap().join("codchi.exe");
+
+ let child_output = Command::new(codchi_exe)
+ .args(args)
+ .creation_flags(CREATE_NO_WINDOW.0)
+ .stderr(Stdio::piped())
+ .output()?;
+
+ if !child_output.status.success() {
+ let stderr = String::from_utf8_lossy(&child_output.stderr);
+ anyhow::bail!("{stderr}");
+ }
+ anyhow::Ok(())
+ })();
+
+ if let Err(e) = result {
+ fn show_message_box(title: &str, message: &str) {
+ use windows::core::PCWSTR;
+
+ let title_wide: Vec = title.encode_utf16().chain(std::iter::once(0)).collect();
+ let message_wide: Vec = message.encode_utf16().chain(std::iter::once(0)).collect();
+
+ unsafe {
+ MessageBoxW(
+ HWND::default(),
+ PCWSTR(message_wide.as_ptr()),
+ PCWSTR(title_wide.as_ptr()),
+ MB_OK | MB_ICONERROR,
+ );
+ }
+ }
+
+ show_message_box("Codchi had an error", &e.to_string());
+ }
+}
diff --git a/flake.nix b/flake.nix
index 77daf6df..0dde19e4 100644
--- a/flake.nix
+++ b/flake.nix
@@ -24,6 +24,7 @@
(self: _: {
codchi = self.callPackage ./codchi { inherit (inputs) self; platform = "linux"; };
codchi-windows = self.callPackage ./codchi { inherit (inputs) self; platform = "win"; };
+ codchiw-windows = self.callPackage ./codchiw { inherit (inputs) self; platform = "win"; };
codchi-utils = self.callPackage ./utils { };
mkContainer = type: driver: (import ./nix/container
@@ -89,6 +90,7 @@
inherit (pkgs) store-lxd store-wsl machine-lxd machine-wsl codchi-utils;
default = pkgs.codchi;
windows = pkgs.codchi-windows;
+ inherit (pkgs) codchiw-windows;
# editor = pkgs.nixvim.makeNixvim (import ./editor.nix);
};