diff --git a/nixide/src/init.rs b/nixide/src/init.rs new file mode 100644 index 0000000..cd9c484 --- /dev/null +++ b/nixide/src/init.rs @@ -0,0 +1,68 @@ +use ctor::ctor; + +use super::NixideResult; +use super::errors::ErrorContext; +use super::util::wrap; +use super::util::wrappers::AsInnerPtr as _; + +pub(crate) static mut LIBNIX_INIT_STATUS: Option> = None; + +/// # Warning +/// +/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor) +/// > explicitly subverts that. The code that runs in `ctor` functions +/// > should be careful to limit itself to libc functions and code +/// > that does not rely on Rust's stdlib services. +/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings) +#[ctor] +#[cfg(not(feature = "exprs"))] +fn init_libutil() { + unsafe { + if !matches!(LIBNIX_INIT_STATUS, Some(Err(_))) { + LIBNIX_INIT_STATUS = Some(wrap::nix_fn!(|ctx: &ErrorContext| unsafe { + sys::nix_libutil_init(ctx.as_ptr()); + })); + } + } +} + +/// # Warning +/// +/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor) +/// > explicitly subverts that. The code that runs in `ctor` functions +/// > should be careful to limit itself to libc functions and code +/// > that does not rely on Rust's stdlib services. +/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings) +#[ctor] +#[cfg(all(feature = "store", not(feature = "exprs")))] +fn init_libstore() { + // XXX: TODO: how do I support `sys::nix_libstore_init_no_load_config(context)`? + unsafe { + if !matches!(LIBNIX_INIT_STATUS, Some(Err(_))) { + LIBNIX_INIT_STATUS = Some(wrap::nix_fn!(|ctx: &ErrorContext| unsafe { + sys::nix_libstore_init(ctx.as_ptr()); + })); + } + } +} + +/// `sys::nix_libexpr_init` internally runs +/// +/// # Warning +/// +/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor) +/// > explicitly subverts that. The code that runs in `ctor` functions +/// > should be careful to limit itself to libc functions and code +/// > that does not rely on Rust's stdlib services. +/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings) +#[ctor] +#[cfg(feature = "exprs")] +fn init_libexpr() { + unsafe { + if !matches!(LIBNIX_INIT_STATUS, Some(Err(_))) { + LIBNIX_INIT_STATUS = Some(wrap::nix_fn!(|ctx: &ErrorContext| unsafe { + sys::nix_libexpr_init(ctx.as_ptr()); + })); + } + } +} diff --git a/nixide/src/lib.rs b/nixide/src/lib.rs index 027aec7..c9407da 100644 --- a/nixide/src/lib.rs +++ b/nixide/src/lib.rs @@ -7,6 +7,7 @@ pub extern crate libc; pub extern crate nixide_sys as sys; pub(crate) mod errors; +mod init; mod stdext; pub(crate) mod util; mod verbosity; @@ -29,63 +30,3 @@ pub use expr::{EvalState, EvalStateBuilder, Value}; pub use flake::{FlakeSettings, LockedFlake}; #[cfg(feature = "store")] pub use store::{Store, StorePath}; - -use ctor::ctor; -use util::wrappers::AsInnerPtr as _; - -pub(crate) static mut INIT_LIBUTIL_STATUS: Option> = None; -#[cfg(feature = "store")] -pub(crate) static mut INIT_LIBSTORE_STATUS: Option> = None; -#[cfg(feature = "exprs")] -pub(crate) static mut INIT_LIBEXPR_STATUS: Option> = None; - -/// # Warning -/// -/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor) -/// > explicitly subverts that. The code that runs in `ctor` functions -/// > should be careful to limit itself to libc functions and code -/// > that does not rely on Rust's stdlib services. -/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings) -#[ctor] -fn init_libutil() { - unsafe { - INIT_LIBUTIL_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe { - sys::nix_libutil_init(ctx.as_ptr()); - })); - } -} - -/// # Warning -/// -/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor) -/// > explicitly subverts that. The code that runs in `ctor` functions -/// > should be careful to limit itself to libc functions and code -/// > that does not rely on Rust's stdlib services. -/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings) -#[ctor] -#[cfg(feature = "store")] -fn init_libstore() { - // XXX: TODO: how do I support `sys::nix_libstore_init_no_load_config(context)`? - unsafe { - INIT_LIBSTORE_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe { - sys::nix_libutil_init(ctx.as_ptr()); - })); - } -} - -/// # Warning -/// -/// > Rust's philosophy is that nothing happens before or after main and [ctor](https://github.com/mmastrac/rust-ctor) -/// > explicitly subverts that. The code that runs in `ctor` functions -/// > should be careful to limit itself to libc functions and code -/// > that does not rely on Rust's stdlib services. -/// > - Excerpt from the [github:mmastrac/rust-ctor README.md](https://github.com/mmastrac/rust-ctor?tab=readme-ov-file#warnings) -#[ctor] -#[cfg(feature = "exprs")] -fn init_libexpr() { - unsafe { - INIT_LIBEXPR_STATUS = Some(util::wrap::nix_fn!(|ctx: &errors::ErrorContext| unsafe { - sys::nix_libexpr_init(ctx.as_ptr()); - })); - } -}