问题描述
我认为Linux的一个主要设计缺陷是共享对象地狱,它涉及以二进制形式而不是源代码形式分发程序.
I think a major design flaw in Linux is the shared object hell when it comes to distributing programs in binary instead of source code form.
这是我的特定问题:我想以ELF二进制格式发布一个Linux程序,该程序应在尽可能多的发行版上运行,以使我的强制性依存关系尽可能的低:在任何情况下,唯一需要的库是libpthread, libX11,librt和libm(当然还有glibc).当我使用gcc构建程序时,我正在动态链接这些库.
Here is my specific problem: I want to publish a Linux program in ELF binary form that should run on as many distributions as possible so my mandatory dependencies are as low as it gets: The only libraries required under any circumstances are libpthread, libX11, librt and libm (and glibc of course). I'm linking dynamically against these libraries when I build my program using gcc.
但是,可选地,我的程序还应该支持ALSA(声音接口),Xcursor,Xfixes和Xxf86vm扩展以及GTK.但是,仅当它们在用户系统上可用时,才应使用它们,否则,我的程序仍应运行,但功能有限.例如,如果GTK不存在,我的程序将退回到终端模式.因为我的程序仍然可以在没有ALSA,Xcursor,Xfixes等的情况下运行.我无法针对这些库进行动态链接,因为如果其中一个库不存在,那么该程序将根本无法启动.
Optionally, however, my program should also support ALSA (sound interface), the Xcursor, Xfixes, and Xxf86vm extensions as well as GTK. But these should only be used if they are available on the user's system, otherwise my program should still run but with limited functionality. For example, if GTK isn't there, my program will fall back to terminal mode. Because my program should still be able to run without ALSA, Xcursor, Xfixes, etc. I cannot link dynamically against these libraries because then the program won't start at all if one of the libraries isn't there.
因此,我需要手动检查是否存在库,然后使用dlopen()逐一打开它们,并使用dlsym()导入必要的功能符号.但是,这会导致各种问题:
So I need to manually check if the libraries are present and then open them one by one using dlopen() and import the necessary function symbols using dlsym(). This, however, leads to all kinds of problems:
1)库命名约定:共享对象通常不只是简单地称为"libXcursor.so",而是具有某种版本的扩展名,例如"libXcursor.so.1",甚至是真正有趣的东西,例如"libXcursor.so.0.2000".这些扩展似乎因系统而异.那么在调用dlopen()时应该选择哪一个呢?在这里使用硬编码名称似乎是个坏主意,因为名称因系统而异.因此,我想到的唯一解决方法是扫描整个库路径,并查找以"libXcursor.so"前缀开头的文件名,然后进行一些自定义版本匹配.但是我怎么知道它们真的兼容?
1) Library naming conventions:Shared objects often aren't simply called "libXcursor.so" but have some kind of version extension like "libXcursor.so.1" or even really funny things like "libXcursor.so.0.2000". These extensions seem to differ from system to system. So which one should I choose when calling dlopen()? Using a hardcoded name here seems like a very bad idea because the names differ from system to system. So the only workaround that comes to my mind is to scan the whole library path and look for filenames starting with a "libXcursor.so" prefix and then do some custom version matching. But how do I know that they are really compatible?
2)库搜索路径:我到底应该在哪里寻找* .so文件?这也因系统而异.有一些默认路径,例如/usr/lib和/lib,但是* .so文件也可以在许多其他路径中.因此,我必须打开/etc/ld.so.conf并进行解析以找出所有库搜索路径.这不是一件容易的事,因为/etc/ld.so.conf文件还可以使用某种 include 指令,这意味着我必须解析更多的.conf文件,并针对可能的情况进行一些检查.循环 include 指令等引起的无限循环.难道真的没有更简单的方法来找出* .so的搜索路径吗?
2) Library search paths: Where should I look for the *.so files after all? This is also different from system to system. There are some default paths like /usr/lib and /lib but *.so files could also be in lots of other paths. So I'd have to open /etc/ld.so.conf and parse this to find out all library search paths. That's not a trivial thing to do because /etc/ld.so.conf files can also use some kind of include directive which means that I have to parse even more .conf files, do some checks against possible infinite loops caused by circular include directives etc. Is there really no easier way to find out the search paths for *.so?
所以,我的实际问题是:难道没有一种更便捷,更轻松的方法来实现我想做的事情吗?创建一个具有ALSA,GTK,libXcursor等可选依赖项的Linux程序真的那么复杂吗?但是没有它也可以工作!做我想做的事情有某种标准吗?还是我注定要以骇人的方式做到这一点?
So, my actual question is this: Isn't there a more convenient, less hackish way of achieving what I want to do? Is it really so complicated to create a Linux program that has some optional dependencies like ALSA, GTK, libXcursor... but should also work without it! Is there some kind of standard for doing what I want to do? Or am I doomed to do it the hackish way?
感谢您的评论/解决方案!
Thanks for your comments/solutions!
推荐答案
就系统的创建者而言,这不是设计缺陷;这是一个优势-鼓励您以源代码形式分发程序.哦,您想出售您的软件?抱歉,这不是针对Linux优化的用例.
This isn't a design flaw as far as creators of the system are concerned; it's an advantage -- it encourages you to distribute programs in source form. Oh, you wanted to sell your software? Sorry, that's not the use case Linux is optimized for.
是的,这称为外部库版本控制.在此处进行阅读.从该说明中应该可以清楚地看到,如果您在通常会给您libXcursor.so.1
作为运行时引用的系统上使用标头编译二进制文件,则您兼容的 only 共享库为,尝试dlopen
libXcursor.so.0.2000
会导致无法预测的崩溃.
Yes, this is called external library versioning. Read about it here. As should be clear from that description, if you compiled your binaries using headers on a system that would normally give you libXcursor.so.1
as a runtime reference, then the only shared library you are compatible with is libXcursor.so.1
, and trying to dlopen
libXcursor.so.0.2000
will lead to unpredictable crashes.
任何提供libXcursor.so
但不提供libXcursor.so.1
的系统都是损坏的安装,或者与您的二进制文件也不兼容.
Any system that provides libXcursor.so
but not libXcursor.so.1
is either a broken installation, or is also incompatible with your binaries.
您不应尝试使用它们的完整路径来dlopen这些库中的任何一个.只需调用dlopen("libXcursor.so.1", RTLD_GLOBAL);
,运行时加载程序便会在适合系统的位置中搜索该库.
You shouldn't be trying to dlopen any of these libraries using their full path. Just call dlopen("libXcursor.so.1", RTLD_GLOBAL);
, and the runtime loader will search for the library in system-appropriate locations.
这篇关于在运行时加载Linux库的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!