NickelEval.jl

Julia FFI bindings for Nickel configuration language
Log | Files | Refs | README | LICENSE

commit 0139f5f82a9fe335d165b8211549a7c30fc992a6
parent 2251a68997c0e59c5662acdf875a6df5240d9d7c
Author: Erik Loualiche <eloualiche@users.noreply.github.com>
Date:   Wed, 18 Mar 2026 13:51:58 -0400

Merge pull request #11 from LouLouLibs/fix/graceful-dlopen

Graceful dlopen fallback + build_ffi() function
Diffstat:
Msrc/NickelEval.jl | 2+-
Msrc/ffi.jl | 37+++++++++++++++++++++++++++++++------
2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/src/NickelEval.jl b/src/NickelEval.jl @@ -2,7 +2,7 @@ module NickelEval export nickel_eval, nickel_eval_file, @ncl_str, NickelError, NickelEnum export nickel_to_json, nickel_to_yaml, nickel_to_toml -export check_ffi_available +export check_ffi_available, build_ffi """ NickelError <: Exception diff --git a/src/ffi.jl b/src/ffi.jl @@ -44,9 +44,14 @@ FFI_AVAILABLE::Bool = false function __init_ffi__() path = _find_library_path() if path !== nothing - global libnickel_lang = path - global FFI_AVAILABLE = true - Libdl.dlopen(path) + try + Libdl.dlopen(path) + global libnickel_lang = path + global FFI_AVAILABLE = true + catch e + @warn "Found libnickel_lang at $path but failed to load it: $e\n" * + "Build from source with: build_ffi()" + end end end @@ -61,12 +66,32 @@ Check if the Nickel C API library is available. """ check_ffi_available() = FFI_AVAILABLE +""" + build_ffi() + +Build the Nickel C API library from source. Requires Rust (cargo). +Restarts the FFI after building so you don't need to restart Julia. +""" +function build_ffi() + build_script = joinpath(@__DIR__, "..", "deps", "build.jl") + @info "Building Nickel C API library from source..." + withenv("NICKELEVAL_BUILD_FFI" => "true") do + include(build_script) + end + # Re-initialize to pick up the newly built library + __init_ffi__() + if FFI_AVAILABLE + @info "FFI ready. nickel_eval() is now available." + else + error("Build completed but library still not loadable. Check the build output above.") + end +end + function _check_ffi_available() FFI_AVAILABLE && return error("Nickel C API library not available.\n\n" * - "Install options:\n" * - " 1. Build from source: NICKELEVAL_BUILD_FFI=true julia -e 'using Pkg; Pkg.build(\"NickelEval\")'\n" * - " 2. Place $(LIB_NAME) in deps/ manually\n") + "Build from Julia: using NickelEval; build_ffi()\n" * + "Build from shell: NICKELEVAL_BUILD_FFI=true julia -e 'using Pkg; Pkg.build(\"NickelEval\")'\n") end # ── Tree-walk: convert C API expr to Julia value ─────────────────────────────