开发者

Using asdf can I load a system providing only previously made FASLs

开发者 https://www.devze.com 2023-03-22 08:55 出处:网络
I have a development machine and a production machine which are identical (Co开发者_JAVA百科py of a vm image).

I have a development machine and a production machine which are identical (Co开发者_JAVA百科py 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.


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.


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.


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


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.

0

精彩评论

暂无评论...
验证码 换一张
取 消