Using quicklisp with parenscript and sigil - common-lisp

I would like to use some ps macros in a .parenscript file. The macros are in a library that will be loaded with quicklisp. I am using sigil to compile the .parenscript file.
I have tried this at the top of the parenscript file:
(lisp
(progn
(ql:quickload 'paren6)
(use-package :paren6)))
but the macro package does not get "used".
Loading the libraries from the command line works:
>sigil --eval "(progn (ql:quickload 'paren6) (use-package :paren6))" sample.parenscript
But it feels clunky, and sigil needs a small hack to prevent it from dumping the output from quickload into the javascript output - indicating that no one else is doing things this way.
I am using sigil because I prefer to build .parenscript -> .js from the command line. Alternatives to sigil will be considered.
What is the best way to indicate a quicklisp dependency for a .parenscript file?

Tracked this one down: Sigil sets *package* to ps except when evaluating lisp forms, where it's left as common-lisp-user so your use-package was affecting the wrong package, and your symbols went wonky.
Try (use-package 'paren6 'ps)

Related

Distributing a CFFI wrapper for a custom C lib

I've built a library that wraps custom C code and thinking about the best way to build the shared library as part of the ASDF load. The makefile is conditionalised for various OSs, so it could be as simple as uiop:run-program ..., but I thought I'd ask here if there were a more standard idiom for this.
Because the C code is specific to this application, it won't be available through a package manager and must be built specifically for each users machine. I'm fine with documenting a manual build, but if I can smooth things for the user I will. I notice that Python seems to have some kind of automated way of building libs for their CFFI and wonder if there's something for CL.
For an answer to my own question: there seems to be neither a de-facto way of doing this (based on a search of github asd files), nor a definitive method in the ASDF best practices, though there are some ideas to be gleaned from that document.
I'll put my implementation out as a suggested idiom for this use case, along with some possible alternatives. Hopefully some of the ASDF experts here will correct any misunderstandings.
;; Define a makefile as a type of source file for the system
(defclass makefile (source-file) ((type :initform "m")))
;; tell ASDF how to compile it
(defmethod perform ((o load-op) (c makefile)) t)
(defmethod perform ((o compile-op) (c makefile))
(let* ((lib-dir (system-relative-pathname "cephes" "scipy-cephes"))
(lib (make-pathname :directory `(:relative ,(namestring lib-dir))
:name "libmd"
:type #+unix "so" #+(or windows win32) "dll"))
(built (probe-file (namestring lib))))
(if built
(format *error-output* "Library ~S exists, skipping build" lib)
(format *error-output* "Building ~S~%" lib))
(unless built
(run-program (format nil "cd ~S && make" (namestring lib-dir)) :output t))))
(defsystem "cephes"
:description "Wrapper for the Cephes Mathematical Library"
:version (:read-file-form "version.sexp")
:license "MS-PL"
:depends-on ("cffi")
:serial t
:components ((:module "libmd"
:components ((:makefile "makefile")))
(:file "package")
(:file "init")
(:file "cephes")))
This works fine, on both MS Windows and UNIX. Adding a method to perform seems to be the most common method on github.
An alternative might be to use a build-op, as described in building a system. The description
Some systems offer operations that are neither loading in the current
image, nor testing. Whichever operation a system is meant to be used
with, you may use it with:
(asdf:make :foobar)
This will invoke build-op, which in turn will depend on the
build-operation for the system, if defined, or load-op if not.
Therefore, for usual Lisp systems that want you to load them, the
above will be equivalent to (asdf:load-system :foobar), but for other
Lisp systems, e.g. one that creates a shell command-line executable,
(asdf:make ...) will do the Right Thing™, whatever that Right Thing™
is.
suggest to me that this is rather close to the idea of building a C library, and it would map nicely to the mental model of using a makefile and the asdf:make command. I didn't find too many examples in the wild of this being used though and technically we are loading the C lib into the existing image.
Another point that could be reconsidered is the detection of an existing shared library to avoid the rebuild. make will avoid recompiling if the shared library exists, but will still call the linker again. This causes errors because it can't write to the shared library when it's in use, at least on MS Windows. The ASDF example used Lisp code to detect the existence of the library and avoiding recompilation, but an alternative might be to use output-files.
The ASDF docs are a bit muddled on the purpose of output-files and there are no examples that make their intentions clear, but in the manual section on creating new operations we have:
output-files If your perform method has any output, you must define a
method for this function. for ASDF to determine where the outputs of
performing operation lie.
which suggests that defining the shared library (libmd.so or libmd.dll) is the recommended way to avoid a recompilation if the output-files already exists.
Finally, the C library could be considered a secondary system, cephes/libmd in this case, and added to the :depends-on clause in the main system. The section on other secondary systems demonstrates building an executable this way, with build-op. Except for the fact that this is building an executable and hard-codes ".exe" it seems to map well onto the use case:
To build an executable, define a system as follows (in this case, it's
a secondary system, but it could also be a primary system). You will
be able to create an executable file foobar-command by evaluating
(asdf:make :foobar/executable):
(defsystem "foobar/executable"
:build-operation program-op
:build-pathname "foobar-command" ;; shell name
:entry-point "foobar::start-foobar" ;; thunk
:depends-on ("foobar")
:components ((:file "main")))
The build-pathname gives the name of the executable; a .exe type will
be automatically added on Windows.
I didn't use this method because the secondary system would look almost exactly like the primary one does now, but would be slightly less understandable.

How to load and use quicklisp program

I've set up quicklisp (with latest SBCL) and done
* (ql:quickload "draw-cons-tree")
and I get the reply
To load "draw-cons-tree":
Load 1 ASDF system:
draw-cons-tree
; Loading "draw-cons-tree"
("draw-cons-tree")
I check my quicklisp directory and I see it's been downloaded, essentially exactly these contents. So how do I actually use draw-cons-tree in the SBCL REPL that I have opened? The github sites says:
* (draw-tree '(a b (c nil 1)))
should produce
[o|o]---[o|o]---[o|/]
| | |
A B [o|o]---[o|o]---[o|/]
| | |
C NIL 1
NIL
but I'm just getting
debugger invoked on a UNDEFINED-FUNCTION in thread
#<THREAD "main thread" RUNNING {10005385B3}>:
The function COMMON-LISP-USER::DRAW-TREE is undefined.
What am I missing here? My only other real experience with quicklisp has been slime, which had a specific .el file to call in Emacs to get slime going. Do I need to drill down into the directory
~/quicklisp/dists/quicklisp/software/draw-cons-tree-20131003-git/draw-cons-tree.lisp
and load the beast each time I want to use it? I tried that and, strangely for me at least, I get a list of WARNINGs of redefined functions, one is draw-tree. So my REPL knows about draw-tree but doesn't? What am I missing here?
Quicklisp loads a system, which may add zero, one or more packages to your environment. Sometimes the names of those packages are easy to guess, like when you install system cl-ppcre, you have a package named "CL-PPCRE" from which you can run things. Sometimes you must read the documentation to know how to use a system you installed.
But in case you are looking for a specific function, then you can use apropos:
CL-USER> (apropos "draw-tree")
DRAW-CONS-TREE::%DRAW-TREE
DRAW-CONS-TREE:DRAW-TREE (fbound)
:DRAW-TREE (bound)
Here, there is one exported symbol, either call it with its name fully qualified:
(DRAW-CONS-TREE:DRAW-TREE ...)
Or use the package first, so that the symbol is accessible from the current package:
> (use-package "DRAW-CONS-TREE")
> (draw-tree ...)
Alternatively, define a new package that uses the package, or go in that package with in-package to have access to its symbols, etc.
See Programming in the Large: Packages and Symbols.

asdf building and Common Lisp

I am having trouble using the asdf build tools with common lisp. Here is my fractals.asd file:
(defpackage :fractals
(:use :cl :asdf :cl-opengl :cl-glu :cl-glut)
(:export :frac-tree :draw-tree))
(in-package :fractals)
;----------------------------------------------------------
(defsystem fractals
:name "fractals"
:version "0.0.0"
:serial t
:components ((:file "frac-tree")
(:file "fractal-lab")))
Both the ffiles fract-tree.lisp and fractal-lab.lisp have the statement (in-package :fractals) at the very beginning of the file. However, I am automatically getting an error saying The name "CL-OPENGL" does not designate any package. I don't understand why this is wrong. Furthermore, if I don't include these libraries, then I have to manually require them myself... I created a directory called: ~/.config/common-lisp/source-registry.conf.d/ where I placed a file called fractals2.conf which contains the following:
(:directory "~/lisp_proj/fractals2/")
This is the directory of my fractals.asd file as shown above. Apparently, this is supposed to tell asdf where my user-defined systems are located. I followed this tutorial.
In summary, how can I get asdf to find my user-defined systems so that I do not have to manually load them?
Thanks for all the help!
You need to declare your dependencies in the defsystem with a :depends-on clause. The :use clause of the defpackage only makes names of already loaded packages available, but won't load them.
BTW, your .asd file should not include the defpackage of the main package. While it makes sense to declare a special package to run the defsystems in there, regular packages should be declared in .lisp files.
EDIT: This may also solve your second problem. If not, it's probably because ASDF doesn't automatically expand the ~ character in paths. In that case, replace it with the actual path of your home directory.
1- Looks like you were using the undefined fractals:defsystem instead of asdf:defsystem
2- the ASDF DSL accepts the directive (:directory (:home "lisp_proj/fractals_2"))
3- Starting with 3.1.2, you can put everything under ~/common-lisp/
4- For God's Sake, RTFM!

CL and SWIG: working example?

Doing a SWIG tutorial, and using the example.c, example.i as they provided there. I generated lisp file with swig -cffi example.i.
But when I run test.lisp with SBCL, i get a complaint about undefined alien function, as well as complaints when compiling the example.lisp itself. I'm pretty sure I still have to compile my example.c into a library and then somehow tell SBCL to load it! But the docs are very scant on this, except for this.
Can somebody tell me how to do this or is there a better way than SWIG to automatically generate CFFI bindings from C/C++ sources??
sbcl output:
...
;
; caught STYLE-WARNING:
; Undefined alien: "fact"
;
; compilation unit finished
; caught 1 STYLE-WARNING condition
;
; caught STYLE-WARNING:
; Undefined alien: "my_mod"
...
test.lisp
;call C functions defined in example.c
(require :cffi)
;;;(require :example "example.lisp")
(load "example.lisp")
(fact 2)
(quit)
First, you need to compile the C library. Do something like:
gcc -shared example.c -o libexample.so
Of course, for a complex existing library compilation could be considerably more complex -- if you're wrapping an existing library, it probably comes with some sort of Makefile to help you build it.
Then, in Lisp, use CFFI to define and load the library. This seems to be the main part that you're missing.
(cffi:define-foreign-library libexample
(t (:default "libexample"))) ;; note no .so suffix here
(cffi:use-foreign-library libexample)
This part:
(t (:default "libexample"))
is a conditional which you can use to give different loading instructions for different platforms. (t ...) is the catchall option, much like with COND. You can find the exact syntax in the documentation for define-foreign-library.
You would now normally use cffi:defcfun and so on to define the functions in the library. This is what the SWIG-generated file does for you, so load it:
(load "example.lisp")
You can now call the functions as normal Lisp functions:
(fact 5)
=> 120

Why can I not access my Leiningen dependencies with Clojure code?

In Clojure, if I want to pull in the clojure.inspector functions, I can go like this:
(use `[clojure.math.numeric-tower :include (expt)])
From the REPL, and I can now evaluate the function expt.
However, it seems to me that there should be (and probably is) another way to do it - pulling in the code using Leiningen dependencies.
I add this line to my project.clj:
[org.clojure/math.numeric-tower "0.0.2"]
And I restart the REPL to pull in the new dependency. I even do "lein deps" to be safe (there is no output for that command). When I try to evaluate expt, it gives me a RuntimeException, and says its Unable to resolve the symbol.
How can I access the expt function, only using Leiningen dependencies?
You can't. It doesn't work like that. Adding a dependency puts the code on your classpath, which merely means it is available for you to use. In order to actually use the things inside the namespaces, you need to use
(require '[the-namespace :refer [the things you want to use]])
or
(require '[the-namespace :as tn])
(tn/somevar)
or do either of those things in an ns declaration (when not in the REPL and working with a file)
(ns foo
(:require [the-namespace :as tn]))

Resources