3

在我正在进行的项目中,我们提供了动态加载附加功能的可能性。为此,我们使用 dlopen。

为了找到这个库,我们有一些我们称之为模块路径的东西。我们有一个默认路径,共享库所在的位置(其中很多已发货)。

目前我们有两个默认路径:我们首先在构建目录中查找共享库,然后在安装目录中查找。这是因为它也应该可以在不安装的情况下运行应用程序(因此在这种情况下,它需要首先在构建目录中查找)。

现在问题来了,如果用户从源代码构建应用程序并使用 make install 安装它,则默认情况下会加载她构建目录中的库。这将导致崩溃。因此,它仅在用户随后删除或重命名构建目录时才有效。

没有问题:是否有技巧(通过 C++ 或构建系统)知道应用程序是否已安装。问题是,该功能是在共享库中实现的,搜索模块的实现方式也必须适用于链接到我们库的其他应用程序(因此我们不能依赖可执行文件的路径)。我们使用 CMake 作为构建系统。

为了使情况更加困难,该解决方案必须在 Windows、Linux 和 Mac OS X 上运行。

编辑:

我进一步调查,问题更复杂。这是这种情况:

  • 有一个小的可执行文件
  • 此外,还有一个“主”库 main.so
  • 然后有一个动态加载的库 lib.so
  • lib.so 链接到 main.so

问题是,lib.so 在其 rpath 的构建目录中具有 main.so 的绝对路径。感谢@MSalters 的提示,我现在能够进行破解以确保加载正确版本的 lib.so(安装目录中的那个),但是由于它在 rpath 中有构建路径,因此它加载了错误的 main .so (所以实际上内存中有两个 main.so 副本——这把事情搞砸了)。

有没有办法从库中删除对构建路径的引用?我尝试了与 rpath 相关的所有 cmake 选项但没有成功

4

2 回答 2

1

你不能检查可执行文件本身在哪里吗?如果它在构建目录中,请使用构建库——如果它在安装中,请使用 install?

getcwd()在所有这些平台上都有等价物,但它可能不是你想要的——这取决于你如何运行可执行文件。

我认为,要获得进程的位置是系统特定的,但包装它应该不会太难。

于 2011-07-15T12:06:27.547 回答
0

安装的版本不应该在 rpath 中有构建目录。

您可能需要进行两次链接(一次用于构建版本,一次用于安装版本)。通常,在 *nix 系统上,已安装的二进制文件有一些静态路径,它会在其中尝试查找插件。您可以定义一些环境变量(或命令行参数)来重载它以执行构建(并使用包装脚本在构建环境中设置它)。

检查某些项目(例如 Firefox)如何解决它。

我对 Windows 系统了解不多,但我认为这样做的标准方法是在与可执行文件相同的目录中搜索插件。

于 2011-07-18T15:45:45.830 回答