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.
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.
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.
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 ;)
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With