对 boost 库的依赖没有完整路径
Dependencies on boost library don't have full path
我成功构建了我的动态库,它依赖于使用自定义前缀 (./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 库上,而不会发生在我的库所依赖的其他依赖项上?
编辑
有人要求我给出构建命令的示例,但像往常一样,"the real life" 示例有点复杂。
在我的例子中,有一个依赖于 boost 的库 libA.dylib
。然后是我的库 libMy.dylib
,它也依赖于 libA.dylib
和 boost。问题出现在 configure
步骤中,当执行简单的库存在检查时(自定义测试程序类似于 AC_CHECK_LIB
)。此检查试图构建一个与 libA.dylib
链接的小测试程序,以证明 libA.dylib
的可用性,但它失败了 - 由于无法找到提升库的错误。当然它找不到它们,因为 otool -L libA.dylib
给了我没有完整路径的 boost 库。
回答问题:
“为什么它只发生在 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 Bundle 中),并添加一个将遵循该相对路径的 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
我成功构建了我的动态库,它依赖于使用自定义前缀 (./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 库上,而不会发生在我的库所依赖的其他依赖项上?
编辑
有人要求我给出构建命令的示例,但像往常一样,"the real life" 示例有点复杂。
在我的例子中,有一个依赖于 boost 的库 libA.dylib
。然后是我的库 libMy.dylib
,它也依赖于 libA.dylib
和 boost。问题出现在 configure
步骤中,当执行简单的库存在检查时(自定义测试程序类似于 AC_CHECK_LIB
)。此检查试图构建一个与 libA.dylib
链接的小测试程序,以证明 libA.dylib
的可用性,但它失败了 - 由于无法找到提升库的错误。当然它找不到它们,因为 otool -L libA.dylib
给了我没有完整路径的 boost 库。
回答问题:
“为什么它只发生在 boost 库上,而不会发生在我的库所依赖的其他依赖项上?”
技术原因是 Boost 构建系统 (bjam) 明确指定库的 安装名称 只是文件名。它可以在内部使用 -install_name 编译器选项来执行此操作。
对于其背后的基本原理,我不能代表 Boost 开发人员,所以我只能推测(这是一种糟糕的投资形式):在库中硬编码本地安装路径只会延迟“找不到库”运行 分配时间的时间错误,因此他们可能只是希望您在开发时间尽快正确解决它。 (或者这可能只是他们不想投入更多时间返工的遗留行为;)
潜在的解决方案
假设您的动态库(依赖于 Boost)被命名为 myLib
。正如您在问题中已经指出的那样,您可以很好地更改 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
使用这种方法,当您根据修改后的 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 Bundle 中),并添加一个将遵循该相对路径的 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