# 📦 RSFindLibs: Rust Dynamic Library Finder & Wrapper Generator A handy Rust library for: 1. 🔍 **Finding dynamic libraries** at runtime. 2. 🛠️ **Generates the boilerplate needed by [libloading](https://docs.rs/libloading)** --- ## 🔍 Library Finder The `find` function helps you locate a dynamic library (`.so`, `.dylib`, `.dll`) at runtime by searching in: - 🏗️ System paths - ⚙️ Environment-specific paths (e.g., `$CONDA_PREFIX`, `LD_LIBRARY_PATH`) - 🔧 Custom-configured directories ### Example ```rust let libpath = rsfindlibs::find("fdb5", None).expect("Library not found"); println!("Library found at: {}", libpath); ``` There is also a handy command line tool that let's you see where rsfindlibs is looking: ``` ➜ cargo run fdb5 -v Starting search for library 'fdb5' package = 'None' Chose library extension '.dylib' for OS 'macos' Adding these current executable directories to search roots: /Users/user/git/rust/rsfindlibs/target/debug Detected Conda environment: /Users/user/micromamba/envs/ionbeam Found environment variable 'fdb5_home'. fdb5_home Found LD_LIBRARY_PATH test/libfdb5.dylib Checking common system paths: / /usr/ /usr/local/ /opt/ /opt/homebrew/ Searching roots in order: ❌ /Users/user/git/rust/rsfindlibs/target/debug/lib/libfdb5.dylib ❌ /Users/user/git/rust/rsfindlibs/target/debug/lib64/libfdb5.dylib ✅ /Users/user/micromamba/envs/a_conda_env/lib/libfdb5.dylib ❌ /Users/user/micromamba/envs/a_conda_env/lib64/libfdb5.dylib ❌ fdb5_home/lib/libfdb5.dylib ❌ fdb5_home/lib64/libfdb5.dylib ❌ test/libfdb5.dylib/lib/libfdb5.dylib ❌ test/libfdb5.dylib/lib64/libfdb5.dylib ❌ /lib/libfdb5.dylib ❌ /lib64/libfdb5.dylib ❌ /usr/lib/libfdb5.dylib ❌ /usr/lib64/libfdb5.dylib ❌ /usr/local/lib/libfdb5.dylib ❌ /usr/local/lib64/libfdb5.dylib ❌ /opt/lib/libfdb5.dylib ❌ /opt/lib64/libfdb5.dylib ❌ /opt/homebrew/lib/libfdb5.dylib ❌ /opt/homebrew/lib64/libfdb5.dylib Library found: /Users/user/micromamba/envs/a_conda_env/lib/libfdb5.dylib ``` --- ## 🛠️ Macro for Generating Wrappers The `generate_library_wrapper!` macro simplifies working with dynamic libraries by generating structs to load and call their functions seamlessly. ### How It Works 1. Declare the library functions you want to use. 2. The macro generates a wrapper struct that loads the library and makes functions accessible like native Rust functions. ### Example ```rust use rsfindlibs::generate_library_wrapper; use libloading::Library; generate_library_wrapper! { FdbApiWrapper { fn fdb_new_handle(fdb: *mut *mut FdbHandle) -> c_int; fn fdb_initialise() -> c_int; fn fdb_flush(fdb: *mut FdbHandle) -> c_int; } } pub static FDBLIB: Lazy> = Lazy::new(|| { let libpath = rsfindlibs::find("fdb5", None).expect("FDB5 library not found"); let raw_lib = Library::new(&libpath).expect("Failed to load library"); let fdblib_wrapper = FdbApiWrapper::load(raw_lib).map_err(|e| e.to_string()).expect("Failed to wrap FDB5 library"); Arc::new(fdblib_wrapper) }); ``` ## 🚀 Installation Add the following to your `Cargo.toml`: ```toml [dependencies] rsfindlibs = "0.1" ``` --- ## 📄 License Apache 2.0