首页 > Lisp > 使用ASDF构建Common Lisp程序包

使用ASDF构建Common Lisp程序包

2011年12月13日 发表评论 阅读评论 14,051 人阅读过  

在切入正题之前先写点不相关的,工作确定之后便开始忙论文的事,忙里偷闲总想搞点什么以做娱乐,不得不说,腾讯面试官说过的要精通两到三门不同的语言我印象很深刻,自己也想尝试一下新东西,VIM让我审美疲劳了,也想尝试一下Emacs,机缘巧合由田春老师翻译的《实用Common Lisp编程》刚上市不久,Emacs和Lisp也有不少渊源,再加上Lisp作为一门生命持久的元老级别的语言,至今仍然能倍受广大黑客的推崇,我相信它一定有学习的价值,而且Hadoop的MapReduce据说也是受Lisp的map和reduce函数的启发而来,相信对于Lisp的学习肯定不会是浪费时间,尽管将来工作中应用Lisp的机会可能很少,但深入学习的话肯定会对自己有一定的启发和帮助。

于是几乎同一时间我开始尝试使用Emacs并在卓越上订购了中文版的《实用Common Lisp编程》,抽空阅读尝试。总起来说这本书是非常不错的,几乎是面面俱到,但有些我认为也很有用的宏如defstruct,deftype,check-type等书中没有给出相关介绍,另外关于cl的package书中有一章节专门讲了定义的规则,但对于package的管理及安装并没有提及,我个人觉得如果是practical编程的话提一下cl中重要的ASDF包管理工具还是很有必要的,既然书中没有提到就得自己通过其它的渠道去了解学习,这方面中文的资料相对较少,大多数的资料都是在外文网站上查到的,当然也包括到stackoverflow上的提问。

ASDF全称是Another System Definition Facility,asdf这个组合很有意思,正好和左手的键盘基本按键重合,当初还以为是作者很有个性地起了这个随意的名字呢。我个人的理解是ASDF是类似于automake或者cmake的工具,提供一种程序包的管理方法和工具,因此也没什么复杂的地方,只不过有一些基本的规则需要遵守,了解了就没什么了。

程序包中一般会有一个.asd文件,该文件定义了程序包中源码文件的组织方式及依赖关系,类似于cmake中的CMakelists.txt,当然该文的编码方式是使用lisp风格的。

1. asdf工具的安装配置。
目前存在的common lisp实现有很多,在这篇文章中有介绍:Common Lisp Implementations: A Survey,免费的common lisp实现中性能比较好使用也比较简单的应该属sbcl了,《practical common lisp》也推荐了sbcl,作为一个新手我第一选择当然也选了sbcl,在sbcl中已经集成了asdf工具,无需再手动安装,但安装方法也很简单,可以参考ASDF Manual,该手册对asdf有详细的介绍。

2. asdf包的编译加载。
asdf是一个工具集,可以对包进行各种操作,其中包括编译,加载等。asdf对于包的编译和加载等操作都需要基于.asd文件,也就是说编译某个包asdf需要先找到该包对应的.asd文件,该文件一般是存放在源码根目录中的,asdf对于该文件的寻址有两种方式,new style和old style,下面分别简单介绍下这两种方式:

old style是为了兼容旧版本的程序的,目前已经不推荐新程序使用,其方法是将程序包的.asd文件所存在的路径添加到asdf的*central-registry*变量中,可使用如下语句完成该操作:

(push "/home/levin/lisp/spider/" asdf:*central-registry*)

上述操作便可将/home/levin/lisp/spider/(注意结尾的’/')这个路径添加到*central-registry*变量中,这样asdf便可对该包进行寻址,但在REPL中执行的该操作只对当前的会话有效的,REPL重启后需要重新添加路径到该变量中,未免有些繁琐,可以将该语句添加至common lisp实现的启动文件中,如sbcl即为.sbclrc这个文件,这样在REPL启动之后该路径便会自动添加到*central-registry*变量中。

new style是ASDF2所提倡使用的方法,其方法是在~/.config/中创建common-lisp目录用于存放相关的配置文件,和该主题相关的配置文件需要创建一个名为source-registry.conf.d的目录,在该目录下可以创建文件名任意的文件,将下面的语句添加至该文件中即可,文件如:

~/.config/common-lisp/source-registry.conf.d/01-spider-source.conf

(:directory "/home/lisp/lisp/spider/")

如上表示在/home/lisp/lisp/spider/这个目录中查找.asd文件,也可以将:directory替换成:tree,使asdf在目录中递归寻找.asd文件:

(:tree "/home/lisp/lisp/spider/")

完成对asdf包的寻址操作之后,便可以使用asdf对程序包进行编译加载,编译和加载包分别可使用:

CL-USER> (asdf:compile-system :spider)
CL-USER> (asdf:load-system :spider)

也可以使用asdf的operate对包进行编译和加载:

CL-USER> (asdf:oos 'asdf:compile-op :spider)
CL-USER> (asdf:oos 'asdf:load-op :spider)

对于一个未经编译完成的包在编译完成会自动加载,同样,未编译完成的包在加载时也会自动先进行编译。

3. asdf系统的构建:

之前提到的.asd文件是asdf的很重要的文件,该文件最简单的形式如下:

(defpackage :spider-system
  (:use :cl :asdf))
(in-package :spider-system)
 
(defsystem spider
  :name "spider"
  :author "levin li"
  :version "0.0.1"
  :license "MIT"
  :description "A spider program."
  :depends-on (:iolib)
  :components ((:file "package")
               (:file "spider" :depends-on ("package"))))

最开头的包定义是为了防止system名与其它包冲突,定义的包中包含一些基本信息,:depends-on声明了该程序将要依赖的包的,:components定义了包中的组件,即源代码,上述的源码包中只有两个文件,package.lisp和spider.lisp,package.lisp是定义一个cl package,可以理解为其它语言中的namespace,package.lisp定义了一个package,之后的程序如spider.lisp可能都会包含在该包中,因此:depends-on(“package”)这句话就非常重要,它会在编译spider.lisp之前先加载已经编译的好的package.lisp,若未声明spider依赖package,则在一次编译完成后REPL重启并对spider.lisp进行修改,而package.lisp未加改动,则asdf只会编译修改过的spider.lisp,这时候系统会提示spider包未找到,因为asdf发现package.lisp的目标文件是最新的,默认不会对其进行编译和加载,这也是我刚开始遇到的问题之一,在认真读了ASDF Manual后才解决了这个问题,关于该文件的一些详细的定义可以参考ASDF Manual。

package.lisp的内容如下:

(in-package :cl-user)
 
(defpackage :spider
  (:use :cl :iolib)
  (:export :send-request
           :test))

其中定义了包的名称,包的依赖的其它包,及要导出的符号等,关于package的更多介绍还是参考《practical common lisp》等资料。而spider.lisp是代码文件,开头需要有一行:

(in-package :spider)

表明当前程序包在spider包中定义,继而可以在spider.lisp中编写其它的逻辑代码,定义函数,宏或变量,所有的这些定义都被包含在包spider中,其中只有在package.lisp中声明为:export的符号才可以被其它包所引用,如上定义,该包中只有send-request和test两个函数可以被其它外部包引用。

4. asdf包的安装

绝大多数的common lisp包都是使用asdf组织的,可以使用asdf-install工具安装软件包,asdf-install使用之前需要先加载:

CL-USER> (asdf:oos 'asdf:load-op :asdf-install)

之后便可以使用asdf-install安装软件包,一般而言有三种方式:

1. 通过包的名字进行安装:

CL-USER> (asdf-install:install "iolib")

这时asdf-install会自动从cliki.net上下载可用的包并安装,http://www.cliki.net/asdf-install这个页面列出了在线可用的软件包的列表。

2. 通过包的url进行安装:

CL-USER> (asdf-install:install "http://weitz.de/files/cl-ppcre.tar.gz")

3. 通过包的本地路径进行安装:
CL-USER> (asdf-install:install “/home/levin/lisp/iolib.tar.gz”)

更加详细的安装方法可以参考asdf-install turorial.

原创文章,转载请注明: 转载自basic coder

本文链接地址: http://basiccoder.com/constructing-common-lisp-package-by-asdf.html

分类: Lisp 标签: , ,
  1. 2011年12月13日12:22 | #1

    以前看Practical Common Lisp的时候没有中译版,大概看了200页,然后看不下去了。。有空一定再看看。

    • 2011年12月13日12:25 | #2

      推荐看英文版,我看中文版看到一半看不下去了,然后转去看英文版了,中译版有些长句翻译的有点生硬,相比于英文原版有些难懂

  2. 2011年12月14日15:13 | #3
  3. nick_lhy
    2011年12月21日19:54 | #4

    我最近也刚买这本书,崇拜Lisp好久好久了。。

  4. 2012年2月7日20:06 | #5

    这个是linux上安装的吧,有在windows上试过吗,我在Windows上运行
    (asdf-install:install “e:/emacs/l/zip.tgz”)直接弹出
    Couldn’t execute “tar”: No such file or directory
    [Condition of type SIMPLE-ERROR]
    如果从远程安装的话(asdf-install:install ‘zip)
    会弹出这样的错误
    Server responded 404 for GET http://common-lisp.net/project/zip/zip.tgz.asc
    [Condition of type ASDF-INSTALL::DOWNLOAD-ERROR]

    不知道你遇见过没有的 这样的问题了 谢谢!!
    我也正在看田春翻译的那本书了,感觉在这些库的安装使用上,书中确实没有讲多少的。

  5. 2012年2月8日15:31 | #6

    @jasper 试试quicklisp?不行的话就手工安装 P.S. windows我没试过…

  6. a
    2012年5月3日19:24 | #7

    sw2wolf :
    http://www.quicklisp.org/

    不错的 能自动下载依赖的包自动安装

  1. 本文目前尚无任何 trackbacks 和 pingbacks.

注意: 评论者允许使用'@user空格'的方式将自己的评论通知另外评论者。例如, ABC是本文的评论者之一,则使用'@ABC '(不包括单引号)将会自动将您的评论发送给ABC。使用'@all ',将会将评论发送给之前所有其它评论者。请务必注意user必须和评论者名相匹配(大小写一致)。