# CMake can use a local Boost

One of my current projects relies on Boost.Python, which requires a more recent version of Boost (1.64) than the one (1.54) provided by my Linux distribution (Ubuntu 14.04). My first guess was to remove Boost from my package manager and install its newer version from source... with dramatic consequences! At first, I only experienced a few glitches in ROS and some libraries built with the old version of Boost, but down the road I ran into serious runtime problems that forced me to revert to the system's Boost 1.54.

My second guess was to use a local version of Boost 1.64, compiled but not installed system-wide and only used by the project that needs it. I knew this is possible because the PID framework does this. Without switching to a software source distribution manager, let's see how to change only the CMakeCache.txt configuration to switch from a system-wide to a local Boost install.

## Local changes to CMakeCache.txt¶

I'm assuming you already have your CMakeLists.txt file written and functional. For instance, you can follow these instructions to use Boost.Python with CMake. We won't make any change to the CMakeLists.txt, so that your local Boost install will only affect you and stay transparent for other project users.

To start with, go to your build directory and call ccmake ., or alternatively open CMakeCache.txt in your text editor.

### Boost paths¶

If you use the JRL CMake modules to find Boost automatically, you will already have a number of Boost_* CMake variables. The first thing is to update them to your local path:

Boost_INCLUDE_DIR:PATH=/my/local/path/boost/1.64.0/include
Boost_LIBRARY_DIR:PATH=/my/local/path/boost/1.64.0/lib
Boost_PYTHON_LIBRARY_DEBUG:FILEPATH=/my/local/path/boost/1.64.0/lib/libboost_python.so
Boost_PYTHON_LIBRARY_RELEASE:FILEPATH=/my/local/path/boost/1.64.0/lib/libboost_python.so


CMAKE_CXX_FLAGS:STRING=-I/my/local/path/boost/1.64.0/include


Possibly the Boost_DIR variable will revert to Boost_DIR-NOTFOUND after you run CMake again. This is not a problem.

While Boost.Python will be linked with its full path, some libraries like Boost.NumPy may still be linked by a mere -lboost_numpy, in which case the linker will fail to find the local shared object (.so) file. Let's add a -L linker flag to help it here:

CMAKE_SHARED_LINKER_FLAGS:STRING=-L/my/local/path/boost/1.64.0/lib


At this stage, your executable or library should compile and link. You can check that the files produced in your build folder (let's assume a .so here) links properly to your local Boost libraries:

$ldd ./build/mylib.so linux-vdso.so.1 => (0x0000...) libboost_numpy.so.1.64.0 => /my/local/path/boost/1.64.0/lib/libboost_numpy.so.1.64.0 (0x0000...) libboost_python.so.1.64.0 => /my/local/path/boost/1.64.0/lib/libboost_python.so.1.64.0 (0x0000...)  However, you may notice that it is not the case with your installed files: $ ldd /install/path/mylib.so
linux-vdso.so.1 =>  (0x00007ffc8f5c7000)
...


This is caused by the different behaviors of CMake between build and install.

### A Tale of two RPATHs¶

RPATH is a list of directories that is directly written into your executable or shared object and tells the linker where to look for libraries. It has precedence over the LD_LIBRARY_PATH system-wide variable, as explained in this page on CMake RPATH handling.

A dirty solution to the "not found" problem would be to add the local Boost 1.64 libraries to LD_LIBRARY_PATH. But then, they would also be visible in other projects trying to link to Boost, which can be problematic. We will rather set RPATH to avoid this and keep things local.

The behavior of CMake with respect to RPATH is controlled by two parameters:

// If set, runtime paths are not added when installing shared libraries,
// but are added when building.
CMAKE_SKIP_INSTALL_RPATH:BOOL=OFF

// If set, runtime paths are not added when using shared libraries.
CMAKE_SKIP_RPATH:BOOL=OFF


In our case, we need both of these values to be off. Plus, we want the linker to behave for the install the way it does for the build, i.e. using full paths to our local Boost libraries. This is specified by the following parameter:

// Use same RPATH at install and build


Once this is set, run make install again. You should see something like: