使用asdf我可以加载一个只提供以前制作的FASL的系统

时间:2011-07-22 07:41:48

标签: deployment lisp compilation common-lisp asdf

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

1.通过仅在生产机器中提供FASL文件来使asdf加载系统

优点:当我需要更改某些内容时,我将在开发机器中编译该文件并替换生产机器中的fasl。

缺点:我不知道是否以及如何做到这一点。

2.使用save-lisp-and-die,或者优先Zachary Beane's builapp tool(我正在使用SBCL)来自动化该过程。

优点:更容易自动化,更简洁,只有一个(虽然很大)文件传递。

缺点:以前解决方案的优点。

我知道我提到的那些缺点和专业人士彼此之间并不是那么重要,但我想知道任何我认为不会改变我的选择或任何其他解决方案的利弊。的。无论我选择什么,我都想知道解决方案1是否可行以及如何。

4 个答案:

答案 0 :(得分:4)

通常这些系统工具应该允许这样做。您只需要系统描述和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

system.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"))

Above根据加载文件的路径名设置*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文件。

现在我将system.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,加载system.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)

完成并且工作。

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

答案 1 :(得分:4)

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

最坏的情况是,如果ASDF不允许你这样做,那么“简单”的黑客就是创建包含的文件(eval-when(:compile-toplevel:load-toplevel:execute)(错误“这不是真实的源文件“))并给他们一个1970-01-01的时间戳代替你的源文件。脚本可以为您做到这一点,聪明的黑客入侵您的源代码注册表可以让您在真实的源代码和虚假的源代码之间切换。

祝你好运。

答案 2 :(得分:1)

Faré是对的 - ASDF中的逻辑使load-op依赖于compile-op,并且会通过尝试比较文件来检查compile-op是否必要在.lisp文件上使用文件写日期在fasl上写日期。

相信你应该能够通过定义cl-source-file的子类来说明fasl-only,然后覆盖operation-done-p方法。在fasl-onlycompile-op上,以便始终返回t

设置你的defsystem以使:default-component-classfasl-only可能是最方便的,然后你的defsystem就可以列出:file个组件。

可能谨慎地覆盖input-filescompile-op上的fasl-only方法以返回nil,但我不确定这是必要的。

答案 3 :(得分:1)

截至2013年2月,ASDF 3现在提供了一种使用FASL-OP和PRECOMPILED-SYSTEM完全按照您的需求进行操作的方法。