回答这个问题:
“为什么它只发生在 boost 库上,而不会发生在我的库所依赖的其他依赖项上?”
技术原因是 Boost 构建系统 (bjam) 显式分配安装名称库的名称仅是文件名。它可以在内部使用-安装名称编译器选项。
对于其背后的原理,我不能代表 Boost 开发人员发言,所以我只能推测(这是一种糟糕的投资形式):对库中的本地安装路径进行硬编码只会将“未找到库”运行时错误延迟到分发时间,因此他们可能只是希望您在开发时间后立即正确解决它。 (或者这可能只是他们不想投入更多时间进行返工的遗留行为;)
潜在的解决方案
让我们想象一下你的动态库(依赖于Boost)被命名为myLib
。正如您在问题中已经指出的那样,您可以很好地更改记录在中的 Boost 库的安装名称myLib
:
install_name_tool myLib -change libboost_regex.dylib /full/path/to/libboost_regex.dylib
另一种方法是更改 Boost 库本身的安装名称:
install_name_tool libboost_regex.dylib -id $new_name
通过这种方法,安装名称$new_name
现在将被记录在myLib
当你根据修改后的内容构建它时libboost_regex.dylib
您知道必须决定为 $new_name 赋予哪个值。它当然可以是库的完整路径,这样 Boost 库将像您的其他依赖项一样运行。
另一种选择——更容易分发——是使用RPath https://developer.apple.com/library/mac/documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/RunpathDependentLibraries.html。 (基于 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 Bundle)中,并添加一个遵循该相对路径的 RPath 值。
编辑问题
对于您描述的无法找到 Boost 的自动检查的具体情况,您可能可以使用上面提出的替代解决方案来解决它。它更改存储在库本身中的 Boost 库的安装名称(因此将被复制到libA.dylib
):
install_name_tool libboost_regex.dylib -id /full/path/to/libboost_regex.dylib
在这个特定的用例中,一个更简单的解决方案可能是填充DYLD_FALLBACK_LIBRARY_PATH
包含 Boost 库的目录路径。动态链接器将在这些目录中查找库,因此它将在那里找到 boost 库。在将运行构建检查的终端中:
export DYLD_FALLBACK_LIBRARY_PATH=/full/path/to/;$DYLD_FALLBACK_LIBRARY_PATH