diff options
| -rw-r--r-- | CMakeLists.txt | 29 | ||||
| -rw-r--r-- | Cargo.lock | 14 | ||||
| -rw-r--r-- | rust/Cargo.toml | 6 | ||||
| -rw-r--r-- | rust/binaryninjacore-sys/Cargo.toml | 9 | ||||
| -rw-r--r-- | rust/binaryninjacore-sys/build.rs | 25 | ||||
| -rw-r--r-- | rust/build.rs | 6 | ||||
| -rw-r--r-- | stubs/CMakeLists.txt | 36 | ||||
| -rw-r--r-- | stubs/generate_stubs.py (renamed from cmake/generate_stubs.py) | 0 |
8 files changed, 95 insertions, 30 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 904fcf4f..3a28b964 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,33 +39,22 @@ if(BinaryNinjaCore_FOUND) target_link_directories(binaryninjaapi PUBLIC ${BinaryNinjaCore_LIBRARY_DIRS}) target_compile_definitions(binaryninjaapi PUBLIC ${BinaryNinjaCore_DEFINITIONS}) else() + add_subdirectory(stubs EXCLUDE_FROM_ALL) + + # Be sure to only link against the stubs archive file + add_dependencies(binaryninjaapi binaryninjacore_stubs) + if(APPLE) - target_link_options(binaryninjaapi PUBLIC -undefined dynamic_lookup) + target_link_libraries(binaryninjaapi PUBLIC "$<TARGET_PROPERTY:binaryninjacore_stubs,ARCHIVE_OUTPUT_DIRECTORY>/$<TARGET_PROPERTY:binaryninjacore_stubs,OUTPUT_NAME>.dylib") elseif(MSVC) - # Generate stubs.cpp with implementations of all the BNAPI functions - execute_process(COMMAND python ${PROJECT_SOURCE_DIR}/cmake/generate_stubs.py ${PROJECT_SOURCE_DIR}/binaryninjacore.h ${PROJECT_BINARY_DIR}/stubs) - - # Compile those stubs into a stub library we can use to fool the linker - add_library(binaryninjacore SHARED ${PROJECT_BINARY_DIR}/stubs/stubs.cpp) - set_target_properties(binaryninjacore - PROPERTIES OUTPUT_NAME binaryninjacore - SOVERSION 1 - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/stubs - ) - target_include_directories(binaryninjacore PUBLIC ${PROJECT_SOURCE_DIR}) - - # Be sure to only link against the stubs archive file - add_dependencies(binaryninjaapi binaryninjacore) if(${CMAKE_GENERATOR} MATCHES "^Visual Studio") # Visual Studio's generator adds the config to the file path - target_link_libraries(binaryninjaapi PUBLIC "$<TARGET_PROPERTY:binaryninjacore,ARCHIVE_OUTPUT_DIRECTORY>/$<CONFIG>/$<TARGET_PROPERTY:binaryninjacore,OUTPUT_NAME>.lib") + target_link_libraries(binaryninjaapi PUBLIC "$<TARGET_PROPERTY:binaryninjacore_stubs,ARCHIVE_OUTPUT_DIRECTORY>/$<CONFIG>/$<TARGET_PROPERTY:binaryninjacore_stubs,OUTPUT_NAME>.lib") else() - target_link_libraries(binaryninjaapi PUBLIC "$<TARGET_PROPERTY:binaryninjacore,ARCHIVE_OUTPUT_DIRECTORY>/$<TARGET_PROPERTY:binaryninjacore,OUTPUT_NAME>.lib") + target_link_libraries(binaryninjaapi PUBLIC "$<TARGET_PROPERTY:binaryninjacore_stubs,ARCHIVE_OUTPUT_DIRECTORY>/$<TARGET_PROPERTY:binaryninjacore_stubs,OUTPUT_NAME>.lib") endif() else() - target_link_options(binaryninjaapi PUBLIC "LINKER:--allow-shlib-undefined") + target_link_libraries(binaryninjaapi PUBLIC "$<TARGET_PROPERTY:binaryninjacore_stubs,ARCHIVE_OUTPUT_DIRECTORY>/$<TARGET_PROPERTY:binaryninjacore_stubs,OUTPUT_NAME>.so.1") endif() endif() @@ -204,6 +204,7 @@ name = "binaryninjacore-sys" version = "0.1.0" dependencies = [ "bindgen", + "cmake", "proc-macro2", ] @@ -311,9 +312,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.27" +version = "1.2.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc" +checksum = "c3a42d84bb6b69d3a8b3eaacf0d88f179e1929695e1ad012b6cf64d9caaa5fd2" dependencies = [ "jobserver", "libc", @@ -423,6 +424,15 @@ dependencies = [ ] [[package]] +name = "cmake" +version = "0.1.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" +dependencies = [ + "cc", +] + +[[package]] name = "colorchoice" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 0b9ac4f3..4856f97b 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -7,16 +7,20 @@ rust-version = "1.83.0" license = "Apache-2.0" [features] +default = ["core"] # This is used when statically linking to prevent exporting CorePluginABIVersion and UiPluginABIVersion. no_exports = [] # Add this if you want to support the demo version of the product. # This will disable certain functions that do not exist in the demo build. demo = ["no_exports"] +# If disabled, a stub binaryninjacore library will be generated and linked. +# This feature should only be disabled for shared libraries that will later be loaded in the same process as the real binaryninjacore. +core = ["binaryninjacore-sys/core"] [dependencies] log = { version = "0.4", features = ["std"] } rayon = { version = "1.10", optional = true } -binaryninjacore-sys = { path = "binaryninjacore-sys" } +binaryninjacore-sys = { path = "binaryninjacore-sys", default-features = false} thiserror = "2.0" serde = "1.0" serde_derive = "1.0" diff --git a/rust/binaryninjacore-sys/Cargo.toml b/rust/binaryninjacore-sys/Cargo.toml index bfd49a41..d4faaec8 100644 --- a/rust/binaryninjacore-sys/Cargo.toml +++ b/rust/binaryninjacore-sys/Cargo.toml @@ -7,8 +7,15 @@ edition = "2021" links = "binaryninjacore" license = "Apache-2.0" +[features] +default = ["core"] +# If disabled, a stub binaryninjacore library will be generated and linked. +# This feature should only be disabled for shared libraries that will later be loaded in the same process as the real binaryninjacore. +core = [] + [build-dependencies] bindgen = "0.71.1" # TODO: Remove this once bindgen correctly pins the version. # proc-macro2 v1.0.79 does not have https://docs.rs/proc-macro2/1.0.80/proc_macro2/struct.Literal.html#method.c_string -proc-macro2 = ">=1.0.80"
\ No newline at end of file +proc-macro2 = ">=1.0.80" +cmake = "0.1" diff --git a/rust/binaryninjacore-sys/build.rs b/rust/binaryninjacore-sys/build.rs index 579276a6..672615da 100644 --- a/rust/binaryninjacore-sys/build.rs +++ b/rust/binaryninjacore-sys/build.rs @@ -41,6 +41,22 @@ fn link_path() -> PathBuf { }) } +// Generate and compile stub shared library and return the path to the folder containing the built stub library +fn generate_stubs() -> PathBuf { + let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"); + + let api_base_path = std::path::PathBuf::from(manifest_dir) + .join("../../") + .canonicalize() + .unwrap(); + + let stubs_path = api_base_path.join("stubs"); + cmake::Config::new(stubs_path) + .generator("Ninja") + .build() + .join("build") +} + fn main() { println!("cargo:rerun-if-env-changed=BINARYNINJADIR"); println!("cargo:rerun-if-changed=../../binaryninjacore.h"); @@ -48,9 +64,12 @@ fn main() { //Cargo's output directory let out_dir = env::var("OUT_DIR").unwrap(); - let link_path = env::var("BINARYNINJADIR") - .map(PathBuf::from) - .unwrap_or_else(|_| link_path()); + let link_path = match env::var("CARGO_FEATURE_CORE") { + Ok(_) => env::var("BINARYNINJADIR") + .map(PathBuf::from) + .unwrap_or_else(|_| link_path()), + Err(_) => generate_stubs(), + }; // Linux builds of binaryninja ship with libbinaryninjacore.so.1 in the // application folder and no symlink. The linker will attempt to link with diff --git a/rust/build.rs b/rust/build.rs index c98bf81b..1e2fede0 100644 --- a/rust/build.rs +++ b/rust/build.rs @@ -1,8 +1,8 @@ use std::path::PathBuf; fn main() { - let link_path = - std::env::var_os("DEP_BINARYNINJACORE_PATH").expect("DEP_BINARYNINJACORE_PATH specified"); + let link_path = std::env::var_os("DEP_BINARYNINJACORE_PATH") + .expect("DEP_BINARYNINJACORE_PATH not specified"); println!("cargo::rustc-link-lib=dylib=binaryninjacore"); println!("cargo::rustc-link-search={}", link_path.to_str().unwrap()); @@ -15,7 +15,7 @@ fn main() { ); } - let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR specified"); + let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not specified"); let out_dir_path = PathBuf::from(out_dir); // Copy all binaries to OUT_DIR for unit tests. diff --git a/stubs/CMakeLists.txt b/stubs/CMakeLists.txt new file mode 100644 index 00000000..35ab6177 --- /dev/null +++ b/stubs/CMakeLists.txt @@ -0,0 +1,36 @@ +cmake_minimum_required(VERSION 3.19 FATAL_ERROR) +project(binaryninjacore_stubs) + +if(WIN32) + set(PYTHON_COMMAND "py -3") +else() + set(PYTHON_COMMAND "python3") +endif() + +file(REAL_PATH "${PROJECT_SOURCE_DIR}/../" ABSOLUTE_API_PATH) + +# Generate stubs.cpp with implementations of all the BNAPI functions +add_custom_command( + OUTPUT ${PROJECT_BINARY_DIR}/stubs.cpp + COMMAND ${PYTHON_COMMAND} ${PROJECT_SOURCE_DIR}/generate_stubs.py ${ABSOLUTE_API_PATH}/binaryninjacore.h ${PROJECT_BINARY_DIR} + DEPENDS ${PROJECT_SOURCE_DIR}/generate_stubs.py ${ABSOLUTE_API_PATH}/binaryninjacore.h + COMMENT "Generating stubs.cpp from binaryninjacore.h" +) + +# Compile those stubs into a stub library we can use to fool the linker +add_library(binaryninjacore_stubs SHARED ${PROJECT_BINARY_DIR}/stubs.cpp) + +set_target_properties(binaryninjacore_stubs + PROPERTIES OUTPUT_NAME binaryninjacore + SOVERSION 1 + CXX_STANDARD 20 + CXX_VISIBILITY_PRESET hidden + CXX_STANDARD_REQUIRED ON + VISIBILITY_INLINES_HIDDEN ON + POSITION_INDEPENDENT_CODE ON + ARCHIVE_OUTPUT_DIRECTORY $<1:${PROJECT_BINARY_DIR}> +) + +target_include_directories(binaryninjacore_stubs PUBLIC ${ABSOLUTE_API_PATH}) + +install(TARGETS binaryninjacore_stubs LIBRARY DESTINATION ${PROJECT_BINARY_DIR}) diff --git a/cmake/generate_stubs.py b/stubs/generate_stubs.py index 5478ba7c..5478ba7c 100644 --- a/cmake/generate_stubs.py +++ b/stubs/generate_stubs.py |
