1
- use std:: env;
1
+ use bindgen:: builder;
2
+ use git2:: Repository ;
3
+ use std:: {
4
+ env, fs, io,
5
+ path:: { Path , PathBuf } ,
6
+ } ;
7
+
8
+ const METACALL_CORE_REPO : & str = "https://github.com/metacall/core.git#v0.7.3" ;
9
+
10
+ pub fn copy_recursively ( source : impl AsRef < Path > , destination : impl AsRef < Path > ) -> io:: Result < ( ) > {
11
+ fs:: create_dir_all ( & destination) ?;
12
+ for entry in fs:: read_dir ( source) ? {
13
+ let entry = entry?;
14
+ let filetype = entry. file_type ( ) ?;
15
+
16
+ if filetype. is_dir ( ) {
17
+ copy_recursively ( entry. path ( ) , destination. as_ref ( ) . join ( entry. file_name ( ) ) ) ?;
18
+ } else {
19
+ fs:: copy ( entry. path ( ) , destination. as_ref ( ) . join ( entry. file_name ( ) ) ) ?;
20
+ }
21
+ }
22
+ Ok ( ( ) )
23
+ }
24
+ fn get_bindings_dir ( ) -> PathBuf {
25
+ let out_dir = PathBuf :: from ( env:: var ( "OUT_DIR" ) . unwrap ( ) ) ;
26
+ let bindings_dir = out_dir. join ( "bindings" ) ;
27
+
28
+ fs:: create_dir_all ( & bindings_dir) . unwrap ( ) ;
29
+
30
+ bindings_dir. canonicalize ( ) . unwrap ( )
31
+ }
32
+ fn download_the_headers < T : ToString > ( bindings_dir : & PathBuf , headers : & [ T ] ) {
33
+ let mut need_for_clone = false ;
34
+ let bindings_str = bindings_dir. to_str ( ) . unwrap ( ) ;
35
+
36
+ for header in headers {
37
+ let path = PathBuf :: from ( format ! ( "{}/{}" , bindings_str, header. to_string( ) ) ) ;
38
+ if !path. exists ( ) && !need_for_clone {
39
+ need_for_clone = true ;
40
+ }
41
+ }
42
+
43
+ if need_for_clone {
44
+ let temp_dir = tempfile:: tempdir ( ) . unwrap ( ) ;
45
+ Repository :: clone ( METACALL_CORE_REPO , & temp_dir) . unwrap ( ) ;
46
+
47
+ let tmp_dir = temp_dir. path ( ) . to_str ( ) . unwrap ( ) ;
48
+ let source = format ! ( "{}/source/metacall" , tmp_dir) ;
49
+ let destination = bindings_dir. join ( "metacall" ) ;
50
+ copy_recursively ( source, destination) . unwrap ( ) ;
51
+ }
52
+ }
53
+ fn generate_bindings < T : ToString > ( bindings_dir : & PathBuf , headers : & [ T ] ) {
54
+ let bindings_dir_str = bindings_dir. to_str ( ) . unwrap ( ) ;
55
+ let mut builder = builder ( ) ;
56
+
57
+ for header in headers {
58
+ builder = builder. header ( format ! ( "{}/{}" , bindings_dir_str, header. to_string( ) ) ) ;
59
+ }
60
+
61
+ builder = builder
62
+ . detect_include_paths ( true )
63
+ . size_t_is_usize ( true )
64
+ . rustfmt_bindings ( true )
65
+ . generate_comments ( true )
66
+ . derive_hash ( true ) ;
67
+ let bindings = builder. generate ( ) . unwrap ( ) ;
68
+
69
+ bindings
70
+ . write_to_file ( bindings_dir. join ( "bindings.rs" ) )
71
+ . unwrap ( ) ;
72
+ }
73
+
2
74
fn main ( ) {
75
+ const HEADERS : [ & str ; 3 ] = [
76
+ "metacall/include/metacall/metacall.h" ,
77
+ "metacall/include/metacall/metacall_value.h" ,
78
+ "metacall/include/metacall/metacall_error.h" ,
79
+ ] ;
80
+ let bindings_dir = get_bindings_dir ( ) ;
81
+
82
+ download_the_headers ( & bindings_dir, & HEADERS ) ;
83
+ generate_bindings ( & bindings_dir, & HEADERS ) ;
84
+
85
+ for header in HEADERS {
86
+ println ! (
87
+ "{}" ,
88
+ format!(
89
+ "cargo:rerun-if-changed={}/{}" ,
90
+ bindings_dir. to_str( ) . unwrap( ) ,
91
+ header
92
+ )
93
+ ) ;
94
+ }
95
+
3
96
// when running tests
4
97
if let Ok ( val) = env:: var ( "CMAKE_BINARY_DIR" ) {
5
98
println ! ( "cargo:rustc-link-search={val}" ) ;
@@ -23,8 +116,4 @@ fn main() {
23
116
} else {
24
117
println ! ( "cargo:rustc-link-lib=metacall" ) ;
25
118
}
26
-
27
- // default install location
28
-
29
- // user defined location
30
119
}
0 commit comments