Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dependencies on boost library don't have full path

I have my dynamic library built successfully with dependencies on boost libraries which were built and installed with custom prefix (./b2 install --prefix=PREFIX). However, when I run otool -L on my library I get output like this:

...
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)
...

Which is, unlike other dependencies, presented without full path towards these boost libraries. This results in runtime errors when my lib is loaded by apps. I know that one can use install_name_tool to manually fix this problem. However, I'm trying to figure out, why does it happen only for boost libraries and does not happen to other dependencies my lib depends on?

EDIT

I've been asked to give an example of build command, but like usual, "the real life" example is a bit more complicated. In my case, there is a library libA.dylib which depends on boost. Then, there's my library libMy.dylib which depends on libA.dylib and boost as well. The problem arises during configure step, when simple library existence check is performed (custom test program similar to AC_CHECK_LIB). This check tries to build a little test program which is linked against libA.dylib in order to prove availability of libA.dylib and it fails - due to the error of not being able to find boost libraries. Of course it wouldn't find them because otool -L libA.dylib gives me boost libs without full path.

like image 964
peetonn Avatar asked Nov 12 '15 06:11

peetonn


People also ask

How do I add Boost to path?

Right-click example in the Solution Explorer pane and select Properties from the resulting pop-up menu. In Configuration Properties > Linker > Additional Library Directories, enter the path to the Boost binaries, e.g. C:\Program Files\boost\boost_1_46_1\lib\. From the Build menu, select Build Solution.

Is Boost library header-only?

Most Boost libraries are header-only: they consist entirely of header files containing templates and inline functions, and require no separately-compiled library binaries or special treatment when linking. The only Boost libraries that must be built separately are: Boost.


1 Answers

To answer the question:
"why does it happen only for boost libraries and does not happen to other dependencies my lib depends on?"

The technical reason is that Boost build system (bjam) is explicitly assigning the install name of the library to be only the file name. It could internally be doing that using the -install_name compiler option.
For the rationale behind it, I cannot speak for the Boost developers, so I could only speculate (which is a poor form of investment): hardcoding the local installation path in a library is only delaying the "library not found" runtime error to the distribution time, so they could just want you to address it properly as soon as development time. (Or it could just be a legacy behaviour they did not want to invest more time to rework ;)

 Potential solutions

Let's imagine your dynamic library (which depends on Boost) is named myLib. As you already pointed out in your question, you could very well change the install name for the Boost libs that is recorded in myLib:

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

An alternative is to change the install name of the Boost libraries themselves:

install_name_tool libboost_regex.dylib -id $new_name

With this approach, the install name $new_name will now be recorded in myLib when you build it against the modified libboost_regex.dylib

You know have to decide which value to give to $new_name. It could of course be the full path to the library, and this way Boost libraries will behave as your other dependencies.

An alternative -- more easily amenable to distribution -- is using RPath. (RPath based install names put the burden on the depender to find its dependency: the depender stores a list of path that it will try to replace "@rpath" with) :

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 could be the path to the folder containing your Boost libraries, which will work well on your development environment. And if one day you need to distribute your library, you could embed the Boost dependencies in a relative path (or in an OS X Bundle), and add an RPath value that will follow this relative path.

 Edit to the question

For the specific case you describe of an automatic check that cannot locate Boost, you can probably solve it with the alternative solution proposed above. It changes the install name of the Boost library which is stored in the library itself (and thus will be copied into libA.dylib):

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

In this specific use case, an even simpler solution could be to populate the DYLD_FALLBACK_LIBRARY_PATH with the path to the directory containing your Boost library. The dynamic linker will look in those directories for libraries, so it will find the boost libraries there. In the terminal in which the build check will be run:

export DYLD_FALLBACK_LIBRARY_PATH=/full/path/to/;$DYLD_FALLBACK_LIBRARY_PATH
like image 159
Ad N Avatar answered Sep 21 '22 00:09

Ad N