common-lispsbclasdfquicklisp

One function refuses to export, while other functions export?


Yesterday, I asked a question about creating libraries with common lisp.

my lib:

;in my-lib.asd
(asdf:defsystem :my-lib
  :depends-on (:cl-json :clsql :clsql-sqlite3)
  :components ((:file "package")
               (:file "functions")
               (:file "macros")))

; in package.lisp
(defpackage :my-lib
  (:import-from :cl-json :encode-json-to-string)
  (:use :cl)
  (:export :use-db
           :make-json
           :cwd
           :status-update))

; in functions.lisp

(in-package :my-lib)

....

(defun make-json (a-list)
  (encode-json-to-string a-list))

(defun change-to-path (project-name)
  (uiop:chdir (merge-pathnames project-name "~/quicklisp/local-projects/")))

(defun cwd ()
  (uiop/os:getcwd))

.....

my other project that depends on the library

;;in project.asd
(asdf:defsystem :project
  :depends-on (:dexador :clsql :clsql-sqlite3 :my-lib :cl-csv :uiop)

;;in package.lisp

(defpackage :project
  (:shadowing-import-from :cl-csv :read-csv)
  (:use :cl :my-lib))

The problem

I keep getting the error The symbol "MAKE-JSON" is not external in the MY-LIB package.

But the other functions that exported work fine. Only make-json doesnt. why?

When i look for all exported packages in the my-lib project, i get a list of all functions except make-json.

> (do-external-symbols (s (find-package 'my-lib))
       (print s))

MY-LIB:STATUS-UPDATE 
MY-LIB:REM-VAR 
MY-LIB:CWD 
MY-LIB:CHANGE-TO-PATH 
NIL

UPDATE:

It seems that make-json only gets added to the list of exported functions if I manually compile the defpackage for my-lib.

I have tried to compile the file with (asdf:load-asd "my-lib") but i still get the error.


Solution

  • You have, at least, the problem that your system doesn't have the dependencies it needs: in order, for instance, for functions.lisp to be compiled then package.lisp needs to have been compiled and loaded. The art of defining systems is the art of expressing dependencies between their parts.

    In this case there is an easy approach and a fancy approach.

    The fancy approach is to express the dependencies explicitly, for instance by:

    (defsystem :my-lib
      :depends-on (:cl-json :clsql :clsql-sqlite3)
      :components ((:file "package")
                   (:file "functions"
                    :depends-on ("package"))
                   (:file "macros"
                    :depends-on ("functions"))))
    

    The easy approach is to tell ASDF that the system has implicit serial dependencies and make sure the components are in the right order:

    (defsystem :my-lib
      :depends-on (:cl-json :clsql :clsql-sqlite3)
      :serial t
      :components ((:file "package")
                   (:file "functions")
                   (:file "macros")))