@@ -123,12 +123,23 @@ pub fn dynamic_lib_name(name: &str) -> String {
123
123
// ```
124
124
assert ! ( !name. contains( char :: is_whitespace) , "dynamic library name cannot contain whitespace" ) ;
125
125
126
+ let extension = dynamic_lib_extension ( ) ;
126
127
if is_darwin ( ) {
127
- format ! ( "lib{name}.dylib " )
128
+ format ! ( "lib{name}.{extension} " )
128
129
} else if is_windows ( ) {
129
- format ! ( "{name}.dll " )
130
+ format ! ( "{name}.{extension} " )
130
131
} else {
131
- format ! ( "lib{name}.so" )
132
+ format ! ( "lib{name}.{extension}" )
133
+ }
134
+ }
135
+
136
+ pub fn dynamic_lib_extension ( ) -> & ' static str {
137
+ if is_darwin ( ) {
138
+ "dylib"
139
+ } else if is_windows ( ) {
140
+ "dll"
141
+ } else {
142
+ "so"
132
143
}
133
144
}
134
145
@@ -149,6 +160,50 @@ pub fn bin_name(name: &str) -> String {
149
160
if is_windows ( ) { format ! ( "{name}.exe" ) } else { name. to_string ( ) }
150
161
}
151
162
163
+ fn ar < P : AsRef < str > , P2 : AsRef < str > > ( obj_path : P , lib_path : P2 , caller_line_number : u32 ) {
164
+ let mut ar = Command :: new ( env:: var ( "AR" ) . unwrap ( ) ) ;
165
+ ar. current_dir ( tmp_dir ( ) ) . arg ( "crus" ) . arg ( lib_path. as_ref ( ) ) . arg ( obj_path. as_ref ( ) ) ;
166
+ let output = ar. output ( ) . unwrap ( ) ;
167
+ if !output. status . success ( ) {
168
+ handle_failed_output ( & ar, output, caller_line_number) ;
169
+ }
170
+ }
171
+
172
+ /// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
173
+ #[ track_caller]
174
+ pub fn build_native_static_lib ( lib_name : & str ) -> PathBuf {
175
+ let caller_location = std:: panic:: Location :: caller ( ) ;
176
+ let caller_line_number = caller_location. line ( ) ;
177
+
178
+ let obj_file = format ! ( "{lib_name}.o" ) ;
179
+ let src = format ! ( "{lib_name}.c" ) ;
180
+ let lib_name = if is_msvc ( ) {
181
+ let lib_path = format ! ( "lib{lib_name}.lib" ) ;
182
+ // First compiling `.c` to `.o`.
183
+ cc ( ) . arg ( "-c" ) . out_exe ( lib_name) . input ( src) . run ( ) ;
184
+ // Generating `.lib` from `.o`.
185
+ let mut msvc_lib = Command :: new ( env:: var ( "MSVC_LIB_PATH" ) . unwrap ( ) ) ;
186
+ msvc_lib
187
+ . current_dir ( tmp_dir ( ) )
188
+ . arg ( "-nologo" )
189
+ . arg ( & format ! ( "-out:{}" , cygpath_windows( & lib_path) ) )
190
+ . arg ( & obj_file) ;
191
+ let output = msvc_lib. output ( ) . unwrap ( ) ;
192
+ if !output. status . success ( ) {
193
+ handle_failed_output ( & msvc_lib, output, caller_line_number) ;
194
+ }
195
+ lib_path
196
+ } else {
197
+ let lib_path = format ! ( "lib{lib_name}.a" ) ;
198
+ // First compiling `.c` to `.o`.
199
+ cc ( ) . arg ( "-v" ) . arg ( "-c" ) . out_exe ( & obj_file) . input ( src) . run ( ) ;
200
+ // Generating `.a` from `.o`.
201
+ ar ( obj_file, & lib_path, caller_line_number) ;
202
+ lib_path
203
+ } ;
204
+ tmp_dir ( ) . join ( lib_name)
205
+ }
206
+
152
207
/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
153
208
/// available on the platform!
154
209
#[ track_caller]
@@ -249,16 +304,13 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
249
304
}
250
305
251
306
let dir2 = dir2. as_ref ( ) ;
252
- for entry in fs:: read_dir ( dir1) . unwrap ( ) {
253
- let entry = entry. unwrap ( ) ;
254
- let entry_name = entry. file_name ( ) ;
255
- let path = entry. path ( ) ;
256
-
257
- if path. is_dir ( ) {
258
- recursive_diff ( & path, & dir2. join ( entry_name) ) ;
307
+ read_dir ( dir1, |entry_path| {
308
+ let entry_name = entry_path. file_name ( ) . unwrap ( ) ;
309
+ if entry_path. is_dir ( ) {
310
+ recursive_diff ( & entry_path, & dir2. join ( entry_name) ) ;
259
311
} else {
260
312
let path2 = dir2. join ( entry_name) ;
261
- let file1 = read_file ( & path ) ;
313
+ let file1 = read_file ( & entry_path ) ;
262
314
let file2 = read_file ( & path2) ;
263
315
264
316
// We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
@@ -267,10 +319,16 @@ pub fn recursive_diff(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
267
319
assert ! (
268
320
file1 == file2,
269
321
"`{}` and `{}` have different content" ,
270
- path . display( ) ,
322
+ entry_path . display( ) ,
271
323
path2. display( ) ,
272
324
) ;
273
325
}
326
+ } ) ;
327
+ }
328
+
329
+ pub fn read_dir < F : Fn ( & Path ) > ( dir : impl AsRef < Path > , callback : F ) {
330
+ for entry in fs:: read_dir ( dir) . unwrap ( ) {
331
+ callback ( & entry. unwrap ( ) . path ( ) ) ;
274
332
}
275
333
}
276
334
0 commit comments