我创建了一个静态链接到几个不同应用程序的通信库。该库为通过不同类型的硬件进行通信提供支持。供应商通过共享库支持某些硬件。在没有这些硬件的系统上,共享库不可用。
之前我们通过编译通信库和应用程序的双版本来处理这个问题。然而,这不太实用,所以我考虑使用更动态的通信库,如果可用的话,尝试使用dlopen()/ dlsym()加载供应商库。这似乎运作良好。但问题是,在将应用程序与我的库链接时,使用我的库的每个人都需要传递-ldl选项。即使这是一个小麻烦,我也想知道这通常是如何解决的。
是否有可能创建一个静态库,它将自动(在编译时或运行时)引入所需的共享库?
让静态库依赖共享库是不错的做法?
编辑:我知道libtool可能会解决这个问题,但是这仍然会改变所有应用程序的构建过程,我宁愿避免这种情况。编辑2:目标平台主要是Linux和Solaris。 Gcc作为编译器。
答案 0 :(得分:4)
我不知道Solaris,所以假设我的答案中的所有内容仅适用于Linux(尽管pkg-config也可以在Solaris上使用)。
首先,静态库没有受支持的方式来引入链接时依赖性。抱歉。大多数库都使用pkg-config之类的东西 - 也就是说,在构建时,添加到编译器命令行:
gcc `pkg-config --cflags your-library` [...]
当你链接时:
gcc `pkg-config --libs your-library` [...]
请注意,在这种情况下,--libs
参数会产生类似-ldl -lyourlib
的输出。 --cflags
参数可能不会产生输出,也可能会添加一些包含路径。
如果你绝对需要它只使用-lyourlib
,你不介意被绑在glibc中不受支持和不稳定的接口......好吧,libdl只是一些薄的包装器动态链接器中的例程,通过未记录的vtable。如果您查看正在使用的glibc版本的dlfcn/
目录下的源代码,您应该能够复制它的功能。
但是,libdl和ld-linux之间的接口是PRIVATE和UNSTABLE - 它可能会在任何glibc版本中发生变化,包括次要版本和bugfix版本。只有在您控制部署的glibc版本时才能执行此操作,并准备在必要时重建您的应用程序。另请注意,如果您的库本身不是LGPL,那么使用这样的私有API可能会产生许可问题;不确定LGPL的情况如何。