Tip for SBCL, Quicklisp, and Library Dependencies with pkg-config

Hey so I have arm wrestled with SBCL/Quicklisp periodically over the last few years. I’m not an avid LISPer and by no means an expert on the subject; but I do like the language and this little nugget might be useful to others who get stuck.

I have SBCL, Quicklisp, and some libraries installed with home-manager, and frequently run into issues installing some packages using Quicklisp because shared object dependencies cannot be found. This can become an issue with drakma for example which depends on libssl.so.

libsll.so is provided by nixpkgs.openssl.dev, but for whatever reason it does not dump the shared object to /home/johndoe/.nix-profile/lib/libssl.so, instead it is necessary to use pkg-config to pull the library path.

You might know that for quicklisp/cffi to locate libraries you can append paths to cffi:*foreign-library-directories*, so a nice starting point is to do something like

;; ~/.sbclrc
#+asdf (require :asdf)
(ql:quickload :cffi :silent t)
(pushnew (merge-pathnames ".nix-profile/lib/" (user-homedir-path))
                 cffi:*foreign-library-directories*)
(pushnew (merge-pathnames ".nix-profile/lib64/" (user-homedir-path))
                 cffi:*foreign-library-directories*)

This works great, but in the case of libssl.so we need to use pkg-config to lookup the path, and ideally we shouldn’t hard code it. So I did the following ( notably I have set PKG_CONFIG_PATH=/home/johndoe/.nix-profile/lib/pkgconfig:/home/johndoe/.nix-profile/lib64/pkgconfig:/home/johndoe/.nix-profile/share/pkgconfig; in my profile, which is important ).

;; After previous snippet
(defun pkg-config-add-lib (libname)
 (let ((process (sb-ext:run-program "/usr/bin/env"
                                    (list "pkg-config" libname "--libs-only-L")
                                    :input t :output :stream :wait t)))
  (let ((stream (sb-ext:process-output process)))
       (loop for line = (read-line stream nil nil)
        while line do
              ;; Drop "-L" part, and add '/' to the end. '/' IS necessary!
              (pushnew (pathname (concatenate 'string (subseq line 2) "/"))
                       cffi:*foreign-library-directories*))
       (sb-ext:process-close process))))
;; Get libssl
(pkg-config-add-lib "libssl")

Now doing (ql:quickload :drakma) actually works! Where previously it would crash looking for libssl.so.1.1.

4 Likes