如何使用SBCL正确保存Common Lisp镜像?

13
如果我想创建一个Lisp程序的镜像,应该如何正确操作?有哪些前提条件?它是否与QUICKLISP兼容?
现在,如果我启动SBCL(只预加载了QUICKLISP),并保存镜像:
(save-lisp-and-die "core")

然后使用这个镜像再次尝试启动SBCL

sbcl --core core

然后尝试执行以下操作:

(ql:quickload :cl-yaclyaml)

我收到了以下信息:
To load "cl-yaclyaml":
  Load 1 ASDF system:
    cl-yaclyaml
; Loading "cl-yaclyaml"
.......
debugger invoked on a SB-INT:EXTENSION-FAILURE in thread
#<THREAD "main thread" RUNNING {100322C613}>:
  Don't know how to REQUIRE sb-sprof.
See also:
  The SBCL Manual, Variable *MODULE-PROVIDER-FUNCTIONS*
  The SBCL Manual, Function REQUIRE

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [RETRY                        ] Retry completing load for #<REQUIRE-SYSTEM "sb-sprof">.
  1: [ACCEPT                       ] Continue, treating completing load for #<REQUIRE-SYSTEM "sb-sprof"> as having been successful.
  2:                                 Retry ASDF operation.
  3: [CLEAR-CONFIGURATION-AND-RETRY] Retry ASDF operation after resetting the configuration.
  4: [ABORT                        ] Give up on "cl-yaclyaml"
  5:                                 Exit debugger, returning to top level.

(SB-IMPL::REQUIRE-ERROR "Don't know how to ~S ~A." REQUIRE "sb-sprof")
0] 

或者,如果我尝试:

(require 'sb-sprof)

当��用已保存的核心来启动sbcl时,我会遇到相同的错误。如果只是启动sbcl,则不会报错。
事实上,预加载QUICKLISP不是问题:如果初始调用sbcl --no-userinit --no-sysinit,同样会出现这个问题。
我做错了吗?
附注:如果我使用roswell,ros -L sbcl-bin -m core run无法获取图像(通过在保存前声明变量*A*并在重新启动后未看到它进行测试)。
附注2:到目前为止,似乎sbcl不提供扩展模块(SB-SPROFSB-POSIX等),除非在保存图像之前明确要求。

1
@RainerJoswig 我扩展了问题。希望它提供更多信息。 - mobiuseng
你使用的是哪个操作系统和哪个版本的SBCL?我在Linux + SBCL 1.3.2上无法重现这个问题。 - jkiiski
2
我找到问题了!SBCL的核心正在寻找带有额外模块(包括SB-SPROFSB-POSIX等)的contrib目录与核心文件在同一目录中。如果它们在保存图像时没有预加载,SBCL就不会将它们放入图像中。我想知道这是特定SBCL版本的行为还是所有版本都是如此? - mobiuseng
1
您是否设置了 SBCL_HOME 环境变量? - jkiiski
1
实际上,我不知道。现在我看到(安装说明的1.2节)SBCL主要在SBCL_HOME或图像所在的位置中寻找contrib。谢谢! - mobiuseng
显示剩余5条评论
2个回答

9
感谢@jkiiski的帮助,以下是完整的解释和解决方案:
  1. SBCL使用额外的模块(SB-SPROF, SB-POSIX等),这些模块不总是加载到映像中。这些模块位于contrib目录中,该目录位于SBCL_HOME环境变量指向的位置(如果设置了)或者位于映像所在位置(例如,在/usr/local/lib/sbcl/中)。

  2. 当映像保存在另一个位置时,如果没有设置SBCL_HOME,SBCL将无法找到contrib,因此会出现我遇到的错误。

  3. 将SBCL_HOME设置为指向contrib位置(或将contrib复制到映像位置或将新映像复制到contrib位置)即可解决问题。

  4. 最后,关于roswell:roswell参数-m会在特定位置搜索映像。对于SBCL(sbcl-bin),它应该是类似于~/.roswell/impls/x86-64/linux/sbcl-bin/1.3.7/dump/。其次,SBCL的映像名称必须采用<name>.core的形式。要启动它,请使用:ros -m <name> -L sbcl-bin run。(快速编辑:最好使用ros dump来保存使用roswell的映像,正如有人指出的那样)


1
对我而言有效的方法是 export SBCL_HOME=/usr/lib/sbcl/(由 (sb-int:sbcl-homedir-pathname) 打印出来的路径,而不是 /usr/local/bin)。 - Ehvince

3
如果您想创建可执行文件,可以尝试以下方法:
(sb-ext:save-lisp-and-die “core” :compression t ;; 这是主函数: :toplevel(lambda() (打印“hell world”) 0) :executable t)
使用此方法,您应该能够随意调用QUICKLOAD。也许您想检查一下我为创建可执行文件的CL-PROJECT扩展:https://github.com/ritschmaster/cl-project

我的版本没有使用zlib支持,因此:COMPRESSION无法工作。我现在不想要独立的可执行文件。我希望sbcl能够进入REPL,添加toplevel函数会使其执行并退出sbcl。 - mobiuseng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接