Tuesday, November 30, 2010

Using Boost in Ubuntu with Eclipse

Boost is an open source library of extremely useful and carefully designed C++ classes and methods ranging from graph algorithms, to regular expressions matching, to multi-threading.
Part of the Boost library was also integrated into the C++ standard as the TR1 set of libraries.
You can learn more about Boost here.
Using it with Eclipse in Ubuntu is definitely possible, but not straightforward; so I decided to post this simple tip here, to help folk spare some of the grief.
The first step in using Boost in your code is to download the header (.hpp) files and (optionally) source code - the latest release is 1.45 and is available from Boost's website.
In theory, you could compile it, and build the libraries' binaries yourself: by all means, go ahead and do it, but there is an easier way, if you can live with a slightly 'older' version.

Ubuntu 9.10 (Karmic Koala) comes with Boost 1.34 pre-configured (I think, this is, at any rate, the version that I had on my system):
$ ls /usr/lib/libboost*
/usr/lib/libboost_date_time-gcc41-1_34_1.so.1.34.1
/usr/lib/libboost_date_time-gcc41-mt-1_34_1.so.1.34.1
/usr/lib/libboost_date_time-gcc42-1_34_1.so.1.34.1
/usr/lib/libboost_date_time-gcc42-mt-1_34_1.so.1.34.1
/usr/lib/libboost_filesystem-gcc41-1_34_1.so.1.34.1
/usr/lib/libboost_filesystem-gcc41-mt-1_34_1.so.1.34.1
/usr/lib/libboost_filesystem-gcc42-1_34_1.so.1.34.1
/usr/lib/libboost_filesystem-gcc42-mt-1_34_1.so.1.34.1
/usr/lib/libboost_iostreams-gcc41-1_34_1.so.1.34.1
/usr/lib/libboost_iostreams-gcc41-mt-1_34_1.so.1.34.1
/usr/lib/libboost_iostreams-gcc42-1_34_1.so.1.34.1
/usr/lib/libboost_iostreams-gcc42-mt-1_34_1.so.1.34.1
/usr/lib/libboost_regex-gcc41-1_34_1.so.1.34.1
/usr/lib/libboost_regex-gcc41-mt-1_34_1.so.1.34.1
/usr/lib/libboost_regex-gcc42-1_34_1.so.1.34.1
/usr/lib/libboost_regex-gcc42-mt-1_34_1.so.1.34.1
/usr/lib/libboost_signals-gcc41-1_34_1.so.1.34.1
/usr/lib/libboost_signals-gcc41-mt-1_34_1.so.1.34.1
/usr/lib/libboost_signals-gcc42-1_34_1.so.1.34.1
/usr/lib/libboost_signals-gcc42-mt-1_34_1.so.1.34.1
/usr/lib/libboost_thread-gcc41-mt-1_34_1.so.1.34.1
/usr/lib/libboost_thread-gcc42-mt-1_34_1.so.1.34.1

However, by using Synaptic, you can actually install the more recent 1.40.0 version:


This will install a bunch of libboost_*.so.1.40.0 files into /usr/lib: in order to match the libraries with the header files (and avoid introducing incomprehensible compilation errors at best, and subtle bugs at worst) you should download the matching boost_1_40_0.tar.bz2 from Boost download archives.

We would be almost there, were it not for the fact that the soname does not really comply with the -l gcc linker option.

In gcc the -L option specifies a 'search directory' (this would not be needed, as /usr/lib is searched for libraries by default) and the -l specifies additional dynamic (.so) or static (.a) libraries: you specify the file to include during the link step by omitting the `lib` prefix and the .so or .a extension.
In other words, if your HelloBoost source uses code from Boost Regex (libboost_regex.so) you would specify it like thus:
$ gcc -Wall hello_boost.cc -o HelloBoost -lboost_regex

You can see where I'm heading with all this: the last step will be to add symbolic links that do away with the soname suffixes of Boost libraries, and all will be well:
$ ln -s /usr/lib/libboost_regex.so.1.40.0 /usr/lib/libboost_regex.so

Given that there are in total 24 files for the whole of Boost 1.40, I've done a bit of find & replace magic, and have come up with the following shell file (the other advantage being that, when a later version becomes available for Ubuntu, I will not have to change any of my Eclipse projects setting, but just change the VERSION value in the script):
#!/bin/bash
#
# Simple script to enable Boost with simple -l gcc option
# Use: gcc -Wall hello_world.cc -o HelloWorld -lboost_regex
#
# Created by M. Massenzio, 2010-11-30

VERSION=1.40.0

for libname in libboost_date_time \
            libboost_filesystem \
            libboost_graph_parallel  \
            libboost_graph      \
            libboost_iostreams  \
            libboost_math_c99f  \
            libboost_math_c99l  \
            libboost_math_c99   \
            libboost_math_tr1f  \
            libboost_math_tr1l  \
            libboost_math_tr1   \
            libboost_mpi        \
            libboost_prg_exec_monitor \
            libboost_program_options  \
            libboost_python-py25      \
            libboost_python-py26      \
            libboost_regex            \
            libboost_serialization    \
            libboost_signals          \
            libboost_system           \
            libboost_thread           \
            libboost_unit_test_framework \
            libboost_wave \
            libboost_wserialization 
do
  ln -s /usr/lib/$libname.so.$VERSION /usr/local/lib/$libname.so
done


The last and final step is to tell Eclipse what to look for when building your binary: right-click on your project's folder (in the C++ Perspective, Project Explorer) then Properties > C/C++ Build > Settings, select GCC C++ Linker > Libraries and add the 'stripped' library names in the option list:


Note for the curious: the additional libraries listed there are for Google C++ Unit testing framework, GUnit, available here - you will have to build it, but that's pretty straightforward, resulting in the two libgtest.a and libgtest_main.a libraries - be careful to add those only to your 'Test' configuration and exclude your unit tests from build in your Release/Debug configurations.

No comments:

Post a Comment