General Lisp Source Code Organization

I am new to CL and am using AllegroCL. I am trying to figure out how to organize the source code to meet the following requirements:

  • I want src code not to include my test packages.
  • I want to declare project dependencies (both src and test deps) in a portable way so that other members of my team do not have to change their systems.
  • I want to facilitate continuous integration during registration, including both assembly and tests.

I am trying to creatively use ASDF to meet these requirements, and I cannot get it right. How do other people approach this problem? Are these 2 requirements just not "Lispy"?

+7
source share
5 answers

Use ASDF or use the defsystem Allegro CL tool.

  • make them two different systems. The test suite system is software dependent.
  • Use relative paths, calculate absolute paths based on the location of the system definition file or the pro version, use logical path names (which are CL path names that can be reassigned according to the rules).
  • There may be a Common Lisp continuous integration tool, but I haven't used it yet. Having a defsystem description is a good start.
+5
source

I use quicklisp, which makes a "quicklisp" panel in your home folder, in which the "local project" folder can be found. This file contains the txt file into which you can insert the URIs into the .asd files.

How to use this utility:

  • create "project.asd" and "project-test.asd" in the project folder

project.asd (controls inclusions for clean project code)

(asdf:defsystem :project-name :description "description here" :version "version here" :author "your name here" :depends-on (:a :list :of :dependencie :libraries) :components ((:file "sourcefileone") (:file "sourcefiletwo"))) 

project-test.asd (controls inclusions for test code)

 (asdf:defsystem :project-name-test :description "testing" ... :depends-on (:project-name) :components ((:file "sourcefileone-test") (:file "sourcefiletwo-test"))) 
  • now insert the URI for these files into the aforementioned local-projects.txt file

  • the program is parallel to the project source in <filename> .lisp and test calls in <filename> -test.lisp (* -test.lisp files must contain a test execution call)

  • run your sbcl or whatever you use and then use (ql:quickload "project-name") or (ql:quickload "project-name-test") depending on whether you just want to download the project or test it .

The only thing you need to do to transfer this elsewhere is to write the local-projects.txt file on the computer on which the project is copied. After that, your colleges can depend on it using asdf files and quick downloads in any other project they want. You can use ctr + c / v to copy the project folder, or perhaps something more complex like git.

For testing, I programmed my own small set of tests, but I'm sure there are good ones. More information about quicklisp can be found here and about asdf here . Perhaps this question may help you if you are stuck in setting up quicklisp.

+5
source

If Quicklisp is installed, you can use the built-in Quickproject function.

 (ql:quickload "quickproject") (quickproject:make-project "~/src/lisp/swatchblade/" :depends-on '(vecto hunchentoot)) 

This creates 4 files:

  • package.lisp
  • swatchblade.lisp
  • swatchblade.asd
  • README.txt

package.lisp defines package namespaces:

 (defpackage #:swatchblade (:use #:cl) (:shadowing-import-from #:vecto #:with-canvas #:rounded-rectangle #:set-rgb-fill #:save-png-stream)) 

swatchblade.asd defines the system / project, source files, dependencies, etc.

 (asdf:defsystem #:swatchblade :serial t :depends-on (#:vecto #:hunchentoot #:cl-colors) :components ((:file "package") (:file "swatchblade"))) 

swatchblade.lisp is the source code.

You can download the project via QuickLisp quickload:

 * (ql:quickload "swatchblade") loading output * (swatchblade:start-web-server :port 8080) Server started on port 8080. 

If you then create another project that depends on the swatchblade system:

 quickproject:make-project "~/src/lisp/whimsytron/" :depends-on '(swatchblade)) 

As for the tests, you can add another namespace to package.lisp for your tests:

  (defpackage #:swatchblade-tests (:use #:cl #:swatchblade)) 

Create a test file, write the code and add the file to the system definition:

 (asdf:defsystem #:swatchblade :serial t :depends-on (#:vecto #:hunchentoot #:cl-colors) :components ((:file "package") (:file "swatchblade") (:file "swatchglade-tests"))) 

Download the swatchblade-tests namespace to run the tests.

Example project with tests here

If you want Quicklisp to not install all the dependencies on the system, you will need to install the dependencies and load the system manually, as far as I know.

The author of Quicklisp, Zach Beane, has a more detailed post on using quickproject .

+5
source

At the suggestion of Rainer, I suggest you use the ASDF system definition tool to define two systems, your main system, foo, and the auxiliary systems of the auxiliary system.

In the foo system definition, add a specification in which in-order-to run test-op on foo, you need to run test-op in foo-tests. This ensures that if you execute (asdf:test-system "foo") , the corresponding test system with its dependencies will be loaded, and then ASDF will execute the test op.

I believe FiveAM is an adequate library for building tests.

Everything will be loaded above, but now you need to make sure that running test-op on foo-tests really runs the tests! To do this, you need to add the PERFORM method for test-op and (eql (find-system "foo-tests")) . This PERFORM method should call all the FiveAM tests you described and either succeed or raise an error if the tests fail.

I made the addition of 5 AM-tester for ASDF. I will try to see how to make it public.

+4
source

IMPORTANT

The advice above is good, but you will be disappointed in trying to check things that are not exportable. A simple approach is not to define two packages. Just put your tests in the same package with other sources. What harm?

If you think there will be harm, then you will need to do it like this:

 (defpackage #:sources (:use #:cl)) (defpackage #:tests (:use #:cl #:lisp-unit) (:import-from #:sources)) 

The important part is :import-from your source package instead of :use ing.

Then you will have to qualify the characters in the source package when you use them in your test package. For example, let's say that you have this function:

 (defun return-true () t) 

Your test might look like this:

 (define-test test-return-true "Make sure it works" (assert-equal t (sources::return-true))) 

The important part is that you say (sources::return-true) instead of just (return-true) . The same applies to characters like 'sym ; refer to it as 'sources::sym .

+1
source

All Articles