#[cfg(feature = "ffi")]
use std::env;
#[allow(
clippy::expect_used,
reason = "Build script may panic on misconfiguration"
)]
#[allow(
unused_assignments,
reason = "Conditional compilation creates unused assignments"
)]
#[allow(unused_mut)]
fn main() {
if std::env::var("DOCS_RS").is_ok() {
println!("cargo:warning=Running in docs.rs environment, skipping file generation");
return;
}
println!("cargo:rerun-if-env-changed=HIGH_PRECISION");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_HIGH_PRECISION");
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=cbindgen.toml");
println!("cargo:rerun-if-changed=cbindgen_cython.toml");
println!("cargo:rerun-if-changed=../Cargo.toml");
#[cfg(feature = "ffi")]
if env::var("CARGO_FEATURE_FFI").is_ok() {
extern crate cbindgen;
use std::{
fs::File,
io::{Read, Write},
path::PathBuf,
};
let crate_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
let mut config_c = cbindgen::Config::from_file("cbindgen.toml")
.expect("unable to find cbindgen.toml configuration file");
let high_precision_c = env::var("HIGH_PRECISION").map_or_else(
|_| {
#[cfg(feature = "high-precision")]
{
true
}
#[cfg(not(feature = "high-precision"))]
{
false
}
},
|v| v.to_lowercase() == "true" || v == "1",
);
if high_precision_c && let Some(mut includes) = config_c.after_includes {
includes.insert_str(0, "\n#define HIGH_PRECISION\n");
config_c.after_includes = Some(includes);
}
let c_header_path = crate_dir.join("../../nautilus_trader/core/includes/model.h");
cbindgen::generate_with_config(&crate_dir, config_c)
.expect("unable to generate bindings")
.write_to_file(&c_header_path);
let mut config_cython = cbindgen::Config::from_file("cbindgen_cython.toml")
.expect("unable to find cbindgen_cython.toml configuration file");
let high_precision = env::var("HIGH_PRECISION").map_or_else(
|_| {
#[cfg(feature = "high-precision")]
{
true
}
#[cfg(not(feature = "high-precision"))]
{
false
}
},
|v| v.to_lowercase() == "true" || v == "1",
);
let flag = if high_precision {
Some("\nDEF HIGH_PRECISION = True # or False".to_string())
} else {
Some("\nDEF HIGH_PRECISION = False # or True".to_string())
};
config_cython.after_includes = flag;
let cython_path = crate_dir.join("../../nautilus_trader/core/rust/model.pxd");
cbindgen::generate_with_config(&crate_dir, config_cython)
.expect("unable to generate bindings")
.write_to_file(cython_path.clone());
let mut src = File::open(cython_path.clone()).expect("`File::open` failed");
let mut data = String::new();
src.read_to_string(&mut data)
.expect("invalid UTF-8 in stream");
let mut data = data.replace("cdef enum", "cpdef enum");
{
let lines: Vec<&str> = data.lines().collect();
let mut output = String::new();
let mut found_extern = false;
for line in lines {
output.push_str(line);
output.push('\n');
if !found_extern && line.trim().starts_with("cdef extern from") {
output.push_str(" ctypedef unsigned long long uint128_t\n");
output.push_str(" ctypedef long long int128_t\n");
found_extern = true;
}
}
data = output;
}
let mut dst = File::create(cython_path).expect("`File::create` failed");
dst.write_all(data.as_bytes())
.expect("I/O error on `dist.write`");
}
}