From 00cb06c758ed8cfad7cabeb5562b263fd5b5eec7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Gibrowski=20Fa=C3=A9?= Date: Sun, 5 Oct 2025 17:51:52 -0300 Subject: [PATCH 1/3] make crate `#![no_std]` friendly We can make the crate work in `#![[no_std]]` environments with minimal changes. Literaly just changing a few imports. --- src/lib.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4208b02..2d538a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,6 +127,7 @@ //! #[cfg(not(feature = "dlopen-foo"))] //! use ffi::*; //! ``` +#![no_std] #![warn(missing_docs)] extern crate libloading; @@ -240,8 +241,8 @@ pub enum DlError { MissingSymbol(&'static str), } -impl std::error::Error for DlError { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { +impl core::error::Error for DlError { + fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { match *self { DlError::CantOpen(ref e) => Some(e), DlError::MissingSymbol(_) => None, @@ -249,8 +250,8 @@ impl std::error::Error for DlError { } } -impl std::fmt::Display for DlError { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Display for DlError { + fn fmt(&self, f: &mut core::fmt::Formatter) ->core::fmt::Result { match *self { DlError::CantOpen(ref e) => write!(f, "Could not open the requested library: {}", e), DlError::MissingSymbol(s) => write!(f, "The requested symbol was missing: {}", s), @@ -287,7 +288,7 @@ macro_rules! dlopen_external_library( impl $structname { pub unsafe fn open(name: &str) -> Result<$structname, $crate::DlError> { // we use it to ensure the 'static lifetime - use std::mem::transmute; + use core::mem::transmute; let lib = $crate::Library::new(name).map_err($crate::DlError::CantOpen)?; let s = $structname { $($($sname: { From 2e2dfa84b1ddb6bf420c2f356791396afda26a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Gibrowski=20Fa=C3=A9?= Date: Sun, 5 Oct 2025 20:25:13 -0300 Subject: [PATCH 2/3] only include libloading when using `std` When we do not use `std`, we cannot load things dynamically with `libloading`. By its very nature, `libloading` will probably always include a lot of platform-specific code, making it not depend on `std` unrealistic. So, when someone says they do not want to use `std`, we should not use `libloading`. As long as downstream does not try to dynamically load something with `default-features=false`, this should never be a problem. What happens if downstream does try that, however? Well, then the Rust compiler with print an error saying they are trying to use a crate that does not exist. Because we default to using `std` (as is the standard for most optionally `no_std` crates), this should not cause any breakage. --- Cargo.toml | 6 +++++- src/lib.rs | 9 ++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8aba6c5..aa3305c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,4 +11,8 @@ keywords = ["dylib", "dlopen"] categories = ["api-bindings"] [dependencies] -libloading = ">=0.7, <0.9" +libloading = { version = ">=0.7, <0.9", optional = true } + +[features] +default = [ "std" ] +std = [ "dep:libloading" ] diff --git a/src/lib.rs b/src/lib.rs index 2d538a2..3584cf0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -130,10 +130,14 @@ #![no_std] #![warn(missing_docs)] +#[cfg(feature = "std")] extern crate libloading; +#[cfg(feature = "std")] pub use libloading::Error as LibLoadingError; + #[doc(hidden)] +#[cfg(feature = "std")] pub use libloading::{Library, Symbol}; /// Macro for generically invoking a FFI function @@ -236,6 +240,7 @@ pub enum DlError { /// /// Includes the error reported by `libloading` when trying to /// open the library. + #[cfg(feature = "std")] CantOpen(LibLoadingError), /// Some required symbol was missing in the library MissingSymbol(&'static str), @@ -244,6 +249,7 @@ pub enum DlError { impl core::error::Error for DlError { fn source(&self) -> Option<&(dyn core::error::Error + 'static)> { match *self { + #[cfg(feature = "std")] DlError::CantOpen(ref e) => Some(e), DlError::MissingSymbol(_) => None, } @@ -251,8 +257,9 @@ impl core::error::Error for DlError { } impl core::fmt::Display for DlError { - fn fmt(&self, f: &mut core::fmt::Formatter) ->core::fmt::Result { + fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { match *self { + #[cfg(feature = "std")] DlError::CantOpen(ref e) => write!(f, "Could not open the requested library: {}", e), DlError::MissingSymbol(s) => write!(f, "The requested symbol was missing: {}", s), } From 4037e685845f37a792f5d7b531d55c0dd6a65d44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Leonardo=20Gibrowski=20Fa=C3=A9?= Date: Sun, 5 Oct 2025 20:34:20 -0300 Subject: [PATCH 3/3] document `no_std` behavior --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 3584cf0..864f01d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -127,6 +127,12 @@ //! #[cfg(not(feature = "dlopen-foo"))] //! use ffi::*; //! ``` +//! +//! ## A note on `#![no_std]` support +//! +//! Deactivating the `std` dependency through `default-features = false` will stop `dlib` from +//! importing `libloading`. This means in `no_std` environments, users of this library *must* +//! link their binaries, and not use `dlopen`. #![no_std] #![warn(missing_docs)]