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
// build.rs — OverDrive InCode SDK (Rust)
//
// This build script:
// 1. Emits linker search paths so the native library is found at link time
// when building from source (not needed for crates.io users).
// 2. Copies the native library from lib/ to the output directory so it is
// found at runtime next to the compiled binary.
// 3. Emits cargo:rustc-link-search so `cargo test` and `cargo run` work
// without manual PATH setup.
use std::env;
use std::path::{Path, PathBuf};
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=lib/");
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap_or_default();
let lib_dir = Path::new(&manifest_dir).join("lib");
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap_or_default());
// Determine the native library name for this platform
let (lib_file, link_name) = if cfg!(target_os = "windows") {
("overdrive.dll", "overdrive")
} else if cfg!(target_os = "macos") {
("liboverdrive.dylib", "overdrive")
} else {
("liboverdrive.so", "overdrive")
};
// If lib/ directory exists and contains the native library, emit linker paths
let lib_path = lib_dir.join(lib_file);
if lib_dir.exists() {
println!("cargo:rustc-link-search=native={}", lib_dir.display());
println!("cargo:rustc-link-lib=dylib={}", link_name);
}
// Copy the native library to the output directory so it's found at runtime
// This helps `cargo run` and `cargo test` work without manual setup
if lib_path.exists() {
// Copy to OUT_DIR/../../../ (the target/debug or target/release directory)
// Walk up from OUT_DIR (which is target/{profile}/build/{pkg}/out)
let mut target_dir = out_dir.clone();
for _ in 0..3 {
target_dir = match target_dir.parent() {
Some(p) => p.to_path_buf(),
None => break,
};
}
let dest = target_dir.join(lib_file);
if !dest.exists() {
if let Err(e) = std::fs::copy(&lib_path, &dest) {
eprintln!(
"cargo:warning=Could not copy {} to {}: {}",
lib_path.display(),
dest.display(),
e
);
} else {
eprintln!(
"cargo:warning=Copied {} to {}",
lib_file,
dest.display()
);
}
}
} else {
// Native library not found in lib/ — emit a helpful warning
eprintln!(
"cargo:warning=OverDrive native library not found at {}",
lib_path.display()
);
eprintln!(
"cargo:warning=Download {} from: https://github.com/ALL-FOR-ONE-TECH/OverDrive-DB_IncodeSDK/releases/latest",
lib_file
);
eprintln!(
"cargo:warning=Place it in the lib/ directory next to Cargo.toml"
);
}
// cbindgen — generate C header from Rust FFI (optional, only if cbindgen is available)
#[cfg(feature = "generate-header")]
{
let crate_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
cbindgen::Builder::new()
.with_crate(crate_dir)
.with_config(cbindgen::Config::from_file("cbindgen.toml").unwrap_or_default())
.generate()
.expect("Unable to generate C bindings")
.write_to_file("c/include/overdrive.h");
}
}