如何在Linux上获取/etc/ld.so.conf中路径列表

5
什么是获取由/etc/ld.so.conf配置的路径列表以及包含在其中的文件的最便携和健壮的方法?手动解析文件似乎不是一个好主意——格式可能会在未来版本中更改。
为了更好地理解问题,我将在下面提供具体细节。请注意,尽管有这些细节,这是一个通用的编程问题,适用于其他情况。
有一个名为LuaRocks的程序。它是Lua编程语言的包管理器(类似于Ruby gems或Python eggs)。LuaRocks软件包称为“rocks”。
作为方便功能,LuaRocks允许rock作者指定外部依赖项列表,其格式为C头文件和/或动态库文件列表。(在Linux上为.so)如果指定的文件不存在,则无法安装rock。
目前,在Linux上,默认情况下,LuaRocks通过在两个硬编码路径/usr/lib/usr/local/lib中搜索文件来检查.so文件是否存在。
我认为这是不正确的行为,并且在Ubuntu和其他Debian发行版的最近更改中破坏了它(broken)
更新:路径并非硬编码,但可以在配置文件中进行用户配置。尽管如此,在我看来,这不是最佳解决方案。
相反地(据我所理解),LuaRocks应该在由/etc/ld.so.conf指定的路径中查找文件,并包括从其中包含的文件。
(现在请重新阅读上面的问题;-))
2个回答

6
您不需要解析/etc/ld.so.conf或任何配置文件-如果运行'ldconfig',它将扫描已配置的目录并生成缓存文件。
然后,在尝试dlopen时,它会通过迭代缓存库目录自动找到文件。同样的事情也适用于编译和使用-lSomeLib,如果在ld.so.conf(.d)中进行了配置,则不需要指定-L/my/other/path。
autoconf通过尝试编译链接到共享库的测试程序来实现此目的,但这只是对dlopen()调用的功能包装器。
因此,虽然其他方法可能不一定是“错误”的,但在根本上,尝试链接到库或执行dlopen()是最正确的方法。
考虑一下,如果您尝试链接到未缓存在/etc/ld.so.cache中的目录中的库,当您尝试运行程序时,它将失败,因为它无法dlopen()该库!
因此,任何“好”的共享库都将位于/etc/ld.so.cache中,并且可链接/dlopen(),这意味着gcc可以使用它进行链接,并且用户生成的库或可执行文件在执行时将能够打开它。
你可以通过明确设置环境变量LD_LIBRARY_PATH或LD_PRELOAD_PATH来规避此问题,但每个选项都有自己的注意事项,如果可能的话应该避免在“标准”使用中使用它们。
一篇关于编写共享库的好文章涵盖了其中一些问题,并且对于任何从事程序化消费其他共享库的人来说都是一篇很好的阅读材料。Ulrich Drepper's How to write shared libraries

1
这个问题与dlopen无关:LR必须在安装岩石(和库)之前决定系统是否符合岩石的合同。 - Alexander Gladysh
实际上,dlopen() 是操作系统查找动态库的方式。这些问题是相互关联的。也就是说,如果你运行 ldconfig,你不需要“搜索”库——它们会自动被找到。但是,无论如何感谢你的负评! - synthesizerpatel
1
你误解了 - 你需要将目录添加到 /etc/ld.so.conf.d/ 中的文件中,然后运行 ldconfig,ldconfig 会生成 /etc/ld.so.cache,然后任何试图查找共享库的东西 'gcc foo.c -lMyLib',或者 'ld -shared foo.c -lMyLib',或者 'dlopen('MyLib')' 引用缓存 @ /etc/ld.so.cache,你不需要指定目录。这正是为什么当你安装新的共享库时,autoconf 会发出一条消息,说 '你应该重新运行 ldconfig 来更新你的缓存'。此时,你不需要提供任何提示来制作/编译工具。 - synthesizerpatel
1
你又错了重点了。没有什么应该在特定目录中寻找.so文件,这就是动态库存在的原因——否则所有的东西都会进入一个目录。如果无法使用dlopen打开库,则未在/etc/ld.so.conf.d/*中配置,并且在系统上不存在。简而言之,任何东西都不应该“查看”/etc/ld.so.conf/*,任何这样做的东西都是错误的方式。这不是观点,它是事实。http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html - synthesizerpatel
3
autoconf 通过尝试编译一个链接到共享库的测试程序来实现这一点,但那只是对 dlopen() 调用的功能性包装。因此,虽然其他方法不一定是“错误”的,但在根本上,尝试链接库或执行 dlopen() 是实现的“最正确”的方式。考虑这一点,如果您尝试链接到未缓存在 /etc/ld.so.cache 中的库,当您尝试运行程序时它将失败,因为它将无法 dlopen() 此库!因此,任何“好的”库都将位于 /etc/ld.so.cache 中,并且可以链接/dlopen()。 - synthesizerpatel
显示剩余4条评论

2
根据FHS,以下是动态库的有效位置:
/lib*/
/opt/*/lib*/
/usr/lib*/
/usr/local/lib*/

(而且很可能也包括~/lib*/。)
我的/etc/ld.so.conf.d/*中的所有条目都符合这个规则。一些条目引用了FHS目录下面的子目录,这意味着你可以在没有路径信息的情况下使用其中的库。
现在我不太了解LuaRocks。如果你只能使用Lua路径样式的通配符(只有?),那么你就无法匹配这些条目,必须解析配置文件。否则,你可以尝试在这些目录的任何地方找到它们。
这种方法会在非FHS兼容系统上失效(唯一的选择是解析配置文件),而且如果一个目录没有被包含在配置文件中,安装程序可能会看到链接器找不到的库。
这两种方法对我来说似乎都可以接受,因此我会简单地忽略配置文件并查看这些目录。
(另一种可能性是尝试链接库,这应该自动使用正确的路径。但这是平台特定的,可能有危险。)

直接在目录中查找似乎不够健壮 - 管理员用户可能会以不同的方式重新配置系统。 - Alexander Gladysh
@Alexander,为什么不呢?除非你要查找几百个solibs,否则对于安装程序来说应该是相当快的。只需fork(),从分叉的进程中调用dlopen(),并使用指示是否成功的退出代码退出。 - bdonlan
@bdonlan:抱歉,“为什么不”——三个中的哪一个? - Alexander Gladysh
如果你所说的“链接库”是指“调用dlopen”,那么或许是的。 - Alexander Gladysh
1
@Alexander:备用格式的 lib 目录被写为 lib<qual>,你可以在目录表中找到它们。<qual> 可以是任何东西,因此使用 * 代替。 - nobody
显示剩余8条评论

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