@@ -27,30 +27,12 @@ impl SpirvBuilder {
27
27
. as_ref ( )
28
28
. ok_or ( SpirvBuilderError :: MissingCratePath ) ?;
29
29
if !matches ! ( self . print_metadata, crate :: MetadataPrintout :: None ) {
30
- return Err ( SpirvBuilderError :: WatchWithPrintMetadata ) ;
30
+ return Err ( SpirvBuilderWatchError :: WatchWithPrintMetadata . into ( ) ) ;
31
31
}
32
32
33
- let metadata_result = crate :: invoke_rustc ( self ) ;
34
- // Load the dependencies of the thing
35
- let metadata_file = if let Ok ( path) = metadata_result {
36
- path
37
- } else {
38
- // Fall back to watching from the crate root if the initial compilation fails
39
- // This is likely to notice changes in the `target` dir, however, given that `cargo watch` doesn't seem to handle that,
40
- let mut watcher = Watcher :: new ( ) ;
41
- watcher
42
- . watcher
43
- . watch ( path_to_crate, RecursiveMode :: Recursive )
44
- . expect ( "Could watch crate root" ) ;
45
- loop {
46
- watcher. recv ( ) ;
47
- let metadata_file = crate :: invoke_rustc ( self ) ;
48
- if let Ok ( f) = metadata_file {
49
- break f;
50
- }
51
- }
52
- } ;
33
+ let metadata_file = metadata_file ( path_to_crate, self ) ?;
53
34
let metadata = self . parse_metadata_file ( & metadata_file) ?;
35
+
54
36
let mut first_compile = None ;
55
37
on_compilation_finishes ( metadata, Some ( AcceptFirstCompile ( & mut first_compile) ) ) ;
56
38
@@ -65,7 +47,7 @@ impl SpirvBuilder {
65
47
if let Ok ( file) = metadata_result {
66
48
let metadata = builder
67
49
. parse_metadata_file ( & file)
68
- . expect ( "Metadata file is correct " ) ;
50
+ . expect ( "metadata file should be valid " ) ;
69
51
watcher. watch_leaf_deps ( & metadata_file) ;
70
52
on_compilation_finishes ( metadata, None ) ;
71
53
}
@@ -79,6 +61,52 @@ impl SpirvBuilder {
79
61
}
80
62
}
81
63
64
+ fn notify_channel ( ) -> Result < ( RecommendedWatcher , Receiver < ( ) > ) , SpirvBuilderWatchError > {
65
+ let ( tx, rx) = sync_channel ( 0 ) ;
66
+ let event_handler = move |result : notify:: Result < Event > | match result {
67
+ Ok ( event) => match event. kind {
68
+ notify:: EventKind :: Any
69
+ | notify:: EventKind :: Create ( _)
70
+ | notify:: EventKind :: Modify ( _)
71
+ | notify:: EventKind :: Remove ( _)
72
+ | notify:: EventKind :: Other => {
73
+ if let Err ( err) = tx. try_send ( ( ) ) {
74
+ log:: error!( "send error: {err:?}" ) ;
75
+ }
76
+ }
77
+ notify:: EventKind :: Access ( _) => { }
78
+ } ,
79
+ Err ( err) => log:: error!( "notify error: {err:?}" ) ,
80
+ } ;
81
+ let watcher = notify:: recommended_watcher ( event_handler) ?;
82
+ Ok ( ( watcher, rx) )
83
+ }
84
+
85
+ fn metadata_file < P > (
86
+ crate_path : P ,
87
+ builder : & SpirvBuilder ,
88
+ ) -> Result < PathBuf , SpirvBuilderWatchError >
89
+ where
90
+ P : AsRef < Path > ,
91
+ {
92
+ match crate :: invoke_rustc ( builder) {
93
+ Ok ( path) => return Ok ( path) ,
94
+ Err ( err) => log:: error!( "{err}" ) ,
95
+ }
96
+
97
+ // Fall back to watching from the crate root if the initial compilation fails
98
+ // This is likely to notice changes in the `target` dir, however, given that `cargo watch` doesn't seem to handle that,
99
+ let ( mut watcher, rx) = notify_channel ( ) . expect ( "should be able to create notify channel" ) ;
100
+ watcher. watch ( crate_path. as_ref ( ) , RecursiveMode :: Recursive ) ?;
101
+ loop {
102
+ rx. recv ( ) . expect ( "watcher should be alive" ) ;
103
+ match crate :: invoke_rustc ( builder) {
104
+ Ok ( path) => break Ok ( path) ,
105
+ Err ( err) => log:: error!( "{err}" ) ,
106
+ }
107
+ }
108
+ }
109
+
82
110
pub struct AcceptFirstCompile < ' a , T > ( & ' a mut Option < T > ) ;
83
111
84
112
impl < ' a , T > AcceptFirstCompile < ' a , T > {
@@ -112,22 +140,7 @@ struct Watcher {
112
140
113
141
impl Watcher {
114
142
fn new ( ) -> Self {
115
- let ( tx, rx) = sync_channel ( 0 ) ;
116
- let watcher =
117
- notify:: recommended_watcher ( move |event : notify:: Result < Event > | match event {
118
- Ok ( e) => match e. kind {
119
- notify:: EventKind :: Access ( _) => ( ) ,
120
- notify:: EventKind :: Any
121
- | notify:: EventKind :: Create ( _)
122
- | notify:: EventKind :: Modify ( _)
123
- | notify:: EventKind :: Remove ( _)
124
- | notify:: EventKind :: Other => {
125
- let _ = tx. try_send ( ( ) ) ;
126
- }
127
- } ,
128
- Err ( e) => println ! ( "notify error: {e:?}" ) ,
129
- } )
130
- . expect ( "Could create watcher" ) ;
143
+ let ( watcher, rx) = notify_channel ( ) . expect ( "should be able to create notify channel" ) ;
131
144
Self {
132
145
watcher,
133
146
rx,
@@ -141,13 +154,21 @@ impl Watcher {
141
154
if self . watched_paths . insert ( path. to_owned ( ) ) {
142
155
self . watcher
143
156
. watch ( it. to_path ( ) . unwrap ( ) , RecursiveMode :: NonRecursive )
144
- . expect ( "Cargo dependencies are valid files " ) ;
157
+ . expect ( "files of cargo dependencies should be valid " ) ;
145
158
}
146
159
} )
147
- . expect ( "Could read dependencies file" ) ;
160
+ . expect ( "should be able to read dependencies file" ) ;
148
161
}
149
162
150
163
fn recv ( & self ) {
151
- self . rx . recv ( ) . expect ( "Watcher still alive" ) ;
164
+ self . rx . recv ( ) . expect ( "watcher should be alive" ) ;
152
165
}
153
166
}
167
+
168
+ #[ derive( Debug , thiserror:: Error ) ]
169
+ pub enum SpirvBuilderWatchError {
170
+ #[ error( "watching within build scripts will prevent build completion" ) ]
171
+ WatchWithPrintMetadata ,
172
+ #[ error( "could not notify for changes: {0}" ) ]
173
+ NotifyFailed ( #[ from] notify:: Error ) ,
174
+ }
0 commit comments