我ATLAS
(使用 Netlib LAPACK
)安装在 Docker 映像中,现在每次运行时ldconfig
,都会出现以下错误:
ldconfig: Can't link /usr/local/lib//usr/local/lib/libtatlas.so to libtatlas.so
ldconfig: Can't link /usr/local/lib//usr/local/lib/libsatlas.so to libsatlas.so
当然,/usr/local/lib//usr/local/lib/libtatlas.so
不存在,但我很困惑为什么它会尝试查找这个文件,因为libtatlas.so
它不是符号链接:
root@cd00953552ab:/usr/local/lib# ls -la | grep atlas
-rw-r--r-- 1 root staff 15242054 Apr 27 08:18 libatlas.a
-rwxr-xr-x 1 root staff 17590040 Apr 27 08:18 libatlas.so
-rwxr-xr-x 1 root staff 17492184 Apr 27 08:18 libsatlas.so
-rwxr-xr-x 1 root staff 17590040 Apr 27 08:18 libtatlas.so
为什么会发生这种情况,有没有办法修复它/关闭此错误消息?
编辑:这是 Readelf 输出:
root@cd00953552ab:/usr/local/lib# eu-readelf -a /usr/local/lib/libatlas.so | grep SONAME
SONAME Library soname: [/usr/local/lib/libtatlas.so]
答案1
由于某种原因,可能与库的构建方式(更具体地说,链接)有关,它们将安装目录存储在 soname 中:因此libtatlas.so
的 soname 是/usr/local/lib/libtatlas.so
。ldconfig
尝试将库链接到它们的 soname(如果不存在),在同一目录中:它找到,检查其 soname,确定需要从(目录和 soname 连接)到/usr/local/lib/libtatlas.so
建立链接,并失败,因为不存在不存在。/usr/local/lib//usr/local/lib/libtatlas.so
/usr/local/lib/libtatlas.so
/usr/local/lib/usr/local/lib
解决此问题的适当方法是确保正确定义库的 sonames。通常,我期望libtatlas.so.3
没有目录名称的等(版本取决于正在构建的库的 ABI 级别)。您可能需要重建库,或者找到正确构建的包......
或者,您可以使用编辑库的soname补丁ELF:
patchelf --set-soname libtatlas.so /usr/local/lib/libtatlas.so
理想情况下,您应该重新链接使用此库构建的程序,因为它们也会嵌入 soname(您也可以使用 PatchELF 对其进行修补)。
在不断发展的系统中,您确实希望在 soname 中指定版本,但在容器中这可能并不重要 - 无论如何您都应该重建容器以进行升级。
答案2
在 BLAS 库的这个特殊情况下ATLAS
。解决真正原因的方法是更正用于构建包的 makefile。
原因请参阅@Stephen Kitt 的回答。
然而,由于一个--set-soname 的错误在 中patchelf
,patchelf 解决方案无法工作。
您的库路径包含“/usr/local”,因此我假设它是从源代码构建的。
检查文件$(SRC)/makes/Make.lib
,$(SRC)
你的源代码根目录在哪里。
特别是这些行:
LDTRY:
$(LD) $(LDFLAGS) -shared -soname $(LIBINSTdir)/$(outso) -o $(outso) \
-rpath-link $(LIBINSTdir) \
--whole-archive $(libas) --no-whole-archive $(LIBS)
这里的soname 是不正确的:-soname $(LIBINSTdir)/$(outso)
。将其更改为-soname $(outso)
,然后重建库即可解决此问题。
如果您已经成功构建,请更改 中的相应行$(BUILD)/lib/Makefile
,其中$(BUILD)
是构建库的目录。然后make shared
构建库。
使用诸如之类的命令readelf -d libtatlas.so | grep soname
检查生成的 .so 文件中的 soname。它不应包含任何目录部分。
如果找不到正确的makefile(例如使用不同版本的makefile ATLAS
),请尝试grep -IR soname
找到需要修改的位置。