139

What should my CMake file look like for linking my program with the Boost library under Ubuntu?

The errors shown during running make:

main.cpp:(.text+0x3b): undefined reference to `boost::program_options::options_description::m_default_line_length'

The main file is really simple:

#include <boost/program_options/options_description.hpp>
#include <boost/program_options/option.hpp>
using namespace std;
#include <iostream>

namespace po = boost::program_options;

int main(int argc, char** argv) {

    po::options_description desc("Allowed options");
    desc.add_options()
        ("help", "produce help message")
        ;

    return 0;
}

I've managed to do that. The only lines that I've added to my CMake files were:

target_link_libraries(
my_target_file
${Boost_PROGRAM_OPTIONS_LIBRARY}
)
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Szymon Lipiński
  • 27,098
  • 17
  • 75
  • 77

6 Answers6

169

In CMake you could use find_package to find libraries you need. There usually is a FindBoost.cmake along with your CMake installation.

As far as I remember, it will be installed to /usr/share/cmake/Modules/ along with other find-scripts for common libraries. You could just check the documentation in that file for more information about how it works.

An example out of my head:

FIND_PACKAGE( Boost 1.40 COMPONENTS program_options REQUIRED )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )

ADD_EXECUTABLE( anyExecutable myMain.cpp )

TARGET_LINK_LIBRARIES( anyExecutable LINK_PUBLIC ${Boost_LIBRARIES} )

I hope this code helps.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MOnsDaR
  • 8,401
  • 8
  • 49
  • 70
  • 2
    Added a working link from Kitwares Github repo. Also added a link to the official documentation about FindBoost.cmake – MOnsDaR Jun 09 '14 at 19:34
  • 1
    Why Boost 1.40 in particular? When did the base functionalities of the library stopped changing? – jgyou Dec 22 '15 at 21:56
  • 8
    Because why not? It's just an example... Fill in whatever suits you best – MOnsDaR Feb 04 '16 at 07:45
  • 7
    An important detail is to place `target_link_libraries` **after** the `add_executable` **and** `find_package` lines, so all linked components are known. – Murphy Dec 21 '16 at 12:36
  • 9
    **This answer is inappropriate for new code. [oLen](https://stackoverflow.com/a/43885372/2137996)'s answer should be preferred** – Alex Reinking Aug 16 '21 at 12:47
61

Adapting @MOnsDaR answer for modern CMake syntax with imported targets, this would be:

find_package(Boost 1.40 COMPONENTS program_options REQUIRED)

add_executable(anyExecutable myMain.cpp)

target_link_libraries(anyExecutable Boost::program_options)

Note that it is not necessary to specify the include directories manually, since it is already taken care of through the imported target Boost::program_options.

oLen
  • 5,177
  • 1
  • 32
  • 48
  • 1
    The downside to this target approach is if your Boost version is newer than your CMake version, this will probably fail. `The FindBoost.cmake` originally builds these only if it explicitly lists your Boost version. At some point this was supposed to be improved, but I'm still seeing failures with CMake 3.10.2 and Boost 1.66 (newest copies from brew). – Henry Schreiner Feb 23 '18 at 11:36
  • 16
    stackoverflow starts failing because there are so many outdated answers that often it is hard to find the right answer (this one). – Carlo Wood Dec 09 '19 at 00:13
  • @HenrySchreiner helpful comment! It helps me understanding why my cmake/conan/boost/g++ version mix is not linking correctly. Is there a way to determine compatible versions for Boost and CMake? – WaterFox Jun 14 '22 at 22:41
  • They've actually really improved this - CMake will now assume the most recent Boost's targets extend to the current one if you mismatch. Also it will use the Boost's CMake module if it provides one, which newer ones do if they used CMake. Best source I think is checking the CMake FindBoost source - starting at https://gitlab.kitware.com/cmake/cmake/-/blob/master/Modules/FindBoost.cmake#L1014 . – Henry Schreiner Jun 21 '22 at 02:49
56

The following is my configuration:

cmake_minimum_required(VERSION 2.8)
set(Boost_INCLUDE_DIR /usr/local/src/boost_1_46_1)
set(Boost_LIBRARY_DIR /usr/local/src/boost_1_46_1/stage/lib)
find_package(Boost COMPONENTS system filesystem REQUIRED)
include_directories(${Boost_INCLUDE_DIR})
link_directories(${Boost_LIBRARY_DIR})

add_executable(main main.cpp)
target_link_libraries( main ${Boost_LIBRARIES} )
Dean Chen
  • 3,800
  • 8
  • 45
  • 70
7

Two ways, using system default install path, usually /usr/lib/x86_64-linux-gnu/:

find_package(Boost REQUIRED regex date_time system filesystem thread graph)
include_directories(${BOOST_INCLUDE_DIRS})
message("boost lib: ${Boost_LIBRARIES}")
message("boost inc:${Boost_INCLUDE_DIR}")

add_executable(use_boost use_boost.cpp)
target_link_libraries(use_boost
        ${Boost_LIBRARIES}
        )

If you install Boost in a local directory or choose local install instead of system install, you can do it by this:

set( BOOST_ROOT "/home/xy/boost_install/lib/" CACHE PATH "Boost library path" )
set( Boost_NO_SYSTEM_PATHS on CACHE BOOL "Do not search system for Boost" )

find_package(Boost REQUIRED regex date_time system filesystem thread graph)
include_directories(${BOOST_INCLUDE_DIRS})
message("boost lib: ${Boost_LIBRARIES}, inc:${Boost_INCLUDE_DIR}")

add_executable(use_boost use_boost.cpp)
target_link_libraries(use_boost
        ${Boost_LIBRARIES}
        )

Note the above dir /home/xy/boost_install/lib/ is where I install Boost:

xy@xy:~/boost_install/lib$ ll -th
total 16K
drwxrwxr-x 2 xy xy 4.0K May 28 19:23 lib/
drwxrwxr-x 3 xy xy 4.0K May 28 19:22 include/

xy@xy:~/boost_install/lib$ ll -th lib/
total 57M
drwxrwxr-x 2 xy xy 4.0K May 28 19:23 ./
-rw-rw-r-- 1 xy xy 2.3M May 28 19:23 libboost_test_exec_monitor.a
-rw-rw-r-- 1 xy xy 2.2M May 28 19:23 libboost_unit_test_framework.a
.......

xy@xy:~/boost_install/lib$ ll -th include/
total 20K
drwxrwxr-x 110 xy xy  12K May 28 19:22 boost/

If you are interested in how to use a local installed Boost, you can see this question How can I get CMake to find my alternative Boost installation?.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jayhello
  • 5,931
  • 3
  • 49
  • 56
4

Here is my take:

cmake_minimum_required(VERSION 3.15)

project(TryOuts LANGUAGES CXX)

find_package(Boost QUIET REQUIRED COMPONENTS program_options)

if(NOT Boost_FOUND)
    message(FATAL_ERROR "Boost Not found")
endif()

add_executable(helloworld main.cpp)

target_link_libraries(helloworld PUBLIC Boost::program_options)
  • target_link_libraries(helloworld PUBLIC Boost::program_options) will give a CMAKE error: -- Configuring done CMake Error at CMakeLists.txt:102 (add_executable): Target "DB32" links to target "Boost::program_options" but the target was not found. Perhaps a find_package() call is missing for an IMPORTED target, or an ALIAS target is missing? – munsingh Jul 09 '20 at 06:17
  • Hi, thanks for the feedback. It seems like the CMake can't locate Boost on your system. Maybe you better to make a fresh build of the Boost from the source. Before that you might want to try the following: Find the package with `find_package(Boost QUIET REQUIRED)` and link to your target (DB32): `target_link_libraries(DB32 PUBLIC Boost::headers)` –  Jul 09 '20 at 15:11
  • Because you put `REQUIRED`, `NOT Boost_FOUND` is never true, so that whole `if` statement is pointless. – Alex Reinking Aug 16 '21 at 12:47
1

Which Boost library? Many of them are pure templates and do not require linking.

Now with that actually shown concrete example which tells us that you want Boost program options (and even more told us that you are on Ubuntu), you need to do two things:

  1. Install libboost-program-options-dev so that you can link against it.
  2. Tell cmake to link against libboost_program_options.

I mostly use Makefiles so here is the direct command-line use:

$ g++ boost_program_options_ex1.cpp -o bpo_ex1 -lboost_program_options
$ ./bpo_ex1
$ ./bpo_ex1 -h
$ ./bpo_ex1 --help
$ ./bpo_ex1 -help
$

It doesn't do a lot it seems.

For CMake, you need to add boost_program_options to the list of libraries, and IIRC this is done via SET(liblist boost_program_options) in your CMakeLists.txt.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • 16
    Your CMake advice is wrong (see the accepted answer), and your commandline advice not very helpful as the question was about CMake. – Ela782 May 06 '14 at 09:29