pee*_*onn 11 c++ macos boost dylib otool
我成功构建了动态库,依赖于boost库,这些库是使用自定义前缀(./b2 install --prefix=PREFIX)构建和安装的.但是,当我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)
...
Run Code Online (Sandbox Code Playgroud)
与其他依赖项不同,它没有完全通向这些boost库的路径.当我的lib被应用程序加载时,这会导致运行时错误.我知道可以使用install_name_tool手动修复此问题.但是,我想弄清楚,为什么它只发生在boost库中,并且不会发生在我的lib依赖的其他依赖项上?
编辑
我被要求给出一个构建命令的例子,但像往常一样,"现实生活"的例子有点复杂.就我而言,有一个libA.dylib依赖于提升的库.然后,我的图书馆libMy.dylib依赖libA.dylib和提升.在configure执行简单库存在检查(类似于自定义测试程序AC_CHECK_LIB)的步骤中出现问题.此检查尝试构建一个与之相关联的小测试程序,libA.dylib以证明其可用性libA.dylib并且失败 - 由于无法找到增强库的错误.当然它不会找到它们因为otool -L libA.dylib在没有完整路径的情况下给我提升库.
回答这个问题:
"为什么它只发生在boost库中,并且不会发生在我的lib依赖的其他依赖项上?"
技术原因是Boost构建系统(bjam)明确地将库的安装名称指定为文件名.它可以使用-install_name编译器选项在内部执行此操作.
对于它背后的基本原理,我不能代表Boost开发人员,所以我只能推测(这是一种糟糕的投资形式):对库中的本地安装路径进行硬编码只会将"库未找到"运行时错误延迟到分发时间,因此他们可能只是希望您在开发时尽快解决它.(或者它可能只是遗传行为,他们不想投入更多时间进行返工;)
让我们假设您的动态库(取决于Boost)被命名myLib.正如您在问题中已经指出的那样,您可以很好地更改记录在以下位置的Boost库的安装名称myLib:
install_name_tool myLib -change libboost_regex.dylib /full/path/to/libboost_regex.dylib
Run Code Online (Sandbox Code Playgroud)
另一种方法是更改Boost库本身的安装名称:
install_name_tool libboost_regex.dylib -id $new_name
Run Code Online (Sandbox Code Playgroud)
使用此方法,$new_name现在将在myLib针对修改后的安装名称中记录安装名称libboost_regex.dylib
您知道必须决定给$ 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
Run Code Online (Sandbox Code Playgroud)
$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
Run Code Online (Sandbox Code Playgroud)
在这个特定的用例中,一个更简单的解决方案可能是填充DYLD_FALLBACK_LIBRARY_PATH包含Boost库的目录的路径.动态链接器将在这些目录中查找库,因此它将在那里找到boost库.在将运行构建检查的终端中:
export DYLD_FALLBACK_LIBRARY_PATH=/full/path/to/;$DYLD_FALLBACK_LIBRARY_PATH
Run Code Online (Sandbox Code Playgroud)