I have small common lisp project that uses lispbuilder-sdl. I'd like to make a fork of lispbuilder-sdl, put it into subdirectory and remove some stuff I don't need from it.
How can I do that?
As far as I know, quicklisp can load projects that are within current directory, within "local-projects" directory (in whatever folder quicklisp installed itself into), or downloads them from the internet. So how do I make a "subproject" that is a fork of existing project (that is available via quickload?) without polluting top-level directory with *.asd files?
--additional info--
I'm using 32bit clozure-cl on windows 7 64bit.
Currently project starts using this file:
(ql:quickload "cffi")
(pushnew #P"bin/" cffi:*foreign-library-directories* :test #'equal)
(pushnew #P"build/bin/" cffi:*foreign-library-directories* :test #'equal)
(pushnew #P"build/bin/Debug/" cffi:*foreign-library-directories* :test #'equal)
(ql:quickload "game")
(defun start ()
(game:main))
(defun reload ()
(ql:quickload "game"))
(defun restart ()
(reload)
(game:main))
(start)
(quit)
game.asd is located within current directory, dependencies are downloaded into quicklisp directory and are loaded from there.
Any project you put into the local-projects folder will override the Quicklisp-supplied version. That is the easiest way to use a modified version of a project.
You can find out where Quicklisp gets a project by checking https://github.com/quicklisp/quicklisp-projects. For example, lispbuilder upstream info comes from https://github.com/quicklisp/quicklisp-projects/blob/master/lispbuilder/source.txt.
Related
I use ADSF to organise my projects.
(asdf:defsystem :sender
:version "0.1.4"
:serial t
:depends-on (:cl-json :dexador :clsql :clsql-sqlite3)
:components ((:file "packages")
(:file "validation")
(:file "sender")))
But when I open a new repl (slime, emacs), I have to go to the packages.lisp file and evaluate the form before I can change the repl to that package with (in-package :sender).
Is there a way to make the slime repl remember my packages?
My current thinking is that I need to "run" adsf to load all my files. If so, how?
UPDATE:
Actually, I need to compile all the files manually before I can actively use them in the repl. I believe I am using asdf incorrectly.
From a .asd system definition, the steps would be:
compile the .asd file, so that you Lisp image knows about the system
C-c C-k or programmatically: (asdf:load-asd "system").
LOAD it somehow: (ql:quickload "system") to install dependencies
or (asdf:load-system "system"), but it will fail if your project has unknown dependencies, Quicklisp would download them.
avoid using cl:load for asdf systems, load-asd / load-system will do more complex stuff.
use it on the REPL. The package that was defined in a packages.lisp file should be available, because this file was declared in the .asd.
You can add stuff to your ~/.sbclrc (or similar for other implementations). Here I tell ASDF where a project lives, so I can quickload it without manually compiling the .asd before:
(pushnew "/home/vince/projets/ciel/" asdf:*central-registry* :test #'equal)
This is an "old" style not encouraged anymore by the ASDF documentation.
Or simply create a symlink for your project to ~/quicklisp/local-projects/ or ~/common-lisp/.
I wouldn't "load-system" my project in the init file, because that's a side effect that would show sometimes when I don't want it (like building an image: if that involves reading my init file, I'd have an unwanted system in it).
Saving a core image with a ton of dependencies is cool. Use it with sbcl --core …. The advantage is that it starts up instantly in the REPL, when loading all projects and dependencies would take a few seconds.
Pointers
ASDF
ASDF cookbook
ASDF manual
ASDF best practices
ASDF Build System explained
Overview
A system is an object which describes a library (or an application) which consists of: a name, a version, a list of files and subsystems, and a list of other systems it depends on. There is more.
If you want to have Lisp know a certain system, then we need to execute its defsystem form either manually or find it automatically. That ONLY makes the system definition known.
If you want to load the system's files, then you need to LOAD the SYSTEM. If you want to compile the system's files files, the you need to COMPILE the system.
So, if you want to use a package (which is a namespace), then you need to run the DEFPACKAGE form. If that form is describe in a file which is component of a system, then you need to load that system.
ASDF : a popular build system for Common Lisp
system -> library, application. It is a bunch of files and dependencies.
system definition -> not the system itself, but a description of it. Use DEFSYSTEM to describe a system
system operations -> like load-system, compile-system and others.
system registry -> Typically we want ASDF to find the systems by name. See the manual or a tutorial for ASDF.
lisp file -> some file we can compile or load
fasl file -> some compiled file we can load
package -> a namespace for symbols, that's actually a built-in feature for Common Lisp
Quicklisp -> a library manager with a selection of curated Common Lisp libraries/applications. The libraries can be loaded over the Internet. Be aware that there is little to no security when loading foreign code from the Internet.
Use a system, its components and dependencies
If you want to use a system you need to load it first. Manually or automatically.
That loading can be done automatically:
For example in an init-file for your Lisp you can load all systems you want/need. Alternative write a function which loads all systems you want.
saving an image. Some Lisps support saving an image. Thus one can load all interesting systems and then save an image. If one starts that image later, all those systems are already in memory. (side problem: getting newer versions loaded)
Is there anything like file in shell for lisp to determine file type? If not, how do you determine file tpye?
In most case pathname-type is good enough, but sometimes you may run into some files doesn't have been correct named.
The functionality of file is available in libmagic:
As of version 4.00 of the Ian Darwin/Christos Zoulas version of file, the functionality of file is incorporated into a libmagic library that is accessible via C (and C-compatible) linking;[7][8] file is implemented using that library.
Wikipedia
And there is a binding for Common Lisp.
I had to install libmagic-dev on my system, and then:
CL-USER> (ql:quickload :magicffi)
...
(:MAGICFFI)
CL-USER> (magicffi:pathname-mime #P"/bin/ls")
"application/x-sharedlib; charset=binary"
See MAGICFFI.
I'm new to CL and I can't figure out how to build binaries from my simple project.
I've created app.asd file with following contents:
(asdf:defsystem game
:version "0.0.1"
:components ((:file "package")
(:file "main")))
package.lisp contents
(defpackage :app
(:use :common-lisp :asdf)
(:export :start))
and main.lisp
(in-package :app)
(defun start (args)
(format t "Hello"))
I've also symlinked app.asd to ~/quicklisp/quicklisp/app.asd, and when I execute
(require 'asdf)
(asdf:operate 'asdf:load-op :app)
it looks like something compiles, but I can't find binaries/object files anywhere.
How do I build my project so I can copy it to another machine without CL installed and run?
I'm using sbcl 1.1.13 and asdf 3.0.2 on osx.
Don't put .asd files in ~/quicklisp/quicklisp/. Use ~/quicklisp/local-projects/ instead.
The syntax for your start defun is wrong. It needs a lambda list.
Common Lisp is often used by starting the environment, loading the application, and then interactively calling functions defined by your application. The load process compiles the source code to machine code and the functions you call interactively are compiled functions.
When I want to make a binary file I can run from the command line, I use buildapp. In your case, you could do something like this:
sbcl --no-userinit --no-sysinit --non-interactive --load ~/quicklisp/setup.lisp \
--eval '(ql:write-asdf-manifest-file "systems.txt")'
buildapp --manifest-file systems.txt \
--manifest-file ~/quicklisp/local-projects/system-index.txt \
--load-system game \
--entry app::start \
--output game
In this scheme, you would have to modify app::start to accept one argument, a list containing all the command line argument strings passed to game.
In general, most Common Lisps have some way to produce a binary program to run independently of the normal runtime. The terminology varies, but it's often called "delivery". If you use a different Common Lisp in the future, you may get more information if you search the documentation for information about delivery.
I am trying to load my project using a self-made .asd file, but somehow asdf does not recognize that the .asd file should also be the root-directory of the project and therefore resuling in an error like failed to find the TRUENAME of /home/$USER/rel-path-to-file where rel-path-to-file is the path to the corresponding file, relative to the loaded .asd file.
This is what I did:
(push "path-to-project-directory-of-asd-file" asdf:*central-registry*)
then
(asdf:load-system 'project-name)
It DOES find my .asd file but somehow not the .lisp files it shall load.
The asdf has been configured and installed by quicklisp. Therefore I also "installed" the project into quicklisp using a symlink, this worked as well. It DOES find the .asd file using ql:quickload :name but still doesn't use the directory containing the .asd file as the project-root.
How can I fix this?
Lisp pathnames are historically such that they require you to add a slash after directory name (I was told this is so due to the operating systems which were created before I was even born), so in order to tell Lisp that you target a directory you must end the name with the slash.
See asdf:system-relative-pathname.
I am new to cl, and I just learned to install packages using asdf-install, but I don't know how it works, I wonder how the package can be installed manully, then I could understand the use of the files in the root directory of the source code, thanks.
Short answer: Just use quicklisp.
Long answer: if you want to understand, how the package, or - more precisely - ASDF system, is laid out, that's a good idea. Actually, there's nothing hard about that.
Every ASDF system should have a system definition file with .asd extension. This file names other file of the system with their paths relative to the .asd file, their types (by default: lisp source code) and dependencies. Your Lisp should know where to find the system definition file. In ASDF there are 2 ways to inform Lisp about it: adding the directory, in which you store the file or symlink to it, to asdf:*central-registry* list or setting up special configuration files (called source-registry - more on that in ASDF manual).
Now if you want to install the system by hand, just download its sources, extract them into some directory (like in /home/user/lib/lisp/ - you may get /home/user/lib/lisp/cl-ppcre-2.3.1/, inside which there's cl-ppcre.asd). To let your Lisp find out about it just (push "/home/user/lib/lisp/cl-ppcre-2.3.1/" asdf:*central-registry*) (and don't forget the trailing slash - it's required), and then you can load the system with (asdf:oos 'asdf:load-op :cl-ppcre).
You might also setup a special dir, where you'll symlink your existing systems, like /home/user/.lisp/ and add it to *central-registry* at Lisp startup type (e.g. in .sbclrc). Now if you want to temporarily override some of the system linked in this dir, say, with a newer version, you don't need to unlink anything - just push the path to alternative system to *central-registry*.
Quicklisp does all that for you and more...