Search code examples
c++linuxboostcmakevcpkg

How to add boost sub-library (not header-only) to project with VCPKG and CMake on Linux?


I'm trying to install boost-program-options (not header-only) on Linux with VCPKG. Unfortunately it is not working. I tried to do its on separate environment, because of that I've created docker instance:

$ docker run -it --rm --network=host -v $(pwd):/home/ --workdir /home --name='ubuntu_test' ubuntu:22.04
# apt-get update && apt-get upgrade -y --no-install-recommends
# apt-get install g++ git cmake curl zip unzip tar ca-certificates make --no-install-recommends  -y

Then I've downloaded and built vcpkg:

# git clone https://github.com/Microsoft/vcpkg.git --depth=1
# ./vcpkg/bootstrap-vcpkg.sh

The next step was to install boost-program-options with vcpkg, so I used commend:

# ./vcpkg/vcpkg install boost-program-options

after succesfull installation I saw output:

    find_package(Boost REQUIRED [COMPONENTS <libs>...])
    target_link_libraries(main PRIVATE Boost::boost Boost::<lib1> Boost::<lib2> ...)

Then I tried to get CMake argument by caling:

# ./vcpkg/vcpkg integrate install
Applied user-wide integration for this vcpkg root.
CMake projects should use: "-DCMAKE_TOOLCHAIN_FILE=/home/vcpkg/scripts/buildsystems/vcpkg.cmake"

Then I use simplest CMakeLists.txt (took from official vcpkg tutorial modified as suggested by vcpkg):

cmake_minimum_required(VERSION 3.16)
project(Learning_VCPKG LANGUAGES CXX)

find_package(Boost REQUIRED COMPONENTS program-options)

if (Boost_FOUND)
    message("Boost found: ${Boost_INCLUDE_DIRS} and ${Boost_LIBRARY_DIRS}")
    include_directories(${Boost_INCLUDE_DIRS})
    link_directories(${Boost_LIBRARY_DIRS})
endif ()

add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES})

When I try to generate project I see 2 warnings and 1 error:

# cmake . -DCMAKE_TOOLCHAIN_FILE=/home/vcpkg/scripts/buildsystems/vcpkg.cmake
-- The CXX compiler identification is GNU 11.3.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Warning at /usr/share/cmake-3.22/Modules/FindBoost.cmake:1369 (message):
  New Boost version may have incorrect or missing dependencies and imported
  targets
Call Stack (most recent call first):
  /usr/share/cmake-3.22/Modules/FindBoost.cmake:1492 (_Boost_COMPONENT_DEPENDENCIES)
  /usr/share/cmake-3.22/Modules/FindBoost.cmake:2102 (_Boost_MISSING_DEPENDENCIES)
  vcpkg/installed/x64-linux/share/boost/vcpkg-cmake-wrapper.cmake:11 (_find_package)
  vcpkg/scripts/buildsystems/vcpkg.cmake:809 (include)
  CMakeLists.txt:4 (find_package)


CMake Warning at /usr/share/cmake-3.22/Modules/FindBoost.cmake:2201 (message):
  No header defined for program-options; skipping header check (note:
  header-only libraries have no designated component)
Call Stack (most recent call first):
  vcpkg/installed/x64-linux/share/boost/vcpkg-cmake-wrapper.cmake:11 (_find_package)
  vcpkg/scripts/buildsystems/vcpkg.cmake:809 (include)
  CMakeLists.txt:4 (find_package)


CMake Error at /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:230 (message):
  Could NOT find Boost (missing: program-options) (found version "1.82.0")
Call Stack (most recent call first):
  /usr/share/cmake-3.22/Modules/FindPackageHandleStandardArgs.cmake:594 (_FPHSA_FAILURE_MESSAGE)
  /usr/share/cmake-3.22/Modules/FindBoost.cmake:2360 (find_package_handle_standard_args)
  vcpkg/installed/x64-linux/share/boost/vcpkg-cmake-wrapper.cmake:11 (_find_package)
  vcpkg/scripts/buildsystems/vcpkg.cmake:809 (include)
  CMakeLists.txt:4 (find_package)


-- Configuring incomplete, errors occurred!
See also "/home/CMakeFiles/CMakeOutput.log".

Next step which I made was to check if boost was really installed:

./vcpkg/vcpkg list | grep boost-program
boost-program-options:x64-linux                   1.82.0#2            Boost program_options module

After that I started to find solution on Internet:

  1. Using static Boost libraries with vcpkg and CMake I've tried to add manually include directory: set(Boost_INCLUDE_DIR ${_VCPKG_INSTALLED_DIR}/vcpkg/installed/x64-linux/include/) unfortunately output is the same as above. I've also tried to add:
set(Boost_USE_STATIC_LIBS        ON)  # only find static libs
set(Boost_USE_DEBUG_LIBS        OFF)  # ignore debug libs and
set(Boost_USE_RELEASE_LIBS       ON)  # only find release libs
set(Boost_USE_MULTITHREADED      ON)
set(Boost_USE_STATIC_RUNTIME     ON)  # link Boost Static libraries

But result is still the same.

  1. Here is information about triplet for Windows: Installing boost via vcpkg, I get the wrong toolset - so it is not answer.

  2. Unable to find Boost libraries with CMake and vcpkg - there were important information, if I change: find_package(Boost COMPONENTS program-options REQUIRED) -> find_package(Boost REQUIRED) it is generating configuration, but unfortunately not linking program (in the question it is boost-variant, which is header-only, but I'm using not header-only)

I can then do its "manually" by changing: target_link_libraries(${PROJECT_NAME} ${Boost_LIBRARIES}) -> target_link_libraries(${PROJECT_NAME} -L${Boost_LIBRARY_DIRS} -lboost_program_options) then program compile & links, but it is dirty hack.

So final, working CMakeLists.txt is:

cmake_minimum_required(VERSION 3.16)
project(Learning_VCPKG LANGUAGES CXX)

find_package(Boost REQUIRED)

if (Boost_FOUND)
    message("Boost found: ${Boost_INCLUDE_DIRS} and ${Boost_LIBRARY_DIRS}")
    include_directories(${Boost_INCLUDE_DIRS})
    link_directories(${Boost_LIBRARY_DIRS})
endif ()

add_executable(${PROJECT_NAME} main.cpp)

target_link_libraries(${PROJECT_NAME} -lboost_program_options)

But I'm sure that there is more proffesional way of adding boost not header-only sublibrary to project with vcpkg on Linux. Especially because boost is one of most popular C++ libraries.


Solution

  • To get rid of the warnings:
    set Boost_NO_WARN_NEW_VERSIONS (if you use at least cmake 3.20) to true

    To use Boost::program_options:

    find_package(Boost COMPONENTS program_options REQUIRED)
    target_link_libraries(<your_target> PRIVATE Boost::program_options)
    

    So what did you do wrong?
    Very simple, you misspelled it: program_options != program-options