common-lisp - 打开共享对象时出错:如何嵌入共享对象或以编程方式指定不同的路径名?
问题描述
所以,我正在将 lisp 图像部署到 webapp 的服务器。到目前为止,这是一次很好的体验,除了这个特殊情况:
我正在使用这个生成webapp:
sbcl --dynamic-space-size 1024 \
--noinform \
--load $HOME/quicklisp/setup.lisp \
--eval '(ql:quickload :webapp)' \
--eval '(swank-loader:init :load-contribs t)' \
--eval "(sb-ext:save-lisp-and-die \"webapp\" :toplevel #'webapp::executable-entry-point :executable t :compression t)"
但是,当我在服务器上启动 webapp 时,我被扔进了调试器:
debugger invoked on a SIMPLE-ERROR in thread
#<THREAD "main thread" RUNNING {10006285B3}>:
Error opening shared object "/home/username/quicklisp/dists/quicklisp/software/clsql-20160208-git/db-mysql/clsql_mysql64.so":
/home/username/quicklisp/dists/quicklisp/software/clsql-20160208-git/db-mysql/clsql_mysql64.so: cannot open shared object file: No such file or directory.
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [CONTINUE ] Skip this shared object and continue.
1: [RETRY ] Retry loading this shared object.
2: [CHANGE-PATHNAME] Specify a different pathname to load the shared object from.
3: [ABORT ] Exit from the current thread.
(SB-SYS:DLOPEN-OR-LOSE #S(SB-ALIEN::SHARED-OBJECT :PATHNAME #P"/home/username/quicklisp/dists/quicklisp/software/clsql-20160208-git/db-mysql/clsql_mysql64.so" :NAMESTRING "/home/username/quicklisp/dists/quicklisp/software/clsql-20160208-git/db-mysql/clsql_mysql64.so" :HANDLE NIL :DONT-SAVE NIL))
0] back
Backtrace for: #<SB-THREAD:THREAD "main thread" RUNNING {10006285B3}>
0: (SB-SYS:DLOPEN-OR-LOSE #S(SB-ALIEN::SHARED-OBJECT :PATHNAME #P"/home/username/quicklisp/dists/quicklisp/software/clsql-20160208-git/db-mysql/clsql_mysql64.so" :NAMESTRING "/home/username/quicklisp/dists/quicklisp/software/clsql-20160208-git/db-mysql/clsql_mysql64.so" :HANDLE NIL :DONT-SAVE NIL))
1: (SB-ALIEN::TRY-REOPEN-SHARED-OBJECT #S(SB-ALIEN::SHARED-OBJECT :PATHNAME #P"/home/username/quicklisp/dists/quicklisp/software/clsql-20160208-git/db-mysql/clsql_mysql64.so" :NAMESTRING "/home/username/quicklisp/dists/quicklisp/software/clsql-20160208-git/db-mysql/clsql_mysql64.so" :HANDLE NIL :DONT-SAVE NIL))
2: (SB-SYS:REOPEN-SHARED-OBJECTS)
3: (SB-IMPL::FOREIGN-REINIT)
4: (SB-IMPL::REINIT)
5: ((FLET SB-UNIX::BODY :IN SAVE-LISP-AND-DIE))
6: ((FLET "WITHOUT-INTERRUPTS-BODY-36" :IN SAVE-LISP-AND-DIE))
7: ((LABELS SB-IMPL::RESTART-LISP :IN SAVE-LISP-AND-DIE))
0] 3
我不确定这是否仅限于clsql
- 有没有办法嵌入共享对象或以编程方式指定路径名,因为这看起来甚至在toplevel
调用函数之前就发生了错误。
确实存在关于将共享对象文件嵌入到 lisp 图像中的两年前的讨论——建议使用 ECL,至少在 ASDF 指令明确之前。
对于 SBCL,我还发现sb-alien:load-shared-object
了该:dont-save nil
选项;但不知道如何在这里使用它。
解决方案
在一般情况下,部署应该可以解决问题。(感谢 u/flaming_bird 在这里指出。)
但是,在这种特殊情况下,clsql
会.so
在clsql-sys:*foreign-library-search-paths*
. 这种“查找”发生在编译/制作期间。完成后,使用的路径将被硬编码到图像中,如果库不在完全相同的路径中,则会引发错误。
另一种方法是在构建映像之前从安装目录(在这种情况下)中删除(或重命名).so
文件,并将其放在部署服务器中需要它的位置(例如,当前目录)。然后,修改构建命令以推送共享库位置(例如)就可以了:clsql
$HOME/quicklisp/software/clsql-20160208-git/db-mysql/
#P"./"
#P"./"
sbcl --dynamic-space-size 1024 \
--noinform \
--load $HOME/quicklisp/setup.lisp \
--eval '(ql:quickload :clsql)' \
--eval '(push #P"./" clsql-sys:*foreign-library-search-paths*)' \
--eval '(ql:quickload :webapp)' \
--eval '(swank-loader:init :load-contribs t)' \
--eval '(py4cl2:pystop)' \
--eval "(sb-ext:save-lisp-and-die \"webapp\" :toplevel #'webapp::executable-entry-point :executable t :compression t)"
推荐阅读
- python - 如何在 matplotlib 中为子图设置相同的纵横比
- java - Dagger(不是 Android)java.lang.NoClassDefFoundError: dagger/internal/Preconditions
- java - Spring Boot 集成测试错误:“无法解析占位符 'wiremock.server.port'”在不需要 Wiremock 的测试中
- javascript - 倾斜密码算法
- javascript - 更新后无法访问计数器
- c# - 具有第二级属性的 WPF TreeView
- javascript - 为什么 router.get('/:x',..) 让另一个函数返回 null,而 router.get('/foo/:x',...) 绝对没问题?
- javascript - 如何使用“包含”选项调整图像的大小,但保留原始尺寸的纵横比?
- unity3d - 着色器在 Unity 编辑器中工作正常,但在 WebGL 构建中变黑
- xslt - xsl:choose - 将硬编码的 0 添加到 XSLT 字符串的末尾