소스 검색

fix hot reload on windows (#2142)

Evan Almloff 1 년 전
부모
커밋
e464294c66
5개의 변경된 파일85개의 추가작업 그리고 52개의 파일을 삭제
  1. 25 12
      packages/cli/src/server/desktop/mod.rs
  2. 2 0
      packages/desktop/Cargo.toml
  3. 18 14
      packages/desktop/src/app.rs
  4. 7 1
      packages/hot-reload/src/file_watcher.rs
  5. 33 25
      packages/hot-reload/src/lib.rs

+ 25 - 12
packages/cli/src/server/desktop/mod.rs

@@ -14,7 +14,7 @@ use interprocess::local_socket::LocalSocketListener;
 use std::{
     fs::create_dir_all,
     process::{Child, Command},
-    sync::{Arc, Mutex, RwLock},
+    sync::{Arc, RwLock},
 };
 use tokio::sync::broadcast::{self};
 
@@ -75,6 +75,22 @@ async fn serve<P: Platform + Send + 'static>(
     serve: &ConfigOptsServe,
     hot_reload_state: Option<HotReloadState>,
 ) -> Result<()> {
+    let hot_reload: tokio::task::JoinHandle<Result<()>> = tokio::spawn({
+        let hot_reload_state = hot_reload_state.clone();
+        async move {
+            match hot_reload_state {
+                Some(hot_reload_state) => {
+                    // The open interprocess sockets
+                    start_desktop_hot_reload(hot_reload_state).await?;
+                }
+                None => {
+                    std::future::pending::<()>().await;
+                }
+            }
+            Ok(())
+        }
+    });
+
     let platform = RwLock::new(P::start(&config, serve)?);
 
     tracing::info!("🚀 Starting development server...");
@@ -88,19 +104,11 @@ async fn serve<P: Platform + Send + 'static>(
         },
         &config,
         None,
-        hot_reload_state.clone(),
+        hot_reload_state,
     )
     .await?;
 
-    match hot_reload_state {
-        Some(hot_reload_state) => {
-            // The open interprocess sockets
-            start_desktop_hot_reload(hot_reload_state).await?;
-        }
-        None => {
-            std::future::pending::<()>().await;
-        }
-    }
+    hot_reload.await.unwrap()?;
 
     Ok(())
 }
@@ -115,7 +123,12 @@ async fn start_desktop_hot_reload(hot_reload_state: HotReloadState) -> Result<()
     let _ = create_dir_all(target_dir); // `_all` is for good measure and future-proofness.
     let path = target_dir.join("dioxusin");
     clear_paths(&path);
-    match LocalSocketListener::bind(path) {
+    let listener = if cfg!(windows) {
+        LocalSocketListener::bind("@dioxusin")
+    } else {
+        LocalSocketListener::bind(path)
+    };
+    match listener {
         Ok(local_socket_stream) => {
             let aborted = Arc::new(Mutex::new(false));
             // States

+ 2 - 0
packages/desktop/Cargo.toml

@@ -49,6 +49,8 @@ futures-util = { workspace = true }
 urlencoding = "2.1.2"
 async-trait = "0.1.68"
 tao = { version = "0.26.1", features = ["rwh_05"] }
+
+[target.'cfg(unix)'.dependencies]
 signal-hook = "0.3.17"
 
 [target.'cfg(any(target_os = "windows",target_os = "macos",target_os = "linux",target_os = "dragonfly", target_os = "freebsd", target_os = "netbsd", target_os = "openbsd"))'.dependencies]

+ 18 - 14
packages/desktop/src/app.rs

@@ -474,22 +474,26 @@ impl App {
     /// Whenever sigkill is sent, we shut down the app and save the window state
     #[cfg(debug_assertions)]
     fn connect_preserve_window_state_handler(&self) {
-        // Wire up the trap
-        let target = self.shared.proxy.clone();
-        std::thread::spawn(move || {
-            use signal_hook::consts::{SIGINT, SIGTERM};
-            let sigkill = signal_hook::iterator::Signals::new([SIGTERM, SIGINT]);
-            if let Ok(mut sigkill) = sigkill {
-                for _ in sigkill.forever() {
-                    if target.send_event(UserWindowEvent::Shutdown).is_err() {
-                        std::process::exit(0);
+        // TODO: make this work on windows
+        #[cfg(unix)]
+        {
+            // Wire up the trap
+            let target = self.shared.proxy.clone();
+            std::thread::spawn(move || {
+                use signal_hook::consts::{SIGINT, SIGTERM};
+                let sigkill = signal_hook::iterator::Signals::new([SIGTERM, SIGINT]);
+                if let Ok(mut sigkill) = sigkill {
+                    for _ in sigkill.forever() {
+                        if target.send_event(UserWindowEvent::Shutdown).is_err() {
+                            std::process::exit(0);
+                        }
+
+                        // give it a moment for the event to be processed
+                        std::thread::sleep(std::time::Duration::from_secs(1));
                     }
-
-                    // give it a moment for the event to be processed
-                    std::thread::sleep(std::time::Duration::from_secs(1));
                 }
-            }
-        });
+            });
+        }
     }
 }
 

+ 7 - 1
packages/hot-reload/src/file_watcher.rs

@@ -173,7 +173,13 @@ pub fn init<Ctx: HotReloadingContext + Send + 'static>(cfg: Config<Ctx>) {
         }
     }
 
-    let local_socket_stream = match LocalSocketListener::bind(hot_reload_socket_path) {
+    let listener = if cfg!(windows) {
+        LocalSocketListener::bind("@dioxusin")
+    } else {
+        LocalSocketListener::bind(hot_reload_socket_path)
+    };
+
+    let local_socket_stream = match listener {
         Ok(local_socket_stream) => local_socket_stream,
         Err(err) => {
             println!("failed to connect to hot reloading\n{err}");

+ 33 - 25
packages/hot-reload/src/lib.rs

@@ -30,41 +30,49 @@ pub enum HotReloadMsg {
 
 /// Connect to the hot reloading listener. The callback provided will be called every time a template change is detected
 pub fn connect(callback: impl FnMut(HotReloadMsg) + Send + 'static) {
-    // FIXME: this is falling back onto the current directory when not running under cargo, which is how the CLI runs this.
-    // This needs to be fixed.
-    let _manifest_dir = std::env::var("CARGO_MANIFEST_DIR");
-
-    // get the cargo manifest directory, where the target dir lives
-    let mut path = match _manifest_dir {
-        Ok(manifest_dir) => PathBuf::from(manifest_dir),
-        Err(_) => std::env::current_dir().unwrap(),
-    };
+    if cfg!(windows) {
+        connect_at(PathBuf::from("@dioxusin"), callback);
+    } else {
+        // FIXME: this is falling back onto the current directory when not running under cargo, which is how the CLI runs this.
+        // This needs to be fixed.
+        let _manifest_dir = std::env::var("CARGO_MANIFEST_DIR");
+
+        // get the cargo manifest directory, where the target dir lives
+        let mut path = match _manifest_dir {
+            Ok(manifest_dir) => PathBuf::from(manifest_dir),
+            Err(_) => std::env::current_dir().unwrap(),
+        };
 
-    // walk the path until we a find a socket named `dioxusin` inside that folder's target directory
-    loop {
-        let maybe = path.join("target").join("dioxusin");
+        // walk the path until we a find a socket named `dioxusin` inside that folder's target directory
+        loop {
+            let maybe = path.join("target").join("dioxusin");
+
+            if maybe.exists() {
+                path = maybe;
+                break;
+            }
 
-        if maybe.exists() {
-            path = maybe;
-            break;
+            // It's likely we're running under just cargo and not dx
+            path = match path.parent() {
+                Some(parent) => parent.to_path_buf(),
+                None => return,
+            };
         }
 
-        // It's likely we're running under just cargo and not dx
-        path = match path.parent() {
-            Some(parent) => parent.to_path_buf(),
-            None => return,
-        };
+        println!("connecting to {:?}", path);
+        connect_at(path, callback);
     }
-
-    println!("connecting to {:?}", path);
-
-    connect_at(path, callback);
 }
 
 pub fn connect_at(socket: PathBuf, mut callback: impl FnMut(HotReloadMsg) + Send + 'static) {
     std::thread::spawn(move || {
         // There might be a socket since the we're not running under the hot reloading server
-        let Ok(socket) = LocalSocketStream::connect(socket.clone()) else {
+        let stream = if cfg!(windows) {
+            LocalSocketStream::connect("@dioxusin")
+        } else {
+            LocalSocketStream::connect(socket.clone())
+        };
+        let Ok(socket) = stream else {
             println!(
                 "could not find hot reloading server at {:?}, make sure it's running",
                 socket