1
+ use crate :: helpers;
2
+
1
3
use super :: build_types:: { BuildState , CompilerInfo } ;
2
4
use super :: clean;
3
5
use super :: packages;
@@ -12,23 +14,23 @@ use std::io::Write;
12
14
// If something is not there, that is fine, we will treat it as a mismatch
13
15
#[ derive( Serialize , Deserialize ) ]
14
16
struct CompilerInfoFile {
15
- #[ serde( skip_serializing_if = "Option::is_none" ) ]
16
- version : Option < String > ,
17
- #[ serde( skip_serializing_if = "Option::is_none" ) ]
18
- bsc_path : Option < String > ,
19
- #[ serde( skip_serializing_if = "Option::is_none" ) ]
20
- bsc_hash : Option < String > ,
21
- #[ serde( skip_serializing_if = "Option::is_none" ) ]
22
- runtime_path : Option < String > ,
23
- #[ serde( skip_serializing_if = "Option::is_none" ) ]
24
- generated_at : Option < String > ,
17
+ version : String ,
18
+ bsc_path : String ,
19
+ bsc_hash : String ,
20
+ rescript_config_hash : String ,
21
+ runtime_path : String ,
22
+ generated_at : String ,
25
23
}
26
24
27
25
pub enum CompilerCheckResult {
28
26
SameCompilerAsLastRun ,
29
27
CleanedPackagesDueToCompiler ,
30
28
}
31
29
30
+ fn get_rescript_config_hash ( package : & packages:: Package ) -> Option < String > {
31
+ helpers:: compute_file_hash ( & package. config . path ) . map ( |hash| hash. to_hex ( ) . to_string ( ) )
32
+ }
33
+
32
34
pub fn verify_compiler_info (
33
35
packages : & AHashMap < String , packages:: Package > ,
34
36
compiler : & CompilerInfo ,
@@ -51,35 +53,48 @@ pub fn verify_compiler_info(
51
53
let current_bsc_path_str = compiler. bsc_path . to_string_lossy ( ) ;
52
54
let current_bsc_hash_hex = compiler. bsc_hash . to_hex ( ) . to_string ( ) ;
53
55
let current_runtime_path_str = compiler. runtime_path . to_string_lossy ( ) ;
56
+ let current_rescript_config_hash = match get_rescript_config_hash ( package) {
57
+ Some ( hash) => hash,
58
+ None => return true , // can't compute hash -> treat as mismatch
59
+ } ;
54
60
55
61
let mut mismatch = false ;
56
- if parsed. bsc_path . as_deref ( ) != Some ( & current_bsc_path_str) {
62
+ if parsed. bsc_path != current_bsc_path_str {
57
63
log:: debug!(
58
64
"compiler-info mismatch for {}: bsc_path changed (stored='{}', current='{}')" ,
59
65
package. name,
60
- parsed. bsc_path. as_deref ( ) . unwrap_or ( "<missing>" ) ,
66
+ parsed. bsc_path,
61
67
current_bsc_path_str
62
68
) ;
63
69
mismatch = true ;
64
70
}
65
- if parsed. bsc_hash . as_deref ( ) != Some ( & current_bsc_hash_hex) {
71
+ if parsed. bsc_hash != current_bsc_hash_hex {
66
72
log:: debug!(
67
73
"compiler-info mismatch for {}: bsc_hash changed (stored='{}', current='{}')" ,
68
74
package. name,
69
- parsed. bsc_hash. as_deref ( ) . unwrap_or ( "<missing>" ) ,
75
+ parsed. bsc_hash,
70
76
current_bsc_hash_hex
71
77
) ;
72
78
mismatch = true ;
73
79
}
74
- if parsed. runtime_path . as_deref ( ) != Some ( & current_runtime_path_str) {
80
+ if parsed. runtime_path != current_runtime_path_str {
75
81
log:: debug!(
76
82
"compiler-info mismatch for {}: runtime_path changed (stored='{}', current='{}')" ,
77
83
package. name,
78
- parsed. runtime_path. as_deref ( ) . unwrap_or ( "<missing>" ) ,
84
+ parsed. runtime_path,
79
85
current_runtime_path_str
80
86
) ;
81
87
mismatch = true ;
82
88
}
89
+ if parsed. rescript_config_hash != current_rescript_config_hash {
90
+ log:: debug!(
91
+ "compiler-info mismatch for {}: rescript_config_hash changed (stored='{}', current='{}')" ,
92
+ package. name,
93
+ parsed. rescript_config_hash,
94
+ current_rescript_config_hash
95
+ ) ;
96
+ mismatch = true ;
97
+ }
83
98
84
99
mismatch
85
100
} )
@@ -98,46 +113,58 @@ pub fn verify_compiler_info(
98
113
}
99
114
100
115
pub fn write_compiler_info ( build_state : & BuildState ) {
101
- let bsc_path_str = build_state. compiler_info . bsc_path . to_string_lossy ( ) . to_string ( ) ;
102
- let bsc_hash_hex = build_state. compiler_info . bsc_hash . to_hex ( ) . to_string ( ) ;
103
- let runtime_path_str = build_state
116
+ let bsc_path = build_state. compiler_info . bsc_path . to_string_lossy ( ) . to_string ( ) ;
117
+ let bsc_hash = build_state. compiler_info . bsc_hash . to_hex ( ) . to_string ( ) ;
118
+ let runtime_path = build_state
104
119
. compiler_info
105
120
. runtime_path
106
121
. to_string_lossy ( )
107
122
. to_string ( ) ;
108
-
109
123
// derive version from the crate version
110
124
let version = env ! ( "CARGO_PKG_VERSION" ) . to_string ( ) ;
111
125
let generated_at = crate :: helpers:: get_system_time ( ) . to_string ( ) ;
112
126
113
- let out = CompilerInfoFile {
114
- version : Some ( version) ,
115
- bsc_path : Some ( bsc_path_str) ,
116
- bsc_hash : Some ( bsc_hash_hex) ,
117
- runtime_path : Some ( runtime_path_str) ,
118
- generated_at : Some ( generated_at) ,
119
- } ;
120
- let contents = serde_json:: to_string_pretty ( & out) . unwrap_or_else ( |_| String :: new ( ) ) ;
127
+ // Borrowing serializer to avoid cloning the constant fields for every package
128
+ #[ derive( Serialize ) ]
129
+ struct CompilerInfoFileRef < ' a > {
130
+ version : & ' a str ,
131
+ bsc_path : & ' a str ,
132
+ bsc_hash : & ' a str ,
133
+ rescript_config_hash : String ,
134
+ runtime_path : & ' a str ,
135
+ generated_at : & ' a str ,
136
+ }
121
137
122
138
build_state. packages . values ( ) . par_bridge ( ) . for_each ( |package| {
123
- let info_path = package. get_compiler_info_path ( ) ;
124
- let should_write = match std:: fs:: read_to_string ( & info_path) {
125
- Ok ( existing) => existing != contents,
126
- Err ( _) => true ,
127
- } ;
139
+ if let Some ( rescript_config_hash) = helpers:: compute_file_hash ( & package. config . path ) {
140
+ let out = CompilerInfoFileRef {
141
+ version : & version,
142
+ bsc_path : & bsc_path,
143
+ bsc_hash : & bsc_hash,
144
+ rescript_config_hash : rescript_config_hash. to_hex ( ) . to_string ( ) ,
145
+ runtime_path : & runtime_path,
146
+ generated_at : & generated_at,
147
+ } ;
148
+ let contents = serde_json:: to_string_pretty ( & out) . unwrap_or_else ( |_| String :: new ( ) ) ;
149
+ let info_path = package. get_compiler_info_path ( ) ;
150
+ let should_write = match std:: fs:: read_to_string ( & info_path) {
151
+ Ok ( existing) => existing != contents,
152
+ Err ( _) => true ,
153
+ } ;
128
154
129
- if should_write {
130
- if let Some ( parent) = info_path. parent ( ) {
131
- let _ = std:: fs:: create_dir_all ( parent) ;
132
- }
133
- // We write atomically to avoid leaving a partially written JSON file
134
- // (e.g. process interruption) that would be read on the next init as an
135
- // invalid/mismatched compiler-info, causing unnecessary cleans. The
136
- // rename within the same directory is atomic on common platforms.
137
- let tmp = info_path. with_extension ( "json.tmp" ) ;
138
- if let Ok ( mut f) = File :: create ( & tmp) {
139
- let _ = f. write_all ( contents. as_bytes ( ) ) ;
140
- let _ = std:: fs:: rename ( & tmp, & info_path) ;
155
+ if should_write {
156
+ if let Some ( parent) = info_path. parent ( ) {
157
+ let _ = std:: fs:: create_dir_all ( parent) ;
158
+ }
159
+ // We write atomically to avoid leaving a partially written JSON file
160
+ // (e.g. process interruption) that would be read on the next init as an
161
+ // invalid/mismatched compiler-info, causing unnecessary cleans. The
162
+ // rename within the same directory is atomic on common platforms.
163
+ let tmp = info_path. with_extension ( "json.tmp" ) ;
164
+ if let Ok ( mut f) = File :: create ( & tmp) {
165
+ let _ = f. write_all ( contents. as_bytes ( ) ) ;
166
+ let _ = std:: fs:: rename ( & tmp, & info_path) ;
167
+ }
141
168
}
142
169
}
143
170
} ) ;
0 commit comments