1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
|
use std::env;
use std::fs::{self, OpenOptions};
use std::io::Write;
use std::path::PathBuf;
use bindgen::EnumVariation;
#[cfg(unix)]
use std::os::unix::fs as unix_fs;
#[cfg(target_os = "windows")]
use std::fs::copy;
fn main() {
let header_path = "../../monero_libwallet2_api_c/src/main/cpp/wallet2_api_c.h";
let lib_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("../../release");
// Set library names based on target OS.
//
// This rigamarole is currently required because the "monero_libwallet2_api_c" library is also
// required under the names "wallet2_api_c" and "libmonero_libwallet2_api_c" by various parts of
// the stack. This is a temporary workaround until the library is refactored to use a single
// name consistently.
let original_lib = if cfg!(target_os = "windows") {
lib_path.join("monero_libwallet2_api_c.dll")
} else if cfg!(target_os = "macos") {
lib_path.join("monero_libwallet2_api_c.dylib")
} else {
lib_path.join("monero_libwallet2_api_c.so")
};
let symlink_1 = if cfg!(target_os = "windows") {
lib_path.join("wallet2_api_c.dll")
} else if cfg!(target_os = "macos") {
lib_path.join("libwallet2_api_c.dylib")
} else {
lib_path.join("libwallet2_api_c.so")
};
let symlink_2 = if cfg!(target_os = "windows") {
lib_path.join("monero_wallet2_api_c.dll")
} else if cfg!(target_os = "macos") {
lib_path.join("libmonero_libwallet2_api_c.dylib")
} else {
lib_path.join("libmonero_libwallet2_api_c.so")
};
// On Unix-like systems, create symlinks.
#[cfg(unix)]
{
if original_lib.exists() && !symlink_1.exists() {
unix_fs::symlink(&original_lib, &symlink_1)
.expect("Failed to create symbolic link for libwallet2_api_c.so");
}
if original_lib.exists() && !symlink_2.exists() {
unix_fs::symlink(&original_lib, &symlink_2)
.expect("Failed to create symbolic link for libmonero_libwallet2_api_c.so");
}
}
// On Windows, copy the files instead of symlinking.
#[cfg(target_os = "windows")]
{
if original_lib.exists() && !symlink_1.exists() {
copy(&original_lib, &symlink_1).expect("Failed to copy DLL file to wallet2_api_c.dll");
}
if original_lib.exists() && !symlink_2.exists() {
copy(&original_lib, &symlink_2)
.expect("Failed to copy DLL file to monero_wallet2_api_c.dll");
}
}
println!("cargo:rerun-if-changed={}", header_path);
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rustc-link-search=native={}", lib_path.display());
println!("cargo:rustc-link-lib=dylib=monero_libwallet2_api_c");
println!("cargo:rustc-link-lib=dylib=stdc++");
println!("cargo:rustc-link-lib=dylib=hidapi-hidraw");
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_path.display());
// Generate bindings using bindgen.
let bindings = bindgen::Builder::default()
.header(header_path)
.allowlist_function("MONERO_.*")
.allowlist_var("MONERO_.*")
.allowlist_var("NetworkType_.*")
.allowlist_var("PendingTransactionStatus_.*")
.allowlist_var("Priority_.*")
.allowlist_var("UnsignedTransactionStatus_.*")
.allowlist_var("TransactionInfoDirection_.*")
.allowlist_var("AddressBookErrorCode.*")
.allowlist_var("WalletDevice_.*")
.allowlist_var("WalletStatus_.*")
.allowlist_var("WalletConnectionStatus_.*")
.allowlist_var("WalletBackgroundSync_.*")
.allowlist_var("BackgroundSync_.*")
.allowlist_var("LogLevel_.*")
.blocklist_type("__.*")
.blocklist_type("_.*")
.blocklist_function("__.*")
.layout_tests(false)
.default_enum_style(EnumVariation::Rust { non_exhaustive: false })
.derive_default(false)
.conservative_inline_namespaces()
.generate_comments(false)
.generate()
.expect("Unable to generate bindings");
let out_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
.join("src")
.join("bindings.rs");
bindings
.write_to_file(out_path.clone())
.expect("Couldn't write bindings!");
// Annotate the generated bindings to ignore certain warnings.
if out_path.exists() {
let contents = fs::read_to_string(out_path.clone()).expect("Failed to read bindings.rs");
let prepend_content = "#![allow(non_upper_case_globals)]\n#![allow(dead_code)]\n";
if !contents.contains("#![allow(non_upper_case_globals)]") {
let new_contents = format!("{}{}", prepend_content, contents);
let mut file = OpenOptions::new()
.write(true)
.truncate(true)
.open(out_path.clone())
.expect("Failed to open bindings.rs");
file.write_all(new_contents.as_bytes()).expect("Failed to write to bindings.rs");
}
}
}
|