Flake lock file updates:
• Updated input 'flake-parts':
'github:hercules-ci/flake-parts/80daad04eddbbf5a4d883996a73f3f542fa437ac?narHash=sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY%3D' (2026-01-11)
→ 'github:hercules-ci/flake-parts/57928607ea566b5db3ad13af0e57e921e6b12381?narHash=sha256-AnYjnFWgS49RlqX7LrC4uA%2BsCCDBj0Ry/WOJ5XWAsa0%3D' (2026-02-02)
• Updated input 'flake-parts/nixpkgs-lib':
'github:nix-community/nixpkgs.lib/2075416fcb47225d9b68ac469a5c4801a9c4dd85?narHash=sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo%3D' (2025-12-14)
→ 'github:nix-community/nixpkgs.lib/72716169fe93074c333e8d0173151350670b824c?narHash=sha256-cBEymOf4/o3FD5AZnzC3J9hLbiZ%2BQDT/KDuyHXVJOpM%3D' (2026-02-01)
• Updated input 'nix':
'github:NixOS/nix/77b6b01b727f0cd1324e431a32a8854768b957ef?narHash=sha256-vpI7XEfX5zeCVRANUzhMNsZfrMWuN0rwNenQ3z0rJNo%3D' (2026-01-30)
→ 'github:NixOS/nix/0acd0566e85e4597269482824711bcde7b518600?narHash=sha256-jJIlRLPPVYu860MVFx4gsRx3sskmLDSRWXXue5tYncw%3D' (2026-02-27)
• Updated input 'nix-cargo-integration':
'github:90-008/nix-cargo-integration/6d583e2098fa3df490c2597df06386e3efcc39b6?narHash=sha256-bjtDp0NHjLjDOjklQVHCDCVM5q39zDzuwenNri0p4Ys%3D' (2026-01-31)
→ 'github:90-008/nix-cargo-integration/c783c5dff02c06f2af6226d4dd4d494542d0a4d2?narHash=sha256-NaUqM0i6XIGdgRNxxQ9sfgCAVeE2Ko9rz7e19RsNUKw%3D' (2026-02-28)
• Updated input 'nix-cargo-integration/parts':
'github:hercules-ci/flake-parts/80daad04eddbbf5a4d883996a73f3f542fa437ac?narHash=sha256-PVvu7OqHBGWN16zSi6tEmPwwHQ4rLPU9Plvs8/1TUBY%3D' (2026-01-11)
→ 'github:hercules-ci/flake-parts/57928607ea566b5db3ad13af0e57e921e6b12381?narHash=sha256-AnYjnFWgS49RlqX7LrC4uA%2BsCCDBj0Ry/WOJ5XWAsa0%3D' (2026-02-02)
• Updated input 'nix-cargo-integration/rust-overlay':
'github:oxalica/rust-overlay/a1d32c90c8a4ea43e9586b7e5894c179d5747425?narHash=sha256-zmnvRUm15QrlKH0V1BZoiT3U%2BQ%2Btr%2BP5Osi8qgtL9fY%3D' (2026-01-31)
→ 'github:oxalica/rust-overlay/a1ab5e89ab12e1a37c0b264af6386a7472d68a15?narHash=sha256-x6IFQ9bL7YYfW2m2z8D3Em2YtAA3HE8kiCFwai2fwrw%3D' (2026-02-28)
• Updated input 'nix-cargo-integration/treefmt':
'github:numtide/treefmt-nix/28b19c5844cc6e2257801d43f2772a4b4c050a1b?narHash=sha256-8aAYwyVzSSwIhP2glDhw/G0i5%2BwOrren3v6WmxkVonM%3D' (2026-01-29)
→ 'github:numtide/treefmt-nix/337a4fe074be1042a35086f15481d763b8ddc0e7?narHash=sha256-wQ6NJSuFqAEmIg2VMnLdCnUc0b7vslUohqqGGD%2BFyxk%3D' (2026-02-04)
• Updated input 'nixpkgs':
'github:NixOS/nixpkgs/bfc1b8a4574108ceef22f02bafcf6611380c100d?narHash=sha256-msG8SU5WsBUfVVa/9RPLaymvi5bI8edTavbIq3vRlhI%3D' (2026-01-26)
→ 'github:NixOS/nixpkgs/dd9b079222d43e1943b6ebd802f04fd959dc8e61?narHash=sha256-I45esRSssFtJ8p/gLHUZ1OUaaTaVLluNkABkk6arQwE%3D' (2026-02-27)
|
||
|---|---|---|
| .vscode | ||
| dev | ||
| doc | ||
| nix-bindings-bdwgc-sys | ||
| nix-bindings-expr | ||
| nix-bindings-expr-sys | ||
| nix-bindings-fetchers | ||
| nix-bindings-fetchers-sys | ||
| nix-bindings-flake | ||
| nix-bindings-flake-sys | ||
| nix-bindings-store | ||
| nix-bindings-store-sys | ||
| nix-bindings-util | ||
| nix-bindings-util-sys | ||
| .envrc | ||
| .gitignore | ||
| bindgen-gcc.sh | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CHANGELOG.md | ||
| flake.lock | ||
| flake.nix | ||
| input-propagation-workaround.nix | ||
| LICENSE | ||
| nci.nix | ||
| README.md | ||
Nix Bindings for Rust
Rust bindings for the Nix C API, providing safe, idiomatic Rust interfaces to Nix's core functionality including store operations, expression evaluation, and flake management.
Overview
This workspace provides multiple crates that wrap different layers of the Nix C API:
nix-bindings-util- Utility types and helpers (settings, context, version detection, string handling)nix-bindings-store- Store operations (paths, derivations, store management)nix-bindings-expr- Expression evaluation and type extractionnix-bindings-flake- Flake operationsnix-bindings-fetchers- Fetcher functionality (requires Nix ≥ 2.29)
The *-sys crates contain generated FFI bindings and are not intended for direct use.
Features
- Nix evaluation - Evaluate Nix expressions and create and extract values
- Store integration - Interact with the Nix store, manage paths, build derivations
- Threading - GC registration and memory management via
Drop - Lazy evaluation - Fine-grained control over evaluation strictness
- Version compatibility - Conditional compilation for different Nix versions
Quick Start
Add the crates you need to your Cargo.toml:
[dependencies]
nix-bindings-store = { git = "https://github.com/nixops4/nix-bindings-rust" }
nix-bindings-expr = { git = "https://github.com/nixops4/nix-bindings-rust" }
Basic example:
use nix_bindings_expr::eval_state::{EvalState, init, gc_register_my_thread};
use nix_bindings_store::store::Store;
use std::collections::HashMap;
fn main() -> anyhow::Result<()> {
// Initialize Nix library and register thread with GC
init()?;
let guard = gc_register_my_thread()?;
// Open a store connection and create an evaluation state
let store = Store::open(None, HashMap::new())?;
let mut eval_state = EvalState::new(store, [])?;
// Evaluate a Nix expression
let value = eval_state.eval_from_string("[1 2 3]", "<example>")?;
// Extract typed values
let elements: Vec<_> = eval_state.require_list_strict(&value)?;
for element in elements {
let num = eval_state.require_int(&element)?;
println!("Element: {}", num);
}
drop(guard);
Ok(())
}
Usage Examples
Evaluating Nix Expressions
use nix_bindings_expr::eval_state::EvalState;
// Evaluate and extract different types
let int_value = eval_state.eval_from_string("42", "<example>")?;
let num = eval_state.require_int(&int_value)?;
let str_value = eval_state.eval_from_string("\"hello\"", "<example>")?;
let text = eval_state.require_string(&str_value)?;
let attr_value = eval_state.eval_from_string("{ x = 1; y = 2; }", "<example>")?;
let attrs = eval_state.require_attrs(&attr_value)?;
Working with Lists
let list_value = eval_state.eval_from_string("[1 2 3 4 5]", "<example>")?;
// Lazy: check size without evaluating elements
let size = eval_state.require_list_size(&list_value)?;
// Selective: evaluate only accessed elements
if let Some(first) = eval_state.require_list_select_idx_strict(&list_value, 0)? {
let value = eval_state.require_int(&first)?;
}
// Strict: evaluate all elements
let all_elements: Vec<_> = eval_state.require_list_strict(&list_value)?;
Thread Safety
Before using EvalState in a thread, register with the garbage collector:
use nix_bindings_expr::eval_state::{init, gc_register_my_thread};
init()?; // Once per process
let guard = gc_register_my_thread()?; // Once per thread
// ... use EvalState ...
drop(guard); // Unregister when done
For more examples, see the documentation in each crate's source code.
Nix Version Compatibility
The crates use conditional compilation to support multiple Nix versions:
nix-bindings-fetchersrequires Nix ≥ 2.29- Some features in other crates require specific Nix versions
The build system automatically detects the Nix version and enables appropriate features.
Integration with Nix Projects
These crates use nix-cargo-integration for seamless integration with Nix builds. To use them in your Nix project:
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
flake-parts.url = "github:hercules-ci/flake-parts";
nix-cargo-integration.url = "github:90-008/nix-cargo-integration";
nix-bindings-rust.url = "github:nixops4/nix-bindings-rust";
};
outputs = inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [
inputs.nix-cargo-integration.flakeModule
inputs.nix-bindings-rust.modules.flake.default
];
perSystem = { config, pkgs, ... }: {
# Optional: override Nix package
nix-bindings-rust.nixPackage = pkgs.nix;
nci.projects."myproject" = {
depsDrvConfig = {
imports = [ config.nix-bindings-rust.nciBuildConfig ];
};
};
};
};
}
See the nix-cargo-integration documentation for more options.
Development
Getting Started
$ nix develop
Building
# Build specific crates (release mode)
nix build .#nix-bindings-store-release
nix build .#nix-bindings-expr-release
# Build with Cargo (in dev shell)
cargo build
cargo build --release
Testing
# Run tests for specific crates via Nix (recommended - includes proper store setup)
nix build .#checks.x86_64-linux.nix-bindings-store-tests
nix build .#checks.x86_64-linux.nix-bindings-expr-tests
# Run all checks (tests + clippy + formatting)
nix flake check
# Run tests with Cargo (in dev shell)
cargo test
# Run specific test
cargo test test_name
Memory Testing
For FFI memory leak testing with valgrind, see doc/hacking/test-ffi.md.
Code Formatting
treefmt
IDE Setup
For VSCode, load the dev shell via Nix Env Selector extension or direnv.
Documentation
License
See LICENSE file in the repository.