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
extern crate bindgen;
use bindgen::callbacks::{DeriveInfo, MacroParsingBehavior, ParseCallbacks};
use cmake::{self, Config};
use std::collections::HashSet;
use std::env;
use std::path::PathBuf;
const IGNORE_MACROS: [&str; 5] = [
"FP_NAN",
"FP_INFINITE",
"FP_NORMAL",
"FP_SUBNORMAL",
"FP_ZERO",
];
const SERDE_TYPES: [&str; 8] = [
// Top-level event types
"dxf_trade_t",
"dxf_quote_t",
"dxf_summary",
// "dxf_profile",
// "dxf_order_t": skipped. anonymous union can't be supportd
// "dxf_time_and_sale". Can't serialize raw C strings
"dxf_candle_t",
// "dxf_trade_eth_t",
// "dx_spread_order",
"dxf_greeks",
"dx_theo_price",
"dxf_underlying",
"dxf_series",
// "dxf_configuration",
];
#[derive(Debug)]
struct CustomParser {
ignore_macros: HashSet<String>,
serde_types: HashSet<String>,
}
impl ParseCallbacks for CustomParser {
fn will_parse_macro(&self, name: &str) -> MacroParsingBehavior {
if self.ignore_macros.contains(name) {
MacroParsingBehavior::Ignore
} else {
MacroParsingBehavior::Default
}
}
fn add_derives(&self, info: &DeriveInfo<'_>) -> Vec<String> {
if self.serde_types.contains(info.name) {
vec!["Serialize".to_string(), "Deserialize".to_string()]
} else {
vec![]
}
}
}
impl CustomParser {
fn new() -> Self {
let ignore_macros = IGNORE_MACROS.iter().map(|s| s.to_string()).collect();
let serde_types = SERDE_TYPES.iter().map(|s| s.to_string()).collect();
Self {
ignore_macros,
serde_types,
}
}
}
fn main() {
// let profile = std::env::var("PROFILE").unwrap();
// let dst = cmake::build("dxfeed-c-api");
let dst = Config::new("dxfeed-c-api")
.define("DISABLE_TLS", "ON")
.define("BUILD_STATIC_LIBS", "ON")
.build();
eprintln!("dst: {}", dst.display());
println!("cargo:rustc-link-search=native={}", dst.display());
println!("cargo:rustc-link-search={}", dst.display());
println!("cargo:rustc-link-lib={}", "DXFeed");
println!("cargo:rustc-link-lib=stdc++");
// println!("cargo:rustc-link-lib=static=DXFeed");
// Tell cargo to look for shared libraries in the specified directory
// println!("cargo:rustc-link-search=dxfeed-c-api/build_{}", profile);
// Tell cargo to tell rustc to link the system dxfeed-c-api static lib
// let suffix = if profile == "debug" { "d" } else { "" };
// println!("cargo:rustc-link-lib=DXFeed{}_64", suffix);
// println!("cargo:rustc-link-lib=stdc++");
// Tell cargo to invalidate the built crate whenever the wrapper changes
println!("cargo:rerun-if-changed=wrapper.h");
// The bindgen::Builder is the main entry point
// to bindgen, and lets you build up options for
// the resulting bindings.
let bindings = bindgen::Builder::default()
// The input header we would like to generate
// bindings for.
.header("wrapper.h")
.blocklist_file(r".*c?math.*")
.blocklist_function("wcstold")
// Tell cargo to invalidate the built crate whenever any of the
// included header files changed.
.parse_callbacks(Box::new(CustomParser::new()))
.derive_partialeq(true)
.rustfmt_bindings(true)
// .parse_callbacks(Box::new(bindgen::CargoCallbacks))
// Finish the builder and generate the bindings.
.generate()
// Unwrap the Result and panic on failure.
.expect("Unable to generate bindings");
// Write the bindings to the $OUT_DIR/bindings.rs file.
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("Couldn't write bindings!");
}