使用 asdf 我可以加载仅提供先前制作的 FASL 的系统

发布于 2024-11-25 17:48:36 字数 523 浏览 1 评论 0原文

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

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

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

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

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

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

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

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

I have a development machine and a production machine which are identical (Copy of a vm image).
I want to deliver the application to the production machine along with the asd file but I don't want to deliver source code. I have thought of 2 ways:

1.Having asdf load a system by providing only the FASL files in the production machine

Pros: When I need to change something I will just compile the file in devel machine and replace the fasl in the production machine.

Cons: I dont know if and how it can be done.

2.Using save-lisp-and-die, or preferebly Zachary Beane's builapp tool (I am using SBCL) to automate the process.

Pros: More easily automated, more concise, and just one (although big) file delivery.

Cons: The pros of the previous solution.

I know that those cons and pros I mention arent so important compared to each other, but I would like to know any pros or cons that I don't see that may change my options, or any other solution that I havent though of. Also no matter what I choose I would like to know if solution 1 is possible and how.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

沩ん囻菔务 2024-12-02 17:48:36

我目前负责维护 ASDF。我不知道 ASDF 允许这样做。我不是为此而设计的。也就是说,我从未尝试过,也不能发誓它不会,或者一个简单的黑客不会让你做到这一点。我欢迎对 ASDF 和/或扩展进行这样的攻击。

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

祝你好运。

I currently maintain ASDF. I don't know that ASDF allows that. I wasn't designed for it. That said, I have never tried and can't swear that it won't, or that a simple hack won't let you do it. I'll welcome such a hack into ASDF and/or an extension.

At worst, if ASDF won't otherwise let you do it, a "simple" hack would be to create files containing (eval-when (:compile-toplevel :load-toplevel :execute) (error "This is not the real source file")) and give them a timestamp of 1970-01-01 in lieu of your source files. A script could do that for you, and clever hacking of your source-registry could allow you to switch between real source code and fake source code.

Good luck.

凡尘雨 2024-12-02 17:48:36

一般来说,这些系统工具应该允许这样做。您所需要的只是系统描述和 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"))

上面设置了基于路径名的 *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)

完成并有效。

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

Generally these system tools should allow that. All you need is the system description and the FASL files. The system tool should then use the FASL files for loading. One only needs to make sure that it does not have a hard dependence on some source file.

This way software has delivered in the Lisp world for decades (> 30 years). There is nothing wrong with that approach. If a particular tool (here ASDF, but there are others) has a problem with that, one should complain to the authors.

If you have a practical problem with it, you should discuss it on the ASDF mailing list or post a question here. Do you have a practical problem with it?

This will not help you directly, but it may give you some hints how a system tool usually works|ed.

Example with LispWorks 6 and its own DEFSYSTEM

We have three files in a directory 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 contains the following system description:

(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 sets the *foo-directory*pathname based on the pathname of the loaded file.
Thus we can set a real absolute pathname, but don't have to manually specify it.
Alternatively we could use relative pathnames - this depends on what one wants to use.
I chose this to show how to set up an absolute pathname automagically.

Now I load this file into LispWorks then compile the system:

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)

We have created two fasl files.

Now I copy the system.lisp file and the fasl files into a new directory:

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

Now I'll start a fresh LispWorks in the bdirectory, load the system.lisp file and then load the system:

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)

Done and works.

Additionally this can be done with relative directories or so-called logical pathnames. Logical pathnames have a mapping from some pathname to a physical pathname, thus enable to use system-independent pathnames - independent from architecture, OS and directory structures. This gives an additional level of independence from the specific deployment scenario.

凉城已无爱 2024-12-02 17:48:36

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

As of February 2013, ASDF 3 now offers a way to do exactly what you want, using FASL-OP and PRECOMPILED-SYSTEM.

自由如风 2024-12-02 17:48:36

Faré 是对的 -- ASDF 中的逻辑使 load-op 依赖于 compile-op,并且它将检查 compile-op 是否尝试将 fasl 上的文件写入日期与 .lisp 文件上的文件写入日期进行比较时, 是必需的。

相信您应该能够通过定义 cl-source-file 的子类(例如fasl-only)来完成这项工作,然后覆盖操作fasl-onlycompile-op 上的 -done-p 方法,以便它始终返回 t

设置您的 defsystem 以便 :default-component-class仅 fasl 可能是最方便的,然后您的 defsystem 可以只列出 :文件 组件。

谨慎的做法是重写compile-op 和fasl-only 上的input-files 方法以返回nil,但我不确定这是必要的。

Faré is right --- the logic in ASDF makes a load-op depend on a compile-op, and it will check to see if the compile-op is necessary by trying to compare the file-write-date on the fasl with the file-write-date on the .lisp file.

I believe you should be able to make this work by defining a sub-class of cl-source-file, say fasl-only, and then override the operation-done-p method on fasl-only and compile-op so that it always returns t.

It will probably be most convenient to set up your defsystem so that the :default-component-class is fasl-only, and then your defsystem can just list :file components.

It might be prudent also to override the input-files method on compile-op and fasl-only to return nil, but I'm not sure that's necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文