Skip to content

Commit 3c9a7d7

Browse files
committed
compile_codegen: refactor watcher to call on_compilation_finishes() even on first completion, code cleanup
1 parent 5db761e commit 3c9a7d7

File tree

1 file changed

+74
-73
lines changed

1 file changed

+74
-73
lines changed

crates/spirv-builder/src/watch.rs

+74-73
Original file line numberDiff line numberDiff line change
@@ -1,114 +1,115 @@
1-
use std::{collections::HashSet, sync::mpsc::sync_channel};
2-
3-
use notify::{Event, RecursiveMode, Watcher};
4-
use rustc_codegen_spirv_types::CompileResult;
5-
61
use crate::{SpirvBuilder, SpirvBuilderError, leaf_deps};
2+
use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher as _};
3+
use rustc_codegen_spirv_types::CompileResult;
4+
use std::path::{Path, PathBuf};
5+
use std::sync::mpsc::Receiver;
6+
use std::{collections::HashSet, sync::mpsc::sync_channel};
77

88
impl SpirvBuilder {
99
/// Watches the module for changes using [`notify`](https://crates.io/crates/notify),
10-
/// and rebuild it upon changes
11-
///
12-
/// Returns the result of the first successful compilation, then calls
13-
/// `on_compilation_finishes` for each subsequent compilation.
10+
/// and rebuild it upon changes. Calls `on_compilation_finishes` after each
11+
/// successful compilation.
1412
pub fn watch(
15-
self,
13+
&self,
1614
mut on_compilation_finishes: impl FnMut(CompileResult) + Send + 'static,
17-
) -> Result<CompileResult, SpirvBuilderError> {
15+
) -> Result<(), SpirvBuilderError> {
1816
let path_to_crate = self
1917
.path_to_crate
2018
.as_ref()
2119
.ok_or(SpirvBuilderError::MissingCratePath)?;
2220
if !matches!(self.print_metadata, crate::MetadataPrintout::None) {
2321
return Err(SpirvBuilderError::WatchWithPrintMetadata);
2422
}
25-
let metadata_result = crate::invoke_rustc(&self);
23+
24+
let metadata_result = crate::invoke_rustc(self);
2625
// Load the dependencies of the thing
2726
let metadata_file = if let Ok(path) = metadata_result {
2827
path
2928
} else {
30-
let (tx, rx) = sync_channel(0);
3129
// Fall back to watching from the crate root if the initial compilation fails
32-
let mut watcher =
33-
notify::recommended_watcher(move |event: notify::Result<Event>| match event {
34-
Ok(e) => match e.kind {
35-
notify::EventKind::Access(_) => (),
36-
notify::EventKind::Any
37-
| notify::EventKind::Create(_)
38-
| notify::EventKind::Modify(_)
39-
| notify::EventKind::Remove(_)
40-
| notify::EventKind::Other => {
41-
let _ = tx.try_send(());
42-
}
43-
},
44-
Err(e) => println!("notify error: {e:?}"),
45-
})
46-
.expect("Could create watcher");
4730
// This is likely to notice changes in the `target` dir, however, given that `cargo watch` doesn't seem to handle that,
31+
let mut watcher = Watcher::new();
4832
watcher
33+
.watcher
4934
.watch(path_to_crate, RecursiveMode::Recursive)
5035
.expect("Could watch crate root");
5136
loop {
52-
rx.recv().expect("Watcher still alive");
53-
let metadata_file = crate::invoke_rustc(&self);
37+
watcher.recv();
38+
let metadata_file = crate::invoke_rustc(self);
5439
if let Ok(f) = metadata_file {
5540
break f;
5641
}
5742
}
5843
};
5944
let metadata = self.parse_metadata_file(&metadata_file)?;
60-
let first_result = metadata;
45+
on_compilation_finishes(metadata);
6146

47+
let builder = self.clone();
6248
let thread = std::thread::spawn(move || {
63-
let mut watched_paths = HashSet::new();
64-
let (tx, rx) = sync_channel(0);
65-
let mut watcher =
66-
notify::recommended_watcher(move |event: notify::Result<Event>| match event {
67-
Ok(e) => match e.kind {
68-
notify::EventKind::Access(_) => (),
69-
notify::EventKind::Any
70-
| notify::EventKind::Create(_)
71-
| notify::EventKind::Modify(_)
72-
| notify::EventKind::Remove(_)
73-
| notify::EventKind::Other => {
74-
let _ = tx.try_send(());
75-
}
76-
},
77-
Err(e) => println!("notify error: {e:?}"),
78-
})
79-
.expect("Could create watcher");
80-
leaf_deps(&metadata_file, |it| {
81-
let path = it.to_path().unwrap();
82-
if watched_paths.insert(path.to_owned()) {
83-
watcher
84-
.watch(it.to_path().unwrap(), RecursiveMode::NonRecursive)
85-
.expect("Cargo dependencies are valid files");
86-
}
87-
})
88-
.expect("Could read dependencies file");
49+
let mut watcher = Watcher::new();
50+
watcher.watch_leaf_deps(&metadata_file);
51+
8952
loop {
90-
rx.recv().expect("Watcher still alive");
91-
let metadata_result = crate::invoke_rustc(&self);
53+
watcher.recv();
54+
let metadata_result = crate::invoke_rustc(&builder);
9255
if let Ok(file) = metadata_result {
93-
let metadata = self
56+
let metadata = builder
9457
.parse_metadata_file(&file)
9558
.expect("Metadata file is correct");
96-
97-
leaf_deps(&file, |it| {
98-
let path = it.to_path().unwrap();
99-
if watched_paths.insert(path.to_owned()) {
100-
watcher
101-
.watch(it.to_path().unwrap(), RecursiveMode::NonRecursive)
102-
.expect("Cargo dependencies are valid files");
103-
}
104-
})
105-
.expect("Could read dependencies file");
106-
59+
watcher.watch_leaf_deps(&metadata_file);
10760
on_compilation_finishes(metadata);
10861
}
10962
}
11063
});
111-
std::mem::drop(thread);
112-
Ok(first_result)
64+
drop(thread);
65+
Ok(())
66+
}
67+
}
68+
69+
struct Watcher {
70+
watcher: RecommendedWatcher,
71+
rx: Receiver<()>,
72+
watched_paths: HashSet<PathBuf>,
73+
}
74+
75+
impl Watcher {
76+
fn new() -> Self {
77+
let (tx, rx) = sync_channel(0);
78+
let watcher =
79+
notify::recommended_watcher(move |event: notify::Result<Event>| match event {
80+
Ok(e) => match e.kind {
81+
notify::EventKind::Access(_) => (),
82+
notify::EventKind::Any
83+
| notify::EventKind::Create(_)
84+
| notify::EventKind::Modify(_)
85+
| notify::EventKind::Remove(_)
86+
| notify::EventKind::Other => {
87+
let _ = tx.try_send(());
88+
}
89+
},
90+
Err(e) => println!("notify error: {e:?}"),
91+
})
92+
.expect("Could create watcher");
93+
Self {
94+
watcher,
95+
rx,
96+
watched_paths: HashSet::new(),
97+
}
98+
}
99+
100+
fn watch_leaf_deps(&mut self, metadata_file: &Path) {
101+
leaf_deps(metadata_file, |it| {
102+
let path = it.to_path().unwrap();
103+
if self.watched_paths.insert(path.to_owned()) {
104+
self.watcher
105+
.watch(it.to_path().unwrap(), RecursiveMode::NonRecursive)
106+
.expect("Cargo dependencies are valid files");
107+
}
108+
})
109+
.expect("Could read dependencies file");
110+
}
111+
112+
fn recv(&self) {
113+
self.rx.recv().expect("Watcher still alive");
113114
}
114115
}

0 commit comments

Comments
 (0)