ffi.load 在 TeXLive 中默认在哪里寻找动态库?

ffi.load 在 TeXLive 中默认在哪里寻找动态库?

未能编译Henri Menke 编写的一段令人惊叹的代码,他在评论中指出,ffi 可能无法在我的系统上找到正确的动态库。

这是一个可以使用的 MCE(必须用 进行编译lualatex --shell-escape)。

\documentclass{standalone}
\usepackage{luacode}
\begin{luacode*}
  local ffi = require("ffi")
  local gsl = ffi.load("gsl")
\end{luacode*}
\begin{document}
Test
\end{document}

我在 archlinux 上运行最新的 vanilla TeXLive 2019。库 (gsl/usr/lib/)由我的包管理器安装:

christophe@plutonium ~ % ls -1 /usr/lib/libgsl*
/usr/lib/libgslcblas.so
/usr/lib/libgslcblas.so.0
/usr/lib/libgslcblas.so.0.0.0
/usr/lib/libgsl.so
/usr/lib/libgsl.so.25
/usr/lib/libgsl.so.25.0.0

头文件位于/usr/include/gsl/(参见文件列表)。

目前,我收到此错误:

[\directlua]:2: could not load library gsl
stack traceback:
    [C]: in function 'FFISUPPORTED'
    [\directlua]:2: in main chunk.
\luacode@dbg@exec ...code@maybe@printdbg {#1} #1 }

l.6 \end{luacode*}

我的问题是:

  1. ffi.load默认情况下查找库的位置(此处gsl)。
  2. 有没有办法在 TeXLive 中全局配置这个默认路径?
  3. 为什么像“ffi.load(“/usr/lib/gsl”)”这样的明确路径也不起作用?

顺便说一下,错误消息略有不同:

[\directlua]:2: could not load library /usr/lib/gsl
stack traceback:
    [C]: in function 'ffi.load'
    [\directlua]:2: in main chunk.
\luacode@dbg@exec ...code@maybe@printdbg {#1} #1 }

l.6 \end{luacode*}

亨利评论后更新。

以下是对该问题的完整看法。

christophe@plutonium /tmp % cat t.tex 
\documentclass{standalone}
\usepackage{luacode}
\begin{luacode*}
  local ffi = require("ffi")
  local gsl = ffi.load("/usr/lib/libgsl.so")
\end{luacode*}
\begin{document}
Test
\end{document}
% Local Variables:
% coding: utf-8-unix
% TeX-engine: luatex
% End:
christophe@plutonium /tmp % luatex --version
This is LuaTeX, Version 1.10.0 (TeX Live 2019)

Execute  'luatex --credits'  for credits and version details.

There is NO warranty. Redistribution of this software is covered by
the terms of the GNU General Public License, version 2 or (at your option)
any later version. For more information about these matters, see the file
named COPYING and the LuaTeX source.

LuaTeX is Copyright 2019 Taco Hoekwater and the LuaTeX Team.

christophe@plutonium /tmp % luatex --credits
This is LuaTeX, Version 1.10.0 (TeX Live 2019)

The LuaTeX team is Hans Hagen, Hartmut Henkel, Taco Hoekwater, Luigi Scarso.

LuaTeX merges and builds upon (parts of) the code from these projects:

tex       : Donald Knuth
etex      : Peter Breitenlohner, Phil Taylor and friends
omega     : John Plaice and Yannis Haralambous
aleph     : Giuseppe Bilotta
pdftex    : Han The Thanh and friends
kpathsea  : Karl Berry, Olaf Weber and others
lua       : Roberto Ierusalimschy, Waldemar Celes and Luiz Henrique de Figueiredo
metapost  : John Hobby, Taco Hoekwater, Luigi Scarso, Hans Hagen and friends
pplib     : Paweł Jackowski
fontforge : George Williams (partial)
luajit    : Mike Pall (used in LuajitTeX)

Compiled with libpng 1.6.36; using 1.6.36
Compiled with lua version 5.3.5
Compiled with mplib version 2.00
Compiled with zlib 1.2.11; using 1.2.11

Development id: 7127

christophe@plutonium /tmp % ls /usr/lib/*gsl*
/usr/lib/libgslcblas.so  /usr/lib/libgslcblas.so.0  /usr/lib/libgslcblas.so.0.0.0  /usr/lib/libgsl.so  /usr/lib/libgsl.so.25  /usr/lib/libgsl.so.25.0.0
christophe@plutonium /tmp % lualatex --shell-escape t.tex
This is LuaTeX, Version 1.10.0 (TeX Live 2019) 
 system commands enabled.
(./t.tex
LaTeX2e <2019-10-01> patch level 2
tput: unknown terminal "xterm-termite"

luaotfload | main : initialization completed in 0.138 seconds
(/usr/local/texlive/2019/texmf-dist/tex/latex/standalone/standalone.cls
Document Class: standalone 2018/03/26 v1.3a Class to compile TeX sub-files stan
dalone
(/usr/local/texlive/2019/texmf-dist/tex/latex/tools/shellesc.sty)
(/usr/local/texlive/2019/texmf-dist/tex/generic/iftex/ifluatex.sty
(/usr/local/texlive/2019/texmf-dist/tex/generic/iftex/iftex.sty))
(/usr/local/texlive/2019/texmf-dist/tex/latex/xkeyval/xkeyval.sty
(/usr/local/texlive/2019/texmf-dist/tex/generic/xkeyval/xkeyval.tex
(/usr/local/texlive/2019/texmf-dist/tex/generic/xkeyval/xkvutils.tex
(/usr/local/texlive/2019/texmf-dist/tex/generic/xkeyval/keyval.tex))))
(/usr/local/texlive/2019/texmf-dist/tex/latex/standalone/standalone.cfg)
(/usr/local/texlive/2019/texmf-dist/tex/latex/base/article.cls
Document Class: article 2019/10/25 v1.4k Standard LaTeX document class
(/usr/local/texlive/2019/texmf-dist/tex/latex/base/size10.clo))
(/usr/local/texlive/2019/texmf-dist/tex/generic/luatex85/luatex85.sty)
(/usr/local/texlive/2019/texmf-dist/tex/generic/oberdiek/pdftexcmds.sty
(/usr/local/texlive/2019/texmf-dist/tex/generic/oberdiek/infwarerr.sty)
(/usr/local/texlive/2019/texmf-dist/tex/generic/oberdiek/ltxcmds.sty)
(/usr/local/texlive/2019/texmf-dist/tex/generic/iftex/ifpdf.sty)))
(/usr/local/texlive/2019/texmf-dist/tex/lualatex/luacode/luacode.sty
(/usr/local/texlive/2019/texmf-dist/tex/luatex/luatexbase/luatexbase.sty
(/usr/local/texlive/2019/texmf-dist/tex/luatex/ctablestack/ctablestack.sty)))[\
directlua]:2: could not load library /usr/lib/libgsl.so
stack traceback:
    [C]: in function 'ffi.load'
    [\directlua]:2: in main chunk.
\luacode@dbg@exec ...code@maybe@printdbg {#1} #1 }

l.6 \end{luacode*}


? 

第二条评论后更新。

christophe@plutonium /tmp % LD_DEBUG=libs lualatex --shell-escape --interaction=batchmode t.tex   
      2773: find library=libdl.so.2 [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:   trying file=/usr/lib/libdl.so.2
      2773: 
      2773: find library=libm.so.6 [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:   trying file=/usr/lib/libm.so.6
      2773: 
      2773: find library=libc.so.6 [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:   trying file=/usr/lib/libc.so.6
      2773: 
      2773: 
      2773: calling init: /usr/lib/libc.so.6
      2773: 
      2773: 
      2773: calling init: /usr/lib/libm.so.6
      2773: 
      2773: 
      2773: calling init: /usr/lib/libdl.so.2
      2773: 
      2773: 
      2773: initialize program: lualatex
      2773: 
      2773: 
      2773: transferring control: lualatex
      2773: 
      2773: find library=libc.so [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:  search path=/usr/lib/tls/haswell/x86_64:/usr/lib/tls/haswell:/usr/lib/tls/x86_64:/usr/lib/tls:/usr/lib/haswell/x86_64:/usr/lib/haswell:/usr/lib/x86_64:/usr/lib        (system search path)
      2773:   trying file=/usr/lib/tls/haswell/x86_64/libc.so
      2773:   trying file=/usr/lib/tls/haswell/libc.so
      2773:   trying file=/usr/lib/tls/x86_64/libc.so
      2773:   trying file=/usr/lib/tls/libc.so
      2773:   trying file=/usr/lib/haswell/x86_64/libc.so
      2773:   trying file=/usr/lib/haswell/libc.so
      2773:   trying file=/usr/lib/x86_64/libc.so
      2773:   trying file=/usr/lib/libc.so
      2773: find library=libgcc.so [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:  search path=/usr/lib       (system search path)
      2773:   trying file=/usr/lib/libgcc.so
      2773: 
      2773: find library=libm.so [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:  search path=/usr/lib       (system search path)
      2773:   trying file=/usr/lib/libm.so
      2773: find library=libdl.so [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:   trying file=/usr/lib/libdl.so
      2773: 
This is LuaTeX, Version 1.10.0 (TeX Live 2019) 
 system commands enabled.
      2775: find library=libreadline.so.8 [0]; searching
      2775:  search cache=/etc/ld.so.cache
      2775:   trying file=/usr/lib/libreadline.so.8
      2775: 
      2775: find library=libdl.so.2 [0]; searching
      2775:  search cache=/etc/ld.so.cache
      2775:   trying file=/usr/lib/libdl.so.2
      2775: 
      2775: find library=libc.so.6 [0]; searching
      2775:  search cache=/etc/ld.so.cache
      2775:   trying file=/usr/lib/libc.so.6
      2775: 
      2775: find library=libncursesw.so.6 [0]; searching
      2775:  search cache=/etc/ld.so.cache
      2775:   trying file=/usr/lib/libncursesw.so.6
      2775: 
      2775: 
      2775: calling init: /usr/lib/libc.so.6
      2775: 
      2775: 
      2775: calling init: /usr/lib/libncursesw.so.6
      2775: 
      2775: 
      2775: calling init: /usr/lib/libdl.so.2
      2775: 
      2775: 
      2775: calling init: /usr/lib/libreadline.so.8
      2775: 
      2775: 
      2775: initialize program: sh
      2775: 
      2775: 
      2775: transferring control: sh
      2775: 
      2775: find library=libtinfow.so.6 [0]; searching
      2775:  search path=/home/christophe/anaconda3/bin/../lib/tls/haswell/x86_64:/home/christophe/anaconda3/bin/../lib/tls/haswell:/home/christophe/anaconda3/bin/../lib/tls/x86_64:/home/christophe/anaconda3/bin/../lib/tls:/home/christophe/anaconda3/bin/../lib/haswell/x86_64:/home/christophe/anaconda3/bin/../lib/haswell:/home/christophe/anaconda3/bin/../lib/x86_64:/home/christophe/anaconda3/bin/../lib        (RPATH from file tput)
      2775:   trying file=/home/christophe/anaconda3/bin/../lib/tls/haswell/x86_64/libtinfow.so.6
      2775:   trying file=/home/christophe/anaconda3/bin/../lib/tls/haswell/libtinfow.so.6
      2775:   trying file=/home/christophe/anaconda3/bin/../lib/tls/x86_64/libtinfow.so.6
      2775:   trying file=/home/christophe/anaconda3/bin/../lib/tls/libtinfow.so.6
      2775:   trying file=/home/christophe/anaconda3/bin/../lib/haswell/x86_64/libtinfow.so.6
      2775:   trying file=/home/christophe/anaconda3/bin/../lib/haswell/libtinfow.so.6
      2775:   trying file=/home/christophe/anaconda3/bin/../lib/x86_64/libtinfow.so.6
      2775:   trying file=/home/christophe/anaconda3/bin/../lib/libtinfow.so.6
      2775: 
      2775: find library=libc.so.6 [0]; searching
      2775:  search path=/home/christophe/anaconda3/bin/../lib      (RPATH from file tput)
      2775:   trying file=/home/christophe/anaconda3/bin/../lib/libc.so.6
      2775:  search cache=/etc/ld.so.cache
      2775:   trying file=/usr/lib/libc.so.6
      2775: 
      2775: 
      2775: calling init: /usr/lib/libc.so.6
      2775: 
      2775: 
      2775: calling init: /home/christophe/anaconda3/bin/../lib/libtinfow.so.6
      2775: 
      2775: 
      2775: initialize program: tput
      2775: 
      2775: 
      2775: transferring control: tput
      2775: 
tput: unknown terminal "xterm-termite"
      2775: 
      2775: calling fini: tput [0]
      2775: 
      2775: 
      2775: calling fini: /home/christophe/anaconda3/bin/../lib/libtinfow.so.6 [0]
      2775: 

luaotfload | main : initialization completed in 0.134 seconds
      2773: find library=gsl [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:  search path=/usr/lib       (system search path)
      2773:   trying file=/usr/lib/gsl
      2773: 
      2773: find library=gsl.so [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:  search path=/usr/lib       (system search path)
      2773:   trying file=/usr/lib/gsl.so
      2773: 
      2773: find library=libgsl.so [0]; searching
      2773:  search cache=/etc/ld.so.cache
      2773:   trying file=/usr/lib/libgsl.so
      2773: 
      2773: /usr/lib/libgsl.so: error: symbol lookup error: undefined symbol: cblas_ctrmv (fatal)
      2773: 
      2773: calling fini: lualatex [0]
      2773: 
      2773: 
      2773: calling fini: /usr/lib/libdl.so.2 [0]
      2773: 
      2773: 
      2773: calling fini: /usr/lib/libm.so.6 [0]

答案1

默认路径只是常规系统默认库路径。从技术上讲,名称会传递给系统函数(至少在 Linux 等类 UNIX 系统上)dlopen。此函数负责搜索库,其行为记录在其手册页DLOPEN(3).(在 Windows 上,该函数称为LoadLibraryA

但你不必为此担心,只需将库放在所有常规库所在的位置即可。你也可以传递路径,但你需要使用正确的文件名:没有名为的文件/usr/lib/gsl,库位于 中/usr/lib/libgsl.so。(如果省略路径,则会自动插入)

但在您的情况下,问题不在于找不到库,而在于无法单独加载库:

在您的系统上,GSL 始终必须与 C布拉斯实现,例如gslcblasGSL 附带的实现。(见有关链接 GSL 的详细信息,请参阅文档,尤其是如何加载另一个 BLAS 实现以获得更好的性能)

正如 Henri Menke 所说,这个问题并不是在所有平台上都必然存在的,尤其是 Debian 以一种确保这个问题不必然存在的方式链接库。但即使对于 Debian 用户,我也建议始终手动加载 CBLAS 实现:这使您的文档更具可移植性,并确保它也可以在其他系统上进行编译。

因此,如果你添加附加库,你的代码就可以工作:

\documentclass{standalone}
\usepackage{luacode}
\begin{luacode*}
  local ffi = require("ffi")
  ffi.load("gslcblas", true) -- Make the symbols available globally
  local gsl = ffi.load"gsl"
\end{luacode*}
\begin{document}
Test
\end{document}

相关内容