Error loading a shared library when trying to run a Clojure project in NixOS

65 Views Asked by At

I am trying to run a super simple Clojure project in NixOS 23.05.

The project.clj file contains:

(defproject fsm "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "EPL-2.0 OR GPL-2.0-or-later WITH Classpath-exception-2.0"
            :url "https://www.eclipse.org/legal/epl-2.0/"}
  :dependencies [[org.clojure/clojure "1.11.1"]
                 [com.phronemophobic/clj-graphviz "0.6.1"]]
  :main ^:skip-aot fsm.core
  :target-path "target/%s"
  :profiles {:uberjar {:aot :all
                       :jvm-opts ["-Dclojure.compiler.direct-linking=true"]}})

The file src/fsm/core.clj contains:

(ns fsm.core
  (:gen-class))

(require '[com.phronemophobic.clj-graphviz :refer [render-graph]])

(defn -main
  "I don't do a whole lot ... yet."
  [& args]
  (println "Hello, World!")

  (render-graph {:edges [["a" "b"]]})
  ;; writes to graph.png

  (render-graph {:edges [["a" "b"]]}
                {:filename "my-graph.png"}))

But when I enter lein run, I get the error message:

Execution error (UnsatisfiedLinkError) at com.sun.jna.NativeLibrary/loadLibrary (NativeLibrary.java:323).
Unable to load library 'gvc':
libgvc.so: cannot open shared object file: No such file or directory
libgvc.so: cannot open shared object file: No such file or directory
Native library (linux-x86-64/libgvc.so) not found in resource path (...)

This works fine in other Linux distros (Pop OS!/Ubuntu), so I believe I am missing something with NixOS configuration. I am unfamiliar with this distribution.

2

There are 2 best solutions below

0
E.T. On

libgvc.so is a part of GraphViz. You need to install GraphViz to get access to that library. Do so however you please.

If you are not using Flakes for deploying/running your app, the easiest way to install GraphViz would be to use a Nix shell like so:

$ nix-shell -p graphviz
$ lein run

You can also add graphviz to your installed packages list the same way you installed lein.

0
jackdbd On

That libgvc.so is a shared object that should be installed on your system when you install Graphviz (see Installed Libraries here). I say should because I'm not sure libgvc (Graphviz context library) is always included when you compile Graphviz.

Installing a library on NixOS means a different thing than installing a library on Ubuntu. This is because apt in Ubuntu (like most package managers in Linux distros) downloads precompiled binaries, while nix in NixOS checks if the required artifact exists in a binary cache, and if it doesn't exist, it compiles the source code and uploads the artifact to that cache.

As you can see from this NixOS module in nixpkgs, Graphviz source code is first fetched from this Gitlab repository, then compiled using the tools declared in nativeBuildInputs. That NixOS module also takes care of ensuring that runtime dependencies are available on your system (see buildInputs).

If the graphviz package you find in nixpkgs does include libgvc, that package is probably fine and you should just double check your NixOS configuration. You should have something like this:

environment.systemPackages = [
  pkgs.graphviz
];

If the graphviz package you find in nixpkgs does not include libgvc, you can make a derivation that includes it.

You could also try compiling a small program that includes Graphviz, and use ldd to find all shared objects that the linker was not able to find.

ldd your-graphviz-program | grep 'not found'

See also how it's done here.

Bonus tip: when you want to bootstrap a quick Clojure project, use dev-templates.