【问题标题】:Dependencies on boost library don't have full path对 boost 库的依赖没有完整路径
【发布时间】:2016-02-13 10:38:11
【问题描述】:

我已经成功构建了我的动态库,它依赖于使用自定义前缀 (./b2 install --prefix=PREFIX) 构建和安装的 boost 库。但是,当我在我的库上运行 otool -L 时,我会得到如下输出:

...
libboost_regex.dylib (compatibility version 0.0.0, current version 0.0.0)
libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
...

与其他依赖项不同,它没有通向这些 boost 库的完整路径。当我的库被应用程序加载时,这会导致运行时错误。 我知道可以使用install_name_tool 来手动解决这个问题。但是,我想弄清楚,为什么它只发生在 boost 库中而不发生在我的库所依赖的其他依赖项上?

编辑

我被要求给出一个构建命令的例子,但像往常一样,“现实生活”的例子有点复杂。 就我而言,有一个库 libA.dylib 依赖于 boost。然后,我的库 libMy.dylib 也依赖于 libA.dylib 和 boost。问题出现在configure 步骤中,当执行简单的库存在检查时(类似于AC_CHECK_LIB 的自定义测试程序)。该检查尝试构建一个与libA.dylib 链接的小测试程序,以证明libA.dylib 的可用性,但由于无法找到boost 库的错误而失败。当然它不会找到它们,因为otool -L libA.dylib 给了我没有完整路径的提升库。

【问题讨论】:

  • 你能发布构建命令吗?您是否指定 -L 以在您的 dll 中保留 boost lib 路径,否则它可能只是在您的 LD 路径中查找。
  • @user3545806 请看上面的更新

标签: c++ macos boost dylib otool


【解决方案1】:

回答问题:
“为什么它只发生在 boost 库中而不发生在我的库所依赖的其他依赖项上?”

技术原因是 Boost 构建系统 (bjam) 明确地将库的 安装名称 指定为文件名。它可以在内部使用 -install_name 编译器选项执行此操作。
至于背后的原因,我不能代表 Boost 开发人员,所以我只能推测(这是一种糟糕的投资形式):在库中硬编码本地安装路径只会将“找不到库”运行时错误延迟到分发时间,所以他们可能只希望您在开发时间尽快解决它。 (或者这可能只是他们不想投入更多时间返工的遗留行为;)

 潜在的解决方案

假设您的动态库(依赖于 Boost)被命名为 myLib。正如您在问题中已经指出的那样,您可以很好地更改 myLib 中记录的 Boost 库的安装名称:

 install_name_tool myLib -change libboost_regex.dylib /full/path/to/libboost_regex.dylib

另一种方法是更改​​ Boost 库本身的安装名称:

install_name_tool libboost_regex.dylib -id $new_name

使用这种方法,当您针对修改后的libboost_regex.dylib 构建它时,安装名称$new_name 现在将记录在myLib

您知道必须决定为 $new_name 赋予哪个值。它当然可以是库的完整路径,这样 Boost 库将表现得像您的其他依赖项。

另一种选择——更容易分发——使用RPath。 (基于 RPath 的安装名称使依赖者承担了查找其依赖项的负担:依赖者存储了一个路径列表,它将尝试将“@rpath”替换为):

install_name_tool libboost_regex.dylib -id @rpath/libboost_regex.dylib #assign a rpath dependant install name to a boost library
 install_name_tool myLib -add_rpath $a_rpath_prefix # adds a candidate to substitute @rpath with, stored in myLib

$a_rpath_prefix 可能是包含 Boost 库的文件夹的路径,它适用于您的开发环境。如果有一天您需要分发您的库,您可以将 Boost 依赖项嵌入到相对路径(或 OS X 捆绑包)中,并添加将遵循此相对路径的 RPath 值。

 修改问题

对于您描述的无法定位 Boost 的自动检查的特定情况,您可能可以使用上面提出的替代解决方案来解决它。它更改了存储在库本身中的 Boost 库的安装名称(因此将被复制到 libA.dylib):

install_name_tool libboost_regex.dylib -id /full/path/to/libboost_regex.dylib

在这个特定的用例中,一个更简单的解决方案可能是使用包含 Boost 库的目录的路径填充 DYLD_FALLBACK_LIBRARY_PATH。动态链接器将在这些目录中查找库,因此它会在那里找到 boost 库。在将运行构建检查的终端中:

export DYLD_FALLBACK_LIBRARY_PATH=/full/path/to/;$DYLD_FALLBACK_LIBRARY_PATH

【讨论】:

  • 感谢您的见解。当我想分发时,我在可执行文件和所有依赖库上运行 install_name_tool。此问题涉及开发阶段(请参阅上面我的问题的更新)并影响想要配置开发环境并尝试构建我的项目的新开发人员。
  • @peetonn 感谢您的评论。我认为您可以使用编辑部分中的一种解决方案来修复任何开发环境。另外,如果它没有回答您的问题,我可能误解了您的问题(在这种情况下,您能否尝试改写一下?)
  • 好吧,我想这里真正的问题是如何为想要构建我的 lib/app 的第三方开发人员提供最“易于部署”的开发环境。最初,我试图解决问题的根源(即 boost 库没有安装路径),但现在看来,在构建 boost 之后,我必须在构建 libA.dylib 之前提供额外的步骤 - 比如“准备提升库”步骤,用户必须在其中执行您自己描述的手动方法。我仍然不相信这是最好的解决方案,但是我会将您的答案标记为可能的解决方案。谢谢!
  • 非常感谢。这是迄今为止我看到的对这个问题的最好解释。我希望 boost 开发人员会阅读它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多