使用asdf可以加载只提供以前制作的fasl的系统



我有一台开发机器和一台生产机器,它们是相同的(vm映像的副本)。我想将应用程序与asd文件一起交付给生产机器,但我不想交付源代码。我想到了两种方法:

1。让asdf通过只提供生产机器中的FASL文件来加载系统

优点:当我需要改变一些东西时,我只需要在开发机中编译文件,然后在生产机中替换fasl。

缺点:我不知道是否可以做到,也不知道如何做到。

2。使用save- lip -and-die,或者最好是Zachary Beane的builapp工具(我使用的是SBCL)来自动化这个过程。

优点:更容易自动化,更简洁,只有一个(尽管很大)文件交付。

缺点:前一个解决方案的优点。

我知道我提到的优点和缺点相比起来并不那么重要,但是我想知道任何我认为可能改变我选择的优点或缺点,或者任何我没有想到的其他解决方案。此外,无论我选择什么,我都想知道解决方案1是否可行,以及如何可行。

我目前维持ASDF。我不知道ASDF是否允许。我不是为这个设计的。也就是说,我从来没有尝试过,也不能保证它不会,或者一个简单的黑客不会让你做到这一点。我欢迎这样的入侵ASDF和/或扩展。

在最坏的情况下,如果ASDF不允许您这样做,一个"简单"的hack将是创建包含(eval-when (:compile-top - level:load-top - level:execute)(错误提示"这不是真正的源文件")的文件,并给它们一个1970-01-01的时间戳来代替您的源文件。一个脚本就可以为你做到这一点,聪明的破解你的源代码注册表可以让你在真实的源代码和虚假的源代码之间切换。

好运。

通常这些系统工具应该允许这样做。您所需要的只是系统描述和FASL文件。然后,系统工具应该使用FASL文件进行加载。我们只需要确保它没有硬依赖于某个源文件。

软件以这种方式在Lisp世界交付了几十年(> 30年)。这种方法并没有错。如果一个特定的工具(这里是ASDF,但也有其他工具)在这方面有问题,人们应该向作者投诉。

如果你对它有实际问题,你应该在ASDF邮件列表上讨论它,或者在这里发布一个问题。你对它有什么实际问题吗?

这不会直接帮助你,但它可能会给你一些提示,告诉你一个系统工具通常是如何工作的。

使用LispWorks 6和它自己的DEFSYSTEM的例子

目录FOO中有三个文件:

RJMBA:foo joswig$ ls -l
-rw-r--r--  1 joswig  admin    13 22 Jul 20:42 a.lisp
-rw-r--r--  1 joswig  admin    14 22 Jul 20:42 b.lisp
-rw-r--r--  1 joswig  admin   331 22 Jul 20:41 system.lisp

系统。Lisp包含以下系统描述:

(defvar *foo-directory*
   (make-pathname :name nil
                  :type nil
                  :directory (pathname-directory *load-pathname*)
                  :defaults *load-pathname*))
(defsystem foo (:default-pathname *foo-directory*)
   :members ("a" "b"))
上面的

根据加载文件的路径名设置*foo-directory*路径名。因此,我们可以设置一个真正的绝对路径名,而不必手动指定它。或者,我们可以使用相对路径名——这取决于你想要使用什么。我选择这个是为了展示如何自动设置绝对路径名。

现在我将这个文件加载到LispWorks中,然后编译系统:

CL-USER 12 > (compile-system 'foo)
;;; Compiling file /Lisp/foo/a.lisp ...
;;; Safety = 3, Speed = 1, Space = 1, Float = 1, Interruptible = 1
;;; Compilation speed = 1, Debug = 2, Fixnum safety = 3
;;; Source level debugging is on
;;; Source file recording is  on
;;; Cross referencing is on
; (TOP-LEVEL-FORM 0)
; (TOP-LEVEL-FORM 1)
;; Processing Cross Reference Information
;;; Compiling file /Lisp/foo/b.lisp ...
;;; Safety = 3, Speed = 1, Space = 1, Float = 1, Interruptible = 1
;;; Compilation speed = 1, Debug = 2, Fixnum safety = 3
;;; Source level debugging is on
;;; Source file recording is  on
;;; Cross referencing is on
; (TOP-LEVEL-FORM 0)
; (TOP-LEVEL-FORM 1)
;; Processing Cross Reference Information
(FOO)

我们已经创建了两个fasl文件

现在我复制系统。将Lisp文件和fasl文件放入新目录:

RJMBA:Lisp joswig$ mkdir bar
RJMBA:Lisp joswig$ cp foo/system.lisp bar/system.lisp
RJMBA:Lisp joswig$ cp foo/a.64xfasl bar/a.64xfasl
RJMBA:Lisp joswig$ cp foo/b.64xfasl bar/b.64xfasl

现在我将在b目录下启动一个新的LispWorks,加载系统。Lisp文件然后加载系统:

RJMBA:Lisp joswig$ cd bar
RJMBA:bar joswig$ lispworks
LispWorks(R): The Common Lisp Programming Environment
Copyright (C) 1987-2009 LispWorks Ltd.  All rights reserved.
Version 6.0.0
User joswig on RJMBA.local
...
CL-USER 1 > (load "system.lisp")
; Loading text file /Lisp/bar/system.lisp
;; Creating system "FOO"
#P"/Lisp/bar/system.lisp"
CL-USER 2 > (load-system 'foo)
; Loading fasl file /Lisp/bar/a.64xfasl
"a" ; whatever the file does
; Loading fasl file /Lisp/bar/b.64xfasl
"b" ; whatever the file does
(FOO)

完成工作。

此外,这可以通过相对目录或所谓的逻辑路径名来完成。逻辑路径名具有从某个路径名到物理路径名的映射,因此可以使用与系统无关的路径名——与体系结构、操作系统和目录结构无关。这为特定的部署场景提供了额外的独立性。

截至2013年2月,ASDF 3现在提供了一种方法,使用FASL-OP和PRECOMPILED-SYSTEM来做您想做的事情。

far是正确的——ASDF中的逻辑使load-op依赖于compile-op,并且它将通过尝试比较fasl上的文件写入日期与.lisp文件上的文件写入日期来检查compile-op是否必要。

相信您应该能够通过定义cl-source-file的子类,例如fasl-only,然后覆盖fasl-onlycompile-op上的operation-done-p方法,使其始终返回t来实现此工作。

将您的defsystem设置为:default-component-classfasl-only,然后您的defsystem可以只列出:file组件,这可能是最方便的。

可能是谨慎的,也覆盖compile-opfasl-only上的input-files方法返回nil,但我不确定这是必要的。

最新更新