问题背景
我在20年的时候转到了 archlinux。比较方便的一点是可以从软件源直接安装 Julia.
但是官方源的 Julia 有一个问题,就是所有涉及到 Arpack.jl
的包都会编译失败。
RROR: LoadError: InitError: could not load library "~/.julia/artifacts/cdf6dc8aa6771a61c6c65a5a5c1a8d1b75f50a2f/lib/libarpack.so"
libopenblas64_.so: cannot open shared object file: No such file or directory
主要表现就是 libopenblas64_.so
找不到。
问题分析
一种解决方案是将这个库复制到对应的文件夹下面,但是这种方法太麻烦了,每次都要复制一次。
实际上这个库在 /usr/lib/julia
下面,并且 arch 官方对 Julia 打了 patch, 将 /usr/lib/julia
加入了 RPATH
,因此 Julia 本身是找得到那个库的。
➜ ~ ls -al /usr/lib/julia/libopenblas64_.so
lrwxrwxrwx 1 root root 23 5月 9日 19:44 /usr/lib/julia/libopenblas64_.so -> /usr/lib/libopenblas.so
➜ ~ patchelf --print-rpath /usr/bin/julia
$ORIGIN/../lib:$ORIGIN/../lib/julia
这里 $ORIGIN
是 julia
可执行文件所在的位置,在我的电脑上就是 /usr/bin
。
问题出在 JLLWrapers.jl
,这个包在 linux 上只认 LD_LIBRARY_PATH
变量,另一个能够用来指定库的搜索路径的变量被设置为了空值。( LIBPATH_default = ""
)。
相关代码
因此,在没有将 /usr/lib/julia
加入到 LD_LIBRARY_PATH
的时候,它不会该路径下找库。就会出现找不到的情况。
我个人觉得应该修改 JLLWrappers.jl
,在它的默认搜索路径加入 julia 的 RPATH
。但是我还没找到在 Julia 里面要如何获取 RPATH
。之前没有正确理解 JLLWrappers.jl
的代码就贸然去提交 pr, 结果不出意外被拒了 。
解决方案
现在主要是有三种解决方案
- 手动复制库文件(不推荐)
- 在
~/.julia/config/startup.jl
里面添加ENV["LD_LIBRARY_PATH"]="/usr/lib:/usr/lib/julia"
(我目前用的这个) - 使用 julia-lang 发布的二进制包 julia-bin
个人评价
我个人不倾向于使用第三种方案,因为我还是希望尽量复用系统已经安装的库文件。
其实我不太喜欢 Julia 的各种 artifacts, 一个是下载起来慢,二是重复下载了很多库,浪费空间。在我的电脑上 ~/.julia
占用了 1.7G 空间,其中下面的 artifacts/
就占用了 817MB 空间。
更新
感觉我现在才算是找到原因了。是 arpck
的 RPATH
有问题。
➜ lib ldd libarpack.so
linux-vdso.so.1 (0x00007ffd528ad000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f565c4dd000)
libopenblas64_.so => not found
libgfortran.so.5 => /usr/lib/libgfortran.so.5 (0x00007f565c202000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f565c11b000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f565c0fb000)
libquadmath.so.0 => /usr/lib/libquadmath.so.0 (0x00007f565c0b2000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f565bea3000)
/usr/lib64/ld-linux-x86-64.so.2 (0x00007f565c56c000)
➜ lib patchelf --print-rpath libarpack.so
$ORIGIN
又看了一下,发现arch 官方的 julia 比 julia-lang 下面的命令少了一个 libopenblas64_.so
, 这可能是问题所在。
julia> filter(x -> occursin("64_",x), Libdl.dllist())
但是我不懂为啥 julia-bin
就没有问题。不懂 arch 打包的时候到底搞了什么黑魔法。
老老实实用 ENV["LD_LIBRARY_PATH"]
了。