Common Lisp源代码组织

时间:2012-08-15 15:01:21

标签: common-lisp asdf

我是CL的新手,正在使用AllegroCL。我正在试图弄清楚如何组织我的源代码以满足以下要求:

  1. 我想阻止src代码包含我的测试套件。
  2. 我想以可移植的方式声明项目依赖项(src和test deps),以便团队中的其他成员不必修改他们的系统。
  3. 我想简化签到时的持续集成,包括构建和测试。
  4. 我一直在努力创造性地使用ASDF来满足这些要求,但我无法做到这一点。其他人如何解决这个问题?这两个要求是不是“Lispy”?

5 个答案:

答案 0 :(得分:5)

使用ASDF或使用Allegro CL defsystem工具。

  1. 使他们成为两个不同的系统。测试套件系统取决于软件系统。
  2. 使用相对路径名,根据系统定义文件的位置计算绝对路径名,或者'pro'版本,使用逻辑路径名(可以根据规则重新映射CL中的路径名)。
  3. 可能有一个针对Common Lisp的持续集成工具,但我还没有使用过任何工具。有一个defsystem描述是一个良好的开端。

答案 1 :(得分:5)

我正在使用quicklisp在你的主文件夹中创建一个“quicklisp”文件夹,其中可以找到“local-project”文件夹。这个包含一个txt文件,您可以在其中将URI插入.asd文件。

如何使用该实用程序:

  • 在项目文件夹
  • 中创建“project.asd”和“project-test.asd”

project.asd(管理纯项目代码的包含)

(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(管理测试代码的包含)

(asdf:defsystem :project-name-test
  :description "testing"
  ...
  :depends-on (:project-name)
  :components ((:file "sourcefileone-test")
               (:file "sourcefiletwo-test")))
  • 现在将这些文件的URI插入上面名为local-projects.txt的

  • 程序并行项目源与< filename> .lisp文件和<中的测试调用filename> -test.lisp文件(* -test.lisp文件必须包含测试执行调用)

  • 启动您的sbcl或您使用的任何内容,然后使用(ql:quickload "project-name")(ql:quickload "project-name-test"),具体取决于您是否只想加载项目或进行测试。

在其他任何地方移植它的唯一方法就是在复制项目的计算机上编写local-projects.txt。之后,您的大学可能会依赖于它使用asdf文件和快速加载他们想要的任何其他项目。要复制项目文件夹,您可以使用ctr + c / v,也可以使用更复杂的git。

为了测试我编写了自己的小型测试套件,但我打赌那里有好的测试套件。 有关quicklisp的更多信息,请访问here和asdf here。如果您遇到快速配置,请{} this question可以帮助您。

答案 2 :(得分:5)

如果安装了Quicklisp,您可以使用内置功能Quickproject。

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

这会创建4个文件:

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

package.lisp定义包命名空间:

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

swatchblade.asd定义了系统/项目,源代码文件,依赖项等。

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

swatchblade.lisp是源代码所在的位置。

您可以通过Quicklisp的快速加载项目加载项目:

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

如果您随后创建了另一个依赖于swatchblade系统的项目:

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

关于测试,您可以在package.lisp中为测试添加另一个命名空间:

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

创建测试文件,编写代码,并将文件添加到系统定义中:

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

加载 swatchblade-tests 命名空间以运行测试。

Sample project with tests here

如果你想避免Quicklisp将所有依赖项安装到系统中,你必须安装依赖项并手动加载系统。

Quicklisp的作者Zach Beane在using quickproject上有更详细的帖子。

答案 3 :(得分:4)

根据Per Rainer的建议,我建议您使用ASDF系统定义工具来定义两个系统,主系统 foo 和辅助系统 foo-tests

foo 系统的定义中,添加in-order-to foo 上执行test-op的规范,您需要执行 foo-tests 上的test-op。这确保了如果执行(asdf:test-system "foo"),将加载相应的测试系统及其依赖项,然后ASDF将执行测试操作。

我发现FiveAM是一个适合构建测试的库。

以上内容将加载所有内容,但现在您需要确保在 foo-tests 上执行test-op实际运行测试!为此,您需要在PERFORMTEST-OP的{​​{1}}上添加方法。 (eql (find-system "foo-tests"))方法应该调用您定义的所有FiveAM测试,并且要么成功,要么在测试失败时引发错误。

我已为ASDF制作了一个FiveAM测试人员插件。我将尝试将其公之于众。

答案 4 :(得分:1)

重要

上面的建议很好,但是你试图测试未出口的东西会很沮丧。一个简单的解决方法是不定义两个包。只需将您的测试与其他来源放在同一个包中即可。有什么危害?

如果您认为会有伤害,那么您必须这样做:

(defpackage #:sources
  (:use #:cl))

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

重要的是:import-from您的源包而不是:use

然后,当您在测试包中使用符号时,必须对源包中的符号进行限定。例如,假设你有这个功能:

(defun return-true () t)

您的测试可能如下所示:

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

重要的是你说(sources::return-true)而不仅仅是(return-true)。像'sym这样的符号也是如此;将其称为'sources::sym