Skip to content

Commit 625675f

Browse files
committed
Add option to build rust api without linking to core
1 parent 1b2f5c4 commit 625675f

5 files changed

Lines changed: 66 additions & 10 deletions

File tree

Cargo.lock

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rust/Cargo.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,20 @@ rust-version = "1.83.0"
77
license = "Apache-2.0"
88

99
[features]
10+
default = ["core"]
1011
# This is used when statically linking to prevent exporting CorePluginABIVersion and UiPluginABIVersion.
1112
no_exports = []
1213
# Add this if you want to support the demo version of the product.
1314
# This will disable certain functions that do not exist in the demo build.
1415
demo = ["no_exports"]
16+
# If disabled, a stubbed binaryninjacore library will be generated and linked.
17+
# This feature should only be disabled for shared libraries that will later be loaded in the same process as the real binaryninjacore.
18+
core = ["binaryninjacore-sys/core"]
1519

1620
[dependencies]
1721
log = { version = "0.4", features = ["std"] }
1822
rayon = { version = "1.10", optional = true }
19-
binaryninjacore-sys = { path = "binaryninjacore-sys" }
23+
binaryninjacore-sys = { path = "binaryninjacore-sys", default-features = false}
2024
thiserror = "2.0"
2125
serde = "1.0"
2226
serde_derive = "1.0"

rust/binaryninjacore-sys/Cargo.toml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,15 @@ edition = "2021"
77
links = "binaryninjacore"
88
license = "Apache-2.0"
99

10+
[features]
11+
default = ["core"]
12+
# If disabled, a stubbed binaryninjacore library will be generated and linked.
13+
# This feature should only be disabled for shared libraries that will later be loaded in the same process as the real binaryninjacore.
14+
core = []
15+
1016
[build-dependencies]
1117
bindgen = "0.71.1"
1218
# TODO: Remove this once bindgen correctly pins the version.
1319
# proc-macro2 v1.0.79 does not have https://docs.rs/proc-macro2/1.0.80/proc_macro2/struct.Literal.html#method.c_string
14-
proc-macro2 = ">=1.0.80"
20+
proc-macro2 = ">=1.0.80"
21+
cc = "1.2.31"

rust/binaryninjacore-sys/build.rs

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::fs::File;
33
use std::io::BufRead;
44
use std::io::BufReader;
55
use std::path::PathBuf;
6+
use std::process::Command;
67

78
#[cfg(target_os = "macos")]
89
static LASTRUN_PATH: (&str, &str) = ("HOME", "Library/Application Support/Binary Ninja/lastrun");
@@ -41,16 +42,59 @@ fn link_path() -> PathBuf {
4142
})
4243
}
4344

45+
fn generate_stubs() -> PathBuf {
46+
// Generate and compile stub shared library and return the path
47+
48+
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
49+
50+
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
51+
52+
// To construct paths relative to the manifest directory:
53+
let api_base_path = std::path::PathBuf::from(manifest_dir)
54+
.join("../../")
55+
.canonicalize()
56+
.unwrap();
57+
58+
let generate_stubs_path = api_base_path.join("cmake").join("generate_stubs.py");
59+
let binaryninja_core_header_path = api_base_path.join("binaryninjacore.h");
60+
let stubs_path = out_dir.join("stubs");
61+
62+
let generate_status = Command::new("python")
63+
.args(&[
64+
generate_stubs_path.to_str().unwrap(),
65+
binaryninja_core_header_path.to_str().unwrap(),
66+
stubs_path.to_str().unwrap(),
67+
])
68+
.status()
69+
.expect("Failed to generate stubs");
70+
71+
if !generate_status.success() {
72+
panic!("Failed to generate stubs");
73+
}
74+
75+
cc::Build::new()
76+
.file(stubs_path.join("stubs.cpp")) // This is named .cpp but is actually c
77+
.shared_flag(true)
78+
.include(api_base_path)
79+
.warnings(false)
80+
.compile("binaryninjacore");
81+
82+
out_dir
83+
}
84+
4485
fn main() {
4586
println!("cargo:rerun-if-env-changed=BINARYNINJADIR");
4687
println!("cargo:rerun-if-changed=../../binaryninjacore.h");
4788

4889
//Cargo's output directory
4990
let out_dir = env::var("OUT_DIR").unwrap();
5091

51-
let link_path = env::var("BINARYNINJADIR")
52-
.map(PathBuf::from)
53-
.unwrap_or_else(|_| link_path());
92+
let link_path = match env::var("CARGO_FEATURE_CORE") {
93+
Ok(_) => env::var("BINARYNINJADIR")
94+
.map(PathBuf::from)
95+
.unwrap_or_else(|_| link_path()),
96+
Err(_) => generate_stubs(),
97+
};
5498

5599
// Linux builds of binaryninja ship with libbinaryninjacore.so.1 in the
56100
// application folder and no symlink. The linker will attempt to link with

rust/build.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use std::path::PathBuf;
22

33
fn main() {
4-
let link_path =
5-
std::env::var_os("DEP_BINARYNINJACORE_PATH").expect("DEP_BINARYNINJACORE_PATH specified");
4+
let link_path = std::env::var_os("DEP_BINARYNINJACORE_PATH")
5+
.expect("DEP_BINARYNINJACORE_PATH not specified");
66

77
println!("cargo::rustc-link-lib=dylib=binaryninjacore");
88
println!("cargo::rustc-link-search={}", link_path.to_str().unwrap());
@@ -15,7 +15,7 @@ fn main() {
1515
);
1616
}
1717

18-
let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR specified");
18+
let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not specified");
1919
let out_dir_path = PathBuf::from(out_dir);
2020

2121
// Copy all binaries to OUT_DIR for unit tests.

0 commit comments

Comments
 (0)