72

I have installed the most recent version of Boost in /usr/local (with includes in /usr/local/include/boost and libraries in /usr/local/lib/boost) and I am now attempting to install Wt from source, but CMake (version 2.6) can't seem to find the Boost installation. It tries to give helpful suggestions about setting BOOST_DIR and Boost_LIBRARYDIR, but I haven't been able to get it to work by tweaking these variables.

The most recent error message that I get is that it can't find the libraries, but it seems to indicate that it is using "/usr/local/include" for the include path, which isn't correct (and I can't seem to fix it). Is there a solution for this off the top of their head, or do I need to go mucking around inside CMake to figure it out?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
BD at Rivenhill
  • 12,395
  • 10
  • 46
  • 49
  • 4
    findBoost is hard when the underlying problem is easy, and impossible when the underlying problem is hard. CMake would be wise to add a `useBoost(1.55 /here/is/the/include/dir /here/is/the/lib/dir)` options which bypasses all this fragile logic. – MSalters Jul 24 '17 at 08:51
  • https://stackoverflow.com/questions/49816206/cmake-find-package-specify-path – Sergei Krivonos Jul 31 '21 at 15:02

16 Answers16

48

You should have a look at FindBoost.cmake script, which handles Boost detection and setting up all Boost variables. It typically resides in /usr/share/cmake-2.6/Modules/. In it, you will find documentation. For instance:

# These last three variables are available also as environment variables:
#
#   BOOST_ROOT or BOOSTROOT      The preferred installation prefix for searching for
#                                Boost.  Set this if the module has problems finding
#                                the proper Boost installation.
#

In contrast to BOOST_ROOT, the variables you are referring to are actually variables that are set by the FindBoost module. Note that you don't have to (and probably also don't want to) edit your CMake project configuration to set BOOST_ROOT. Instead, you should use the environment variable, e.g. calling

# BOOST_ROOT=/usr/local/... ccmake .

jonnew
  • 194
  • 1
  • 3
  • 12
ypnos
  • 50,202
  • 14
  • 95
  • 141
  • 1
    if you install in /usr/local/boost, shouldn't BOOST_ROOT be /usr/local/boost? If that works but fails for the libs (as they are not under /usr/local/boost the way you describe it), try to make a symlink /usr/local/boost/libs -> /usr/local/lib/boost – ypnos Jun 10 '10 at 21:31
  • I typed in an incorrect path to the include files in the first sentence, now fixed. – BD at Rivenhill Jul 03 '10 at 16:26
  • autotools and make exist in versions that run on Windows using Cygwin AFAIK, but it is difficult to use those. I think that effort spent on developing a new system like CMake that everyone would then need to learn how to use in addition to autotools would be better spent making the current tools easier to use. – BD at Rivenhill Nov 11 '11 at 21:33
  • 3
    The *easiest* way which worked for me is to do set( BOOST_ROOT .../myPath/... ) within the CMakeLists.txt – Lars Hadidi Jun 11 '15 at 12:51
  • @jmendeth How about qmake? It's also crossplatform (at least I've built the same program for Win, Linux and MacOS) and seems to have less magic going on than with CMake. IMHO, qmake is easier to learn. The downside is it's tied to Qt. – Paulo Carvalho Sep 22 '16 at 19:16
  • The great thing about standardized packages is that there are so many to choose from. The truth is that is used to be a breeze to compile mysql from source; now it's a multi-day nightmare. – Danial Dec 20 '16 at 23:07
45

I was finally able to get what I wanted with

cmake -DCMAKE_INSTALL_PREFIX=$TARGET \
    -DBoost_NO_BOOST_CMAKE=TRUE \
    -DBoost_NO_SYSTEM_PATHS=TRUE \
    -DBOOST_ROOT:PATHNAME=$TARGET \
    -DBoost_LIBRARY_DIRS:FILEPATH=${TARGET}/lib
ϹοδεMεδιϲ
  • 2,790
  • 3
  • 33
  • 54
Damien Kick
  • 611
  • 5
  • 5
31

The short version

You only need BOOST_ROOT, but you're going to want to disable searching the system for your local Boost if you have multiple installations or cross-compiling for iOS or Android. In which case add Boost_NO_SYSTEM_PATHS is set to false.

set( BOOST_ROOT "" CACHE PATH "Boost library path" )
set( Boost_NO_SYSTEM_PATHS on CACHE BOOL "Do not search system for Boost" )

Normally this is passed on the CMake command-line using the syntax -D<VAR>=value.

The longer version

Officially speaking the FindBoost page states these variables should be used to 'hint' the location of Boost.

This module reads hints about search locations from variables:

BOOST_ROOT             - Preferred installation prefix
 (or BOOSTROOT)
BOOST_INCLUDEDIR       - Preferred include directory e.g. <prefix>/include
BOOST_LIBRARYDIR       - Preferred library directory e.g. <prefix>/lib
Boost_NO_SYSTEM_PATHS  - Set to ON to disable searching in locations not
                         specified by these hint variables. Default is OFF.
Boost_ADDITIONAL_VERSIONS
                       - List of Boost versions not known to this module
                         (Boost install locations may contain the version)

This makes a theoretically correct incantation:

cmake -DBoost_NO_SYSTEM_PATHS=TRUE \
      -DBOOST_ROOT=/path/to/boost-dir

When you compile from source

include( ExternalProject )

set( boost_URL "http://sourceforge.net/projects/boost/files/boost/1.63.0/boost_1_63_0.tar.bz2" )
set( boost_SHA1 "9f1dd4fa364a3e3156a77dc17aa562ef06404ff6" )
set( boost_INSTALL ${CMAKE_CURRENT_BINARY_DIR}/third_party/boost )
set( boost_INCLUDE_DIR ${boost_INSTALL}/include )
set( boost_LIB_DIR ${boost_INSTALL}/lib )

ExternalProject_Add( boost
        PREFIX boost
        URL ${boost_URL}
        URL_HASH SHA1=${boost_SHA1}
        BUILD_IN_SOURCE 1
        CONFIGURE_COMMAND
        ./bootstrap.sh
        --with-libraries=filesystem
        --with-libraries=system
        --with-libraries=date_time
        --prefix=<INSTALL_DIR>
        BUILD_COMMAND
        ./b2 install link=static variant=release threading=multi runtime-link=static
        INSTALL_COMMAND ""
        INSTALL_DIR ${boost_INSTALL} )

set( Boost_LIBRARIES
        ${boost_LIB_DIR}/libboost_filesystem.a
        ${boost_LIB_DIR}/libboost_system.a
        ${boost_LIB_DIR}/libboost_date_time.a )
message( STATUS "Boost static libs: " ${Boost_LIBRARIES} )

Then when you call this script you'll need to include the boost.cmake script (mine is in the a subdirectory), include the headers, indicate the dependency, and link the libraries.

include( boost )
include_directories( ${boost_INCLUDE_DIR} )
add_dependencies( MyProject boost )
target_link_libraries( MyProject
                       ${Boost_LIBRARIES} )
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Cameron Lowell Palmer
  • 21,528
  • 7
  • 125
  • 126
19

I had a similar issue, CMake finding a vendor-installed Boost only, but my cluster had a locally installed version which is what I wanted it to use. Red Hat Linux 6.

Anyway, it looks like all the BOOSTROOT, BOOST_ROOT, and Boost_DIR stuff would get annoyed unless one also sets Boost_NO_BOOST_CMAKE (e.g add to cmd line -DBoost_NO_BOOST_CMAKE=TRUE).

(I will concede the usefulness of CMake for multiplatform, but I can still hate it.)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user1795638
  • 191
  • 1
  • 2
  • 12
    CMake itself is not so bad at all, and getting better with time. But the findBoost and findPython modules are clearly written by the guy who hates the world. – Slava Sep 21 '16 at 14:02
  • it was necessary for me too (Ubuntu Linux) – Alkor Jul 03 '20 at 19:43
16

Generally the most common mistake is not cleaning your build directory after adding new options. I have Boost installed from system packet manager. Its version is 1.49.

I also downloaded Boost 1.53 and "installed" it under $HOME/installs.

The only thing that I had to do in my project was to (I keep sources in my_project_directory/src):

cd my_project_directory
mkdir build
cd build
cmake -DCMAKE_INCLUDE_PATH=$HOME/installs/include -DCMAKE_LIBRARY_PATH=$HOME/installs/lib ../src

And that's it. Ta bum tss.

But if I'd make after cd build -> cmake ../src it would set Boost from the system path. Then doing cmake -DCMAKE_INCLUDE_PATH=$HOME/installs/include -DCMAKE_LIBRARY_PATH=$HOME/installs/lib ../src would change nothing.

You have to clean your build directory ( cd build && rm -rf * ;) )

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
jaor
  • 831
  • 7
  • 18
  • When I try that I get "Manually-specified variables were not used by the project: CMAKE_INCLUDE_PATH CMAKE_LIBRARY_PATH" – David Doria Apr 24 '15 at 19:32
  • What version of boost and cmake? – jaor Apr 25 '15 at 11:10
  • CMake 3.2.2 and Boost 1.55 – David Doria Apr 27 '15 at 11:35
  • Do not use the variables I mentioned. It should be sufficient to use BOOST_ROOT/BOOST_INCLUDEDIR/BOOST_LIBRARYDIR with Boost_NO_SYSTEM_PATHS set to ON. – jaor Apr 28 '15 at 07:44
  • 1
    When I do -DBoost_NO_SYSTEM_PATHS=ON -DBOOST_ROOT=/home/doriad/bin/boost_1.55.0/ in a fresh build directory, I get compiler errors showing that /usr/include/boost headers are still being used. – David Doria Apr 28 '15 at 18:17
  • Ah, sorry, find_package was returning BOOST_ROOT=FALSE because I was searching for a header-only library of boost. – David Doria Apr 28 '15 at 18:46
15

I had a similar issue, and I could use customized Boost libraries by adding the below lines to my CMakeLists.txt file:

set(Boost_NO_SYSTEM_PATHS TRUE)
if (Boost_NO_SYSTEM_PATHS)
  set(BOOST_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../3p/boost")
  set(BOOST_INCLUDE_DIRS "${BOOST_ROOT}/include")
  set(BOOST_LIBRARY_DIRS "${BOOST_ROOT}/lib")
endif (Boost_NO_SYSTEM_PATHS)
find_package(Boost REQUIRED regex date_time system filesystem thread graph program_options)
include_directories(${BOOST_INCLUDE_DIRS})
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
hungptit
  • 1,414
  • 15
  • 16
  • 1
    Hi, I followed your tips, and I got an error `Could not find module FindBOOST.cmake or a configuration file for package BOOST.` How to handle it ? – just_rookie Mar 28 '16 at 11:42
  • @just_rookie I think you can fix this issue by having a local cmake then use it to compile both customized Boost libraries and your code. – hungptit Apr 04 '16 at 14:12
12

There is a generic method to give CMake directions about where to find libraries.

When looking for a library, CMake looks first in the following variables:

  • CMAKE_LIBRARY_PATH and LD_LIBRARY_PATH for libraries
  • CMAKE_INCLUDE_PATH and INCLUDE_PATH for includes

If you declare your Boost files in one of the environment variables, CMake will find it. Example:

export CMAKE_LIBRARY_PATH="/stuff/lib.boost.1.52/lib:$CMAKE_LIBRARY_PATH"
export CMAKE_INCLUDE_PATH="/stuff/lib.boost.1.52/include:$CMAKE_INCLUDE_PATH"

If it's too cumbersome, you can also use a nice installing tool I wrote that will do everything for you: C++ version manager

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Offirmo
  • 18,962
  • 12
  • 76
  • 97
3

After digging around in CMake and experimenting, I determined that CMake was unhappy with the fact that all of my Boost libraries were contained in /usr/local/lib/boost and not /usr/local/lib. Once I soft-linked them back out, the build worked.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
BD at Rivenhill
  • 12,395
  • 10
  • 46
  • 49
3

Try this flag: -DBoost_NO_BOOST_CMAKE=TRUE. After hours of trying and fixing, only adding this flag worked for me.

What I ran was:

mkdir build && cd build
cmake .. -DBoost_NO_BOOST_CMAKE=TRUE
xmantas
  • 578
  • 5
  • 11
  • This helped me, I succeed by using `cmake -DBoost_NO_BOOST_CMAKE=TRUE -DBOOST_ROOT=/work/boost_1_75_0 ..` – Matt Apr 10 '23 at 20:24
2

I spent most of my evening trying to get this working. I tried all of the -DBOOST_* &c. directives with CMake, but it kept linking to my system Boost libraries, even after clearing and re-configuring my build area repeatedly.

At the end I modified the generated Makefile and voided the cmake_check_build_system target to do nothing (like 'echo ""') so that it wouldn't overwrite my changes when I ran make, and then did 'grep -rl "lboost_python" * | xargs sed -i "s:-lboost_python:-L/opt/sw/gcc5/usr/lib/ -lboost_python:g' in my build/ directory to explicitly point all the build commands to the Boost installation I wanted to use. Finally, that worked.

I acknowledge that it is an ugly kludge, but I am just putting it out here for the benefit of those who come up against the same brick wall, and just want to work around it and get work done.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Doug S.
  • 31
  • 3
2

In CMake, you can add the following to your CMakelists:

# install boost by apt-get method
include_directories(BEFORE SYSTEM "/usr/include") 

#  or install by building from src
# include_directories(BEFORE SYSTEM "/usr/local/include") 

This method saved my serveral months. you can try it. By the way, as a temporary solution, you can rename directories you don't expect to find as below:

sudo mv /usr/local/include/boost /usr/local/include/boost_bak

Hopefully, it will help people who are in deep trouble like me.

Kevin Chou
  • 489
  • 5
  • 8
1

I also encountered the same problem, but trying the hints here didn't help, unfortunately.

The only thing that helped was to download the newest version from the Boost page, compile and install it as described in Installing Boost 1.50 on Ubuntu 12.10.

In my case I worked with Boost 1.53.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Samsky
  • 438
  • 5
  • 11
1

I ran into a similar problem on a Linux server, where two versions of Boost have been installed. One is the precompiled 1.53.0 version which counts as old in 2018; it's in /usr/include and /usr/lib64. The version I want to use is 1.67.0, as a minimum version of 1.65.1 is required for another C++ library I'm installing; it's in /opt/boost, which has include and lib subdirectories. As suggested in previous answers, I set variables in CMakeLists.txt to specify where to look for Boost 1.67.0 as follows

include_directories(/opt/boost/include/)
include_directories(/opt/boost/lib/)
set(BOOST_ROOT /opt/boost/)
set(BOOST_INCLUDEDIR /opt/boost/include/)
set(BOOST_LIBRARYDIR /opt/boost/lib)
set(Boost_NO_SYSTEM_PATHS TRUE)
set(Boost_NO_BOOST_CMAKE TRUE)

But CMake doesn't honor those changes. Then I found an article online: CMake can use a local Boost, and realized that I need to change the variables in CMakeCache.txt. There I found that the Boost-related variables are still pointing to the default Boost 1.53.0, so no wonder CMake doesn't honor my changes in CMakeLists.txt. Then I set the Boost-related variables in CMakeCache.txt

Boost_DIR:PATH=Boost_DIR-NOTFOUND
Boost_INCLUDE_DIR:PATH=/opt/boost/include/
Boost_LIBRARY_DIR_DEBUG:PATH=/opt/boost/lib
Boost_LIBRARY_DIR_RELEASE:PATH=/opt/boost/lib

I also changed the variables pointing to the non-header, compiled parts of the Boost library to point to the version I want. Then CMake successfully built the library that depends on a recent version of Boost.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lambda Moses
  • 433
  • 5
  • 14
0

While configure could find my Boost installation, CMake could not.

Locate FindBoost.cmake and look for LIBRARY_HINTS to see what sub-packages it is looking for. In my case it wanted the MPI and graph libraries.

 # Compute component-specific hints.
  set(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT "")
  if(${COMPONENT} STREQUAL "mpi" OR ${COMPONENT} STREQUAL "mpi_python" OR
     ${COMPONENT} STREQUAL "graph_parallel")
    foreach(lib ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES})
      if(IS_ABSOLUTE "${lib}")
        get_filename_component(libdir "${lib}" PATH)
        string(REPLACE "\\" "/" libdir "${libdir}")
        list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT ${libdir})
      endif()
    endforeach()
  endif()

apt-cache search ... I installed the dev packages since I was building code, and the dev package drags in all the dependencies. I'm not so sure that a standard Boost install needs Open MPI, but this is OK for now.

sudo apt-get install libboost-mpi-dev libboost-mpi-python-dev
sudo apt-get install libboost-graph-parallel-dev
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rickfoosusa
  • 1,061
  • 19
  • 26
0

I just added the environment variable Boost_INCLUDE_DIR or add it to the cmake command -DBoost_INCLUDE_DIR and point to the include folder.

Ahmed Tawfik
  • 363
  • 4
  • 13
0

I had the same problem. My approach was to define which version to use (if any) via an environment variable:

# Use speficic version if BOOST_VER environment variable is defined
if(NOT "$ENV{BOOST_VER}" STREQUAL "")
    find_package (Boost "$ENV{BOOST_VER}" EXACT COMPONENTS system unit_test_framework log log_setup filesystem thread REQUIRED)
else()
    # Use default version
    find_package (Boost COMPONENTS system unit_test_framework log log_setup filesystem thread REQUIRED)
endif()