NickelEval.jl

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

commit 09a872e5b679c9811283ff94550686dff65280a8
parent 7f4c62c0a8300b7c2af92d30d4dd4b38cc0f60a6
Author: Erik Loualiche <[email protected]>
Date:   Wed, 18 Mar 2026 12:44:24 -0400

Merge pull request #7 from LouLouLibs/fix/runtime-library-loading

Fix: resolve library path at runtime (JLL pattern)
Diffstat:
MProject.toml | 1+
Msrc/NickelEval.jl | 4++++
Msrc/ffi.jl | 25+++++++++++++++----------
3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/Project.toml b/Project.toml @@ -6,6 +6,7 @@ version = "0.6.0" [deps] Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" LazyArtifacts = "4af54fe1-eca0-43a8-85a7-787d91b784e3" +Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" [compat] julia = "1.6" diff --git a/src/NickelEval.jl b/src/NickelEval.jl @@ -88,4 +88,8 @@ end include("ffi.jl") +function __init__() + __init_ffi__() +end + end # module diff --git a/src/ffi.jl b/src/ffi.jl @@ -3,6 +3,7 @@ # This file provides the convenience layer: library discovery, eval, tree-walk. using LazyArtifacts +using Libdl # Platform-specific library name const LIB_NAME = if Sys.isapple() @@ -34,16 +35,20 @@ function _find_library_path() return nothing end -const LIB_PATH = _find_library_path() -const FFI_AVAILABLE = LIB_PATH !== nothing - -# Set the library path for LibNickel's @ccall wrappers. -# CRITICAL: this const must come before include("libnickel.jl") because the -# LibNickel module's @ccall uses `libnickel_lang` as a bare identifier -# imported from the parent module. -# Always define the const (even with empty string) so the import doesn't fail -# at compile time. The runtime check in _check_ffi_available() gates actual use. -const libnickel_lang = FFI_AVAILABLE ? LIB_PATH : "" +# Library path and availability resolved at runtime via __init__(), +# not at precompile time. This allows Pkg.build() to install the library +# after initial precompilation (JLL pattern, requires Julia 1.6+). +libnickel_lang::String = "" +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) + end +end include("libnickel.jl") import .LibNickel